CSProj creation now optional; other nits.

This commit is contained in:
Varad Meru [gmail] 2020-10-21 16:05:39 -07:00
Родитель 4328e86b59
Коммит ea87381171
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: D65E2959EB74910D
15 изменённых файлов: 260 добавлений и 66 удалений

27
.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/AutoRest.CSharp.V3/bin/Debug/netcoreapp3.0/AutoRest.CSharp.V3.dll",
"args": [],
"cwd": "${workspaceFolder}/src/AutoRest.CSharp.V3",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

42
.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/src/AutoRest.CSharp.V3/AutoRest.CSharp.V3.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/src/AutoRest.CSharp.V3/AutoRest.CSharp.V3.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/src/AutoRest.CSharp.V3/AutoRest.CSharp.V3.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"folders": [
{
"path": "."
},
{
"path": "."
}
]
}

Просмотреть файл

@ -31,7 +31,27 @@
<ItemGroup>
<Folder Include="Generation\Static\" />
<Folder Include="StaticResources\" />
<Folder Include="StaticResources\" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<None Update="StaticResources\AutorestGenerated.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticResources\GitIgnoreTemplateFile.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticResources\HostJSONTemplate.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticResources\TemplateCSProj.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticResources\VSCodeExtensions.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="StaticResources\LocalSettingsJSONTemplate.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Просмотреть файл

@ -52,7 +52,7 @@ namespace AutoRest.CSharp.V3.AutoRest.Plugins
var LocalSettingsJSONTemplate = File.ReadAllText(@"StaticResources/LocalSettingsJSONTemplate.json");
var VSCodeExtensions = File.ReadAllText(@"StaticResources/VSCodeExtensions.json");
var HostJSONTemplate = File.ReadAllText(@"StaticResources/HostJSONTemplate.json");
var AutorestGeneratedJSONTemplate = File.ReadAllText(@"StaticResources/AutorestGeneratedJSONTemplate.json");
var AutorestGeneratedJSONTemplate = File.ReadAllText(@"StaticResources/AutorestGenerated.json");
project.AddGeneratedFile(".gitignore", GitIgnoreTemplateFile);
project.AddGeneratedFile(".vscode/extensions.json", VSCodeExtensions);

Просмотреть файл

@ -200,10 +200,9 @@ namespace AutoRest.CSharp.V3.Generation.Writers
foreach (var initializer in constructor.Initializers)
{
writer.Append($"{initializer.Property.Declaration.Name} = ")
.WriteConversion(initializer.Value.Type, initializer.Property.Declaration.Type, w=>w.WriteReferenceOrConstant(initializer.Value));
.WriteConversion(initializer.Value.Type, initializer.Property.Declaration.Type, w => w.WriteReferenceOrConstant(initializer.Value));
if (initializer.DefaultValue != null &&
!initializer.Value.Type.IsValueType)
if (initializer.DefaultValue != null && (!initializer.Value.Type.IsValueType || initializer.Value.Type.IsNullable))
{
writer.Append($"?? ").WriteReferenceOrConstant(initializer.DefaultValue.Value);
}
@ -227,7 +226,7 @@ namespace AutoRest.CSharp.V3.Generation.Writers
{
writer.WriteXmlDocumentationSummary(schema.Description);
using (writer.Scope($"public enum {schema.Declaration.Name}"))
using (writer.Scope($"{schema.Declaration.Accessibility} enum {schema.Declaration.Name}"))
{
foreach (EnumTypeValue value in schema.Values)
{
@ -275,14 +274,16 @@ namespace AutoRest.CSharp.V3.Generation.Writers
foreach (var choice in schema.Values)
{
writer.Line($"private const {schema.BaseType} {choice.Declaration.Name}Value = {choice.Value.Value:L};");
var fieldName = GetValueFieldName(name, choice.Declaration.Name, schema.Values);
writer.Line($"private const {schema.BaseType} {fieldName} = {choice.Value.Value:L};");
}
writer.Line();
foreach (var choice in schema.Values)
{
writer.WriteXmlDocumentationSummary(choice.Description);
writer.Append($"public static {cs} {choice.Declaration.Name}").AppendRaw("{ get; }").Append($" = new {cs}({choice.Declaration.Name}Value);").Line();
var fieldName = GetValueFieldName(name, choice.Declaration.Name, schema.Values);
writer.Append($"public static {cs} {choice.Declaration.Name}").AppendRaw("{ get; }").Append($" = new {cs}({fieldName});").Line();
}
writer.WriteXmlDocumentationSummary($"Determines if two <see cref=\"{name}\"/> values are the same.");
@ -338,6 +339,24 @@ namespace AutoRest.CSharp.V3.Generation.Writers
}
}
private string GetValueFieldName(string enumName, string enumValue, IList<EnumTypeValue> enumValues)
{
if (enumName != $"{enumValue}Value")
{
return $"{enumValue}Value";
}
int index = 1;
foreach (var value in enumValues)
{
if (value.Declaration.Name == $"{enumValue}Value{index}")
{
index++;
}
}
return $"{enumValue}Value{index}";
}
private void WriteEditorBrowsableFalse(CodeWriter writer)
{
writer.Line($"[{typeof(EditorBrowsableAttribute)}({typeof(EditorBrowsableState)}.{nameof(EditorBrowsableState.Never)})]");

Просмотреть файл

@ -64,8 +64,24 @@ namespace AutoRest.CSharp.V3.Input
internal partial class DictionaryOfAny
{
private static char[] _formatSplitChar = new[] {',', ' '};
public string? Accessibility => TryGetValue("x-accessibility", out object? value) ? value?.ToString() : null;
public string? Namespace => TryGetValue("x-namespace", out object? value) ? value?.ToString() : null;
public string? Usage => TryGetValue("x-csharp-usage", out object? value) ? value?.ToString() : null;
public string[] Formats
{
get
{
if (TryGetValue("x-csharp-formats", out object? value) && value?.ToString() is string s)
{
return s.Split(_formatSplitChar, StringSplitOptions.RemoveEmptyEntries);
}
return Array.Empty<string>();
}
}
}
internal partial class ServiceResponse

50
src/AutoRest.CSharp.V3/Input/Generated/CodeModel.cs сгенерированный
Просмотреть файл

@ -143,7 +143,7 @@ namespace AutoRest.CSharp.V3.Input
public Language Default { get; set; } = new Language();
[YamlDotNet.Serialization.YamlMember(Alias = "csharp")]
public CSharpLanguage? CSharp { get; set; }
public Language? CSharp { get; set; }
[YamlDotNet.Serialization.YamlMember(Alias = "python")]
public Language? Python { get; set; }
@ -584,6 +584,9 @@ namespace AutoRest.CSharp.V3.Input
[YamlDotNet.Serialization.YamlMember(Alias = "wrapped")]
public bool? Wrapped { get; set; }
[YamlDotNet.Serialization.YamlMember(Alias = "text")]
public bool? Text { get; set; }
}
/// <summary>custom extensible metadata for individual serialization formats</summary>
@ -2294,7 +2297,7 @@ namespace AutoRest.CSharp.V3.Input
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.0.23.0 (Newtonsoft.Json v9.0.0.0)")]
internal partial class HttpMultiPartRequest : HttpWithBodyRequest
internal partial class HttpMultipartRequest : HttpWithBodyRequest
{
/// <summary>indicates that the HTTP Request should be a multipart request
///
@ -2303,47 +2306,6 @@ namespace AutoRest.CSharp.V3.Input
public bool? Multipart { get; set; }
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.0.23.0 (Newtonsoft.Json v9.0.0.0)")]
internal partial class HttpMultipartRequest
{
/// <summary>indicates that the HTTP Request should be a multipart request
///
/// ie, that it has multiple requests in a single request.</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "multipart")]
public bool? Multipart { get; set; } = true;
/// <summary>a normalized value for the media type (ie, distills down to a well-known moniker (ie, 'json'))</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "knownMediaType")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public KnownMediaType KnownMediaType { get; set; }
/// <summary>must contain at least one media type to send for the body</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "mediaTypes")]
[System.ComponentModel.DataAnnotations.Required]
public System.Collections.Generic.ICollection<string> MediaTypes { get; set; } = new System.Collections.ObjectModel.Collection<string>();
/// <summary>A relative path to an individual endpoint.
///
/// The field name MUST begin with a slash.
/// The path is appended (no relative URL resolution) to the expanded URL from the Server Object's url field in order to construct the full URL.
/// Path templating is allowed.
///
/// When matching URLs, concrete (non-templated) paths would be matched before their templated counterparts.</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "path")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string Path { get; set; }
/// <summary>the base URI template for the operation. This will be a template that has Uri parameters to craft the base url to use.</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "uri")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string Uri { get; set; }
/// <summary>the HTTP Method used to process this operation</summary>
[YamlDotNet.Serialization.YamlMember(Alias = "method")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public HttpMethod Method { get; set; }
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.0.23.0 (Newtonsoft.Json v9.0.0.0)")]
internal partial class HttpResponseHeader
{
@ -2822,4 +2784,4 @@ namespace AutoRest.CSharp.V3.Input
[System.Runtime.Serialization.EnumMember(Value = @"default")]
Default = 63,
}
}
}

Просмотреть файл

@ -12,6 +12,15 @@ namespace AutoRest.CSharp.V3.Input
public SchemaUsageProvider(CodeModel codeModel)
{
foreach (var objectSchema in codeModel.Schemas.Objects)
{
var usage = objectSchema?.Extensions?.Usage;
if (usage != null)
{
Apply(objectSchema, (SchemaTypeUsage) Enum.Parse(typeof(SchemaTypeUsage), usage, true));
}
}
foreach (var operationGroup in codeModel.OperationGroups)
{
foreach (var operation in operationGroup.Operations)
@ -26,24 +35,34 @@ namespace AutoRest.CSharp.V3.Input
Apply(operationResponse.ResponseSchema, SchemaTypeUsage.Error | SchemaTypeUsage.Output);
}
foreach (var parameter in operation.Parameters)
{
ApplyParameterSchema(parameter);
}
foreach (var serviceRequest in operation.Requests)
{
foreach (var parameter in serviceRequest.Parameters)
{
if (parameter.Flattened == true)
{
Apply(parameter.Schema, SchemaTypeUsage.FattenedParameters | SchemaTypeUsage.Input, recurse: false);
}
else
{
Apply(parameter.Schema, SchemaTypeUsage.Model | SchemaTypeUsage.Input);
}
ApplyParameterSchema(parameter);
}
}
}
}
}
private void ApplyParameterSchema(RequestParameter parameter)
{
if (parameter.Flattened == true)
{
Apply(parameter.Schema, SchemaTypeUsage.FattenedParameters | SchemaTypeUsage.Input, recurse: false);
}
else
{
Apply(parameter.Schema, SchemaTypeUsage.Model | SchemaTypeUsage.Input);
}
}
private void Apply(Schema? schema, SchemaTypeUsage usage, bool recurse = true)
{
if (schema == null)
@ -100,7 +119,7 @@ namespace AutoRest.CSharp.V3.Input
}
}
public SchemaTypeUsage GetUsage(ObjectSchema schema)
public SchemaTypeUsage GetUsage(Schema schema)
{
_usages.TryGetValue(schema, out var usage);
return usage;

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Azure.Core;
using Microsoft.CodeAnalysis;
@ -15,9 +16,13 @@ namespace AutoRest.CSharp.V3.Input.Source
private readonly INamedTypeSymbol? _existingType;
private SourceMemberMapping[] PropertyMappings { get; }
public ModelTypeMapping(INamedTypeSymbol memberAttribute, INamedTypeSymbol? existingType)
public string[]? Usage { get; }
public string[]? Formats { get; }
public ModelTypeMapping(INamedTypeSymbol modelAttribute, INamedTypeSymbol memberAttribute, INamedTypeSymbol? existingType)
{
_existingType = existingType;
List<SourceMemberMapping> memberMappings = new List<SourceMemberMapping>();
foreach (ISymbol member in GetMembers(existingType))
{
@ -28,6 +33,40 @@ namespace AutoRest.CSharp.V3.Input.Source
}
PropertyMappings = memberMappings.ToArray();
if (existingType != null)
{
foreach (var attributeData in existingType.GetAttributes())
{
if (SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, modelAttribute))
{
foreach (var namedArgument in attributeData.NamedArguments)
{
switch (namedArgument.Key)
{
case nameof(CodeGenModelAttribute.Usage):
Usage = ToStringArray(namedArgument.Value.Values);
break;
case nameof(CodeGenModelAttribute.Formats):
Formats = ToStringArray(namedArgument.Value.Values);
break;
}
}
}
}
}
}
private string[]? ToStringArray(ImmutableArray<TypedConstant> values)
{
if (values.IsDefaultOrEmpty)
{
return null;
}
return values
.Select(v => (string?) v.Value)
.OfType<string>()
.ToArray();
}
public SourceMemberMapping? GetForMember(string name)

Просмотреть файл

@ -14,14 +14,17 @@ namespace AutoRest.CSharp.V3.Input.Source
{
private readonly Compilation _compilation;
private readonly INamedTypeSymbol _clientAttribute;
private readonly INamedTypeSymbol _modelAttribute;
private readonly INamedTypeSymbol _schemaMemberNameAttribute;
private readonly Dictionary<string, INamedTypeSymbol> _nameMap = new Dictionary<string, INamedTypeSymbol>(StringComparer.OrdinalIgnoreCase);
public SourceInputModel(Compilation compilation)
{
_compilation = compilation;
_schemaMemberNameAttribute = compilation.GetTypeByMetadataName(typeof(CodeGenMemberAttribute).FullName!)!;
_clientAttribute = compilation.GetTypeByMetadataName(typeof(CodeGenTypeAttribute).FullName!)!;
_modelAttribute = compilation.GetTypeByMetadataName(typeof(CodeGenModelAttribute).FullName!)!;
IAssemblySymbol assembly = _compilation.Assembly;
@ -39,7 +42,7 @@ namespace AutoRest.CSharp.V3.Input.Source
public ModelTypeMapping CreateForModel(INamedTypeSymbol? symbol)
{
return new ModelTypeMapping(_schemaMemberNameAttribute, symbol);
return new ModelTypeMapping(_modelAttribute, _schemaMemberNameAttribute, symbol);
}
public INamedTypeSymbol? FindForType(string ns, string name)

Просмотреть файл

@ -42,7 +42,7 @@ namespace AutoRest.CSharp.V3.Output.Models.Shared
if (value != null && type.IsFrameworkType && value.GetType() != type.FrameworkType)
{
throw new InvalidOperationException("Constant type mismatch");
throw new InvalidOperationException($"Constant type mismatch. value: {value} | type.IsFrameworkType {type.IsFrameworkType} | {value.GetType()} != {type.FrameworkType}");
}
}

Просмотреть файл

@ -35,8 +35,18 @@ namespace AutoRest.CSharp.V3.Output.Models.Types
_choices = choices;
DefaultName = schema.CSharpName();
DefaultAccessibility = schema.Extensions?.Accessibility ?? "public";
DefaultNamespace = schema.Extensions?.Namespace ?? $"{_context.DefaultNamespace}.Models";
var usage = context.SchemaUsageProvider.GetUsage(schema);
var hasUsage = usage.HasFlag(SchemaTypeUsage.Model);
DefaultAccessibility = schema.Extensions?.Accessibility ?? (hasUsage ? "public" : "internal");
if (schema.Extensions?.Namespace is string namespaceExtension)
{
DefaultNamespace = namespaceExtension;
}
else
{
DefaultNamespace = context.DefaultNamespace;
}
if (ExistingType != null)
{

Просмотреть файл

@ -18,6 +18,19 @@ pipeline:
azure-functions-csharp/emitter:
input: azure-functions-csharp
scope: output-scope
output-scope:
output-artifact: source-file-csharp
```
``` yaml $(generate-metadata) == true
use-extension:
"@autorest/modelerfour": "4.15.414"
modelerfour:
always-create-content-type-parameter: true
flatten-models: true
flatten-payloads: true
group-parameters: true
pipeline:
azure-functions-csharpproj:
input: modelerfour/identity
azure-functions-csharpproj/emitter:

Просмотреть файл

@ -10,6 +10,20 @@ namespace Azure.Core
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct)]
internal class CodeGenModelAttribute : CodeGenTypeAttribute
{
/// <summary>
/// Gets or sets a coma separated list of additional model usage modes. Allowed values: model, error, intput, output.
/// </summary>
public string[]? Usage { get; set; }
/// <summary>
/// Gets or sets a coma separated list of additional model serialization formats.
/// </summary>
public string[]? Formats { get; set; }
public CodeGenModelAttribute() : base(null)
{
}
public CodeGenModelAttribute(string originalName): base(originalName)
{
}