diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Models/Types/MrwSerializationTypeProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Models/Types/MrwSerializationTypeProvider.cs index a6482de70e..440677fde0 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Models/Types/MrwSerializationTypeProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Models/Types/MrwSerializationTypeProvider.cs @@ -300,10 +300,7 @@ private List BuildSerializationConstructorParameters() foreach (var property in _inputModel.Properties) { - var parameter = new ParameterProvider(property) - { - Validation = ParameterValidationType.None, - }; + var parameter = new ParameterProvider(property); constructorParameters.Add(parameter); if (shouldAddRawDataField && string.Equals(parameter.Name, _rawDataField?.Name, StringComparison.OrdinalIgnoreCase)) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/SystemExtensibleSnippets.SystemModelSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/SystemExtensibleSnippets.SystemModelSnippets.cs index 7d841407a3..0da82862ba 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/SystemExtensibleSnippets.SystemModelSnippets.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/SystemExtensibleSnippets.SystemModelSnippets.cs @@ -15,16 +15,13 @@ internal class SystemModelSnippets : ModelSnippets public override MethodProvider BuildFromOperationResponseMethod(TypeProvider typeProvider, MethodSignatureModifiers modifiers) { var result = new ParameterProvider("response", $"The result to deserialize the model from.", typeof(PipelineResponse)); - return new MethodProvider - ( + return new MethodProvider( new MethodSignature(ClientModelPlugin.Instance.Configuration.ApiTypes.FromResponseName, null, $"Deserializes the model from a raw response.", modifiers, typeProvider.Type, null, new[] { result }), new MethodBodyStatement[] { Snippet.UsingVar("document", JsonDocumentSnippet.Parse(new PipelineResponseSnippet(result).Content), out var document), Snippet.Return(TypeProviderSnippet.Deserialize(typeProvider, document.RootElement)) - }, - "default" - ); + }); } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/CodeWriterBenchmark.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/CodeWriterBenchmark.cs index 5a3fd737db..7571e8c68a 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/CodeWriterBenchmark.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/CodeWriterBenchmark.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.IO; -using System.Reflection; using BenchmarkDotNet.Attributes; using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Providers; @@ -16,9 +14,6 @@ public class CodeWriterBenchmark public CodeWriterBenchmark() { - PluginHandler pluginHandler = new PluginHandler(); - pluginHandler.LoadPlugin(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location)!.FullName, "Projects", "Model")); - var properties = new[] { new InputModelProperty("MyProperty", "myProperty", "The property of mine", new InputPrimitiveType(InputPrimitiveTypeKind.Int32, false), true, false, false) @@ -28,6 +23,12 @@ public CodeWriterBenchmark() _writer = new TypeProviderWriter(modelProvider); } + [GlobalSetup] + public void GlobalSetup() + { + PluginInitializer.Initialize(); + } + [Benchmark] public void WriteModel() { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/MethodProviderBenchmark.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/MethodProviderBenchmark.cs new file mode 100644 index 0000000000..cda2a44f57 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/MethodProviderBenchmark.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using Microsoft.Generator.CSharp.Providers; +using Microsoft.Generator.CSharp.Statements; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.Perf +{ + public class MethodProviderBenchmark + { + private MethodSignature Signature { get; } + private MethodBodyStatement BodyStatement = new(); + private Dictionary>? ParamHash; + + public MethodProviderBenchmark() + { + var parameters = new List + { + new ParameterProvider("param1", $"param1", typeof(int)) { Validation = ParameterValidationType.None }, + new ParameterProvider("param2", $"param2", typeof(string)) { Validation = ParameterValidationType.AssertNotNull } + }; + Signature = new MethodSignature("name", null, null, MethodSignatureModifiers.Public, null, null, parameters); + ParamHash = GetParamhash(false); + } + + [GlobalSetup] + public void GlobalSetup() + { + PluginInitializer.Initialize(); + } + + [Benchmark] + [BenchmarkCategory("ValidationStatements")] + public void Yieldreturn() + { + List statements = [.. GetValidationStatementsWithYield()]; + statements.Add(BodyStatement); + } + + [Benchmark] + [BenchmarkCategory("ValidationStatements")] + public void UseList() + { + List statements = [.. GetValidationStatements()]; + statements.Add(BodyStatement); + } + + [Benchmark] + [BenchmarkCategory("ValidationStatements")] + public void UseSingleList() + { + MethodBodyStatement statements = GetStatementsAsSingleList(BodyStatement); + } + + [Benchmark] + [BenchmarkCategory("ValidationStatements")] + public void UseArray() + { + MethodBodyStatement statements = GetStatementsWithHash(BodyStatement, ParamHash); + } + + private Dictionary>? GetParamhash(bool skipParamValidation) + { + Dictionary>? paramHash = null; + if (!skipParamValidation) + { + paramHash = new(); + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation == ParameterValidationType.None) + continue; + + if (!paramHash.ContainsKey(parameter.Validation)) + paramHash[parameter.Validation] = new List(); + paramHash[parameter.Validation].Add(parameter); + } + } + return paramHash; + } + + private MethodBodyStatement GetStatementsWithHash(MethodBodyStatement bodyStatements, Dictionary>? paramHash) + { + if (paramHash is null) + return bodyStatements; + + int count = 0; + foreach (var kvp in paramHash) + { + if (kvp.Key == ParameterValidationType.None) + continue; + count += kvp.Value.Count; + } + + if (count == 0) + { + throw new System.Exception("count is 0"); + //return bodyStatements; + } + + MethodBodyStatement[] statements = new MethodBodyStatement[count + 2]; + int index = 0; + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation != ParameterValidationType.None) + { + statements[index] = Argument.ValidateParameter(parameter); + index++; + } + } + statements[index] = EmptyLineStatement; + index++; + + statements[index] = bodyStatements; + + return statements; + } + + private MethodBodyStatement GetStatementsAsSingleList(MethodBodyStatement original) + { + bool wroteValidation = false; + List statements = new(); + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation != ParameterValidationType.None) + { + statements.Add(Argument.ValidateParameter(parameter)); + wroteValidation = true; + } + } + if (wroteValidation) + statements.Add(EmptyLineStatement); + + statements.Add(original); + return statements; + } + + private IEnumerable GetValidationStatementsWithYield() + { + bool wroteValidation = false; + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation != ParameterValidationType.None) + { + yield return Argument.ValidateParameter(parameter); + wroteValidation = true; + } + } + if (wroteValidation) + yield return EmptyLineStatement; + } + + private IReadOnlyList GetValidationStatements() + { + bool wroteValidation = false; + List statements = new(); + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation != ParameterValidationType.None) + { + statements.Add(Argument.ValidateParameter(parameter)); + wroteValidation = true; + } + } + if (wroteValidation) + statements.Add(EmptyLineStatement); + return statements; + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/PluginInitializer.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/PluginInitializer.cs new file mode 100644 index 0000000000..06a7251a01 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/perf/PluginInitializer.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.IO; +using System.Reflection; + +namespace Microsoft.Generator.CSharp.Perf +{ + internal static class PluginInitializer + { + public static void Initialize() + { + PluginHandler pluginHandler = new PluginHandler(); + pluginHandler.LoadPlugin(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location)!.FullName, "Projects", "Model")); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodCollection.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodCollection.cs index 2e3cb985bf..9489ccd281 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodCollection.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Providers; -using Microsoft.Generator.CSharp.Statements; using Microsoft.Generator.CSharp.Snippets; namespace Microsoft.Generator.CSharp @@ -60,21 +59,18 @@ private static MethodProvider BuildCreateMessageMethod(InputOperation operation) var methodSignature = new MethodSignature(methodSignatureName, FormattableStringHelpers.FromString(operation.Summary), FormattableStringHelpers.FromString(operation.Description), methodModifier, null, null, Parameters: methodParameters); var methodBody = Snippet.EmptyStatement; - return new MethodProvider(methodSignature, methodBody, CSharpMethodKinds.CreateMessage); + return new MethodProvider(methodSignature, methodBody); } /// /// Returns all methods in the collection of a specific kind. /// - internal List GetMethods(CSharpMethodKinds kind) + internal List GetMethods() { var methods = new List(); foreach (var method in _cSharpMethods) { - if (method.Kind == kind) - { - methods.Add(method); - } + methods.Add(method); } return methods; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodKinds.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodKinds.cs deleted file mode 100644 index 6949e2c11d..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/CSharpMethodKinds.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -using System; -using System.ComponentModel; - -namespace Microsoft.Generator.CSharp -{ - /// - /// Represents the kind of . - /// - public readonly partial struct CSharpMethodKinds : IEquatable - { - private const string ConvenienceValue = "Convenience"; - private const string ProtocolValue = "Protocol"; - private const string CreateMessageValue = "CreateMessage"; - private const string ConstructorValue = "Constructor"; - - private readonly string _value; - - /// Initializes a new instance of the structure. - /// The string value of the instance. - /// is null. - public CSharpMethodKinds(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - /// - /// Convenience method kind. - /// - public static CSharpMethodKinds Convenience { get; } = new CSharpMethodKinds(ConvenienceValue); - - /// - /// Protocol method kind. - /// - public static CSharpMethodKinds Protocol { get; } = new CSharpMethodKinds(ProtocolValue); - - /// - /// CreateMessage method kind. - /// - public static CSharpMethodKinds CreateMessage { get; } = new CSharpMethodKinds(CreateMessageValue); - - /// - /// Constructor method kind. - /// - public static CSharpMethodKinds Constructor { get; } = new CSharpMethodKinds(ConstructorValue); - - /// Determines if two values are the same. - public static bool operator ==(CSharpMethodKinds left, CSharpMethodKinds right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(CSharpMethodKinds left, CSharpMethodKinds right) => !left.Equals(right); - - /// Converts a string to a . - /// The string value to convert. - public static implicit operator CSharpMethodKinds(string value) => new(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object? obj) => obj is CSharpMethodKinds other && Equals(other); - - /// - public bool Equals(CSharpMethodKinds other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - - /// - public override string ToString() => _value; - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/KnownParameters.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/KnownParameters.cs index 15b969da0c..d775891827 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/KnownParameters.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/OutputTypes/KnownParameters.cs @@ -49,7 +49,7 @@ public static partial class KnownParameters public static ParameterProvider CancellationTokenParameter => _cancellationTokenParameter ??= new("cancellationToken", $"The cancellation token to use", new CSharpType(typeof(CancellationToken)), Snippet.DefaultOf(typeof(CancellationToken))); private static ParameterProvider? _enumerationCancellationTokenParameter; - public static ParameterProvider EnumeratorCancellationTokenParameter => _enumerationCancellationTokenParameter ??= new("cancellationToken", $"Enumerator cancellation token", typeof(CancellationToken), Snippet.DefaultOf(typeof(CancellationToken))) { Attributes = new[] { new AttributeStatement(typeof(EnumeratorCancellationAttribute)) } }; + public static ParameterProvider EnumeratorCancellationTokenParameter => _enumerationCancellationTokenParameter ??= new("cancellationToken", $"Enumerator cancellation token", typeof(CancellationToken), Snippet.DefaultOf(typeof(CancellationToken)), attributes: [new AttributeStatement(typeof(EnumeratorCancellationAttribute))]); private static ParameterProvider? _response; public static ParameterProvider Response => _response ??= new("response", $"Response returned from backend service", CodeModelPlugin.Instance.Configuration.ApiTypes.ResponseType); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ChangeTrackingDictionaryProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ChangeTrackingDictionaryProvider.cs index 99fd63cc3a..1873406321 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ChangeTrackingDictionaryProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ChangeTrackingDictionaryProvider.cs @@ -142,7 +142,6 @@ private PropertyProvider BuildEnumerableValues() { return new PropertyProvider(null, MethodSignatureModifiers.None, new CSharpType(typeof(IEnumerable<>), _tValue), "Values", new ExpressionPropertyBody( new MemberExpression(This, "Values")), - null, _IReadOnlyDictionary); } @@ -150,7 +149,6 @@ private PropertyProvider BuildEnumerableKeys() { return new PropertyProvider(null, MethodSignatureModifiers.None, new CSharpType(typeof(IEnumerable<>), _tKey), "Keys", new ExpressionPropertyBody( new MemberExpression(This, "Keys")), - null, _IReadOnlyDictionary); } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs index 010e42f60d..fad9df0ba8 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs @@ -93,10 +93,9 @@ protected override PropertyProvider[] BuildProperties() protected override MethodProvider[] BuildConstructors() { - var validation = ValueType.IsValueType ? ParameterValidationType.None : ParameterValidationType.AssertNotNull; var valueParameter = new ParameterProvider("value", $"The value.", ValueType) { - Validation = validation + Validation = ValueType.IsValueType ? ParameterValidationType.None : ParameterValidationType.AssertNotNull }; var signature = new ConstructorSignature( Type: Type, @@ -108,11 +107,10 @@ protected override MethodProvider[] BuildConstructors() var valueField = (ValueExpression)_valueField; var body = new MethodBodyStatement[] { - new ParameterValidationStatement(signature.Parameters), Assign(valueField, valueParameter) }; - return [new MethodProvider(signature, body, CSharpMethodKinds.Constructor)]; + return [new MethodProvider(signature, body)]; } protected override MethodProvider[] BuildMethods() @@ -235,7 +233,9 @@ protected override MethodProvider[] BuildMethods() Modifiers: MethodSignatureModifiers.Internal, ReturnType: ValueType, Parameters: Array.Empty(), - Summary: null, Description: null, ReturnDescription: null); + Summary: null, + Description: null, + ReturnDescription: null); // writes the method: // internal float ToSerialSingle() => _value; // when ValueType is float diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FieldProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FieldProvider.cs index e7ac24e2a9..457ab35ccb 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FieldProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FieldProvider.cs @@ -3,6 +3,7 @@ using System; using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Statements; namespace Microsoft.Generator.CSharp.Providers { @@ -13,6 +14,7 @@ public sealed class FieldProvider public CSharpType Type { get; } public string Name { get; } public ValueExpression? InitializationValue { get; } + public XmlDocProvider? XmlDocs { get; } private CodeWriterDeclaration? _declaration; @@ -30,6 +32,7 @@ public FieldProvider( Name = name; Description = description; InitializationValue = initializationValue; + XmlDocs = Description is not null ? new XmlDocProvider() { Summary = new XmlDocSummaryStatement([Description]) } : null; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/IndexerProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/IndexerProvider.cs index 9410fdc66b..f4f940ab5f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/IndexerProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/IndexerProvider.cs @@ -2,15 +2,14 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; namespace Microsoft.Generator.CSharp.Providers { internal class IndexerProvider : PropertyProvider { public ParameterProvider IndexerParameter { get; } - public IndexerProvider(FormattableString? description, MethodSignatureModifiers modifiers, CSharpType propertyType, ParameterProvider indexerParameter, PropertyBody propertyBody, IReadOnlyDictionary? exceptions = null, CSharpType? explicitInterface = null) - : base(description, modifiers, propertyType, "this", propertyBody, exceptions, explicitInterface) + public IndexerProvider(FormattableString? description, MethodSignatureModifiers modifiers, CSharpType propertyType, ParameterProvider indexerParameter, PropertyBody propertyBody, CSharpType? explicitInterface = null) + : base(description, modifiers, propertyType, "this", propertyBody, explicitInterface) { IndexerParameter = indexerParameter; } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/MethodProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/MethodProvider.cs index 23bdcc6b03..7a92869f9e 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/MethodProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/MethodProvider.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Statements; +using static Microsoft.Generator.CSharp.Snippets.Snippet; namespace Microsoft.Generator.CSharp.Providers { @@ -11,25 +14,42 @@ namespace Microsoft.Generator.CSharp.Providers /// public sealed class MethodProvider { - /// - /// The kind of method of type . - /// - public CSharpMethodKinds Kind { get; } public MethodSignatureBase Signature { get; } public MethodBodyStatement? BodyStatements { get; } public ValueExpression? BodyExpression { get; } + public XmlDocProvider XmlDocs { get; } /// /// Initializes a new instance of the class with a body statement and method signature. /// /// The method signature. /// The method body. - /// The method kind . - public MethodProvider(MethodSignatureBase signature, MethodBodyStatement bodyStatements, CSharpMethodKinds? kind = null) + public MethodProvider(MethodSignatureBase signature, MethodBodyStatement bodyStatements) { Signature = signature; - BodyStatements = bodyStatements; - Kind = kind ?? new CSharpMethodKinds("Undefined"); + bool skipParamValidation = !signature.Modifiers.HasFlag(MethodSignatureModifiers.Public); + var paramHash = GetParamhash(skipParamValidation); + BodyStatements = GetBodyStatementWithValidation(bodyStatements, paramHash); + XmlDocs = BuildXmlDocs(paramHash); + } + + private Dictionary>? GetParamhash(bool skipParamValidation) + { + Dictionary>? paramHash = null; + if (!skipParamValidation) + { + paramHash = new(); + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation == ParameterValidationType.None) + continue; + + if (!paramHash.ContainsKey(parameter.Validation)) + paramHash[parameter.Validation] = new List(); + paramHash[parameter.Validation].Add(parameter); + } + } + return paramHash; } /// @@ -37,12 +57,71 @@ public MethodProvider(MethodSignatureBase signature, MethodBodyStatement bodySta /// /// The method signature. /// The method body expression. - /// The method kind . - public MethodProvider(MethodSignatureBase signature, ValueExpression bodyExpression, CSharpMethodKinds? kind = null) + public MethodProvider(MethodSignatureBase signature, ValueExpression bodyExpression) { Signature = signature; BodyExpression = bodyExpression; - Kind = kind ?? new CSharpMethodKinds("Undefined"); + XmlDocs = BuildXmlDocs(null); + } + + + private MethodBodyStatement GetBodyStatementWithValidation(MethodBodyStatement bodyStatements, Dictionary>? paramHash) + { + if (paramHash is null) + return bodyStatements; + + int count = 0; + foreach (var kvp in paramHash) + { + if (kvp.Key == ParameterValidationType.None) + continue; + count += kvp.Value.Count; + } + + if (count == 0) + return bodyStatements; + + MethodBodyStatement[] statements = new MethodBodyStatement[count + 2]; + int index = 0; + foreach (var parameter in Signature.Parameters) + { + if (parameter.Validation != ParameterValidationType.None) + { + statements[index] = Argument.ValidateParameter(parameter); + index++; + } + } + statements[index] = EmptyLineStatement; + index++; + + statements[index] = bodyStatements; + + return statements; + } + + private XmlDocProvider BuildXmlDocs(Dictionary>? paramHash) + { + var docs = new XmlDocProvider(); + if (Signature.SummaryText is not null) + docs.Summary = new XmlDocSummaryStatement([Signature.SummaryText]); + + foreach (var parameter in Signature.Parameters) + { + docs.Params.Add(new XmlDocParamStatement(parameter.Name, parameter.Description)); + } + + if (paramHash is not null) + { + foreach (var kvp in paramHash) + { + docs.Exceptions.Add(new XmlDocExceptionStatement(kvp.Key, kvp.Value)); + } + } + + if (Signature is MethodSignature methodSignature && methodSignature.ReturnDescription is not null) + docs.Returns = new XmlDocReturnsStatement(methodSignature.ReturnDescription); + + return docs; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs index 38ef66fe0a..5dd7d7de4d 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs @@ -97,12 +97,10 @@ protected override MethodProvider[] BuildConstructors() constructorParameters), bodyStatements: new MethodBodyStatement[] { - new ParameterValidationStatement(constructorParameters), GetPropertyInitializers(constructorParameters) - }, - kind: CSharpMethodKinds.Constructor); + }); - return new MethodProvider[] { constructor }; + return [constructor]; } private IReadOnlyList BuildConstructorParameters() diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ParameterProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ParameterProvider.cs index bea5012de4..e89a28bf97 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ParameterProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ParameterProvider.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -18,10 +19,10 @@ public sealed class ParameterProvider : IEquatable public FormattableString Description { get; } public CSharpType Type { get; init; } public ValueExpression? DefaultValue { get; init; } - public ParameterValidationType? Validation { get; init; } = ParameterValidationType.None; + public ParameterValidationType Validation { get; init; } = ParameterValidationType.None; public bool IsRef { get; } public bool IsOut { get; } - internal AttributeStatement[] Attributes { get; init; } = Array.Empty(); + internal IReadOnlyList Attributes { get; } = Array.Empty(); public ParameterProvider(InputModelProperty inputProperty) { @@ -37,7 +38,6 @@ public ParameterProvider(InputModelProperty inputProperty) /// The to convert. public ParameterProvider(InputParameter inputParameter) { - // TO-DO: Add additional implementation to properly build the parameter https://github.com/Azure/autorest.csharp/issues/4607 Name = inputParameter.Name; Description = FormattableStringHelpers.FromString(inputParameter.Description) ?? FormattableStringHelpers.Empty; Type = CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(inputParameter.Type); @@ -50,7 +50,8 @@ public ParameterProvider( CSharpType type, ValueExpression? defaultValue = null, bool isRef = false, - bool isOut = false) + bool isOut = false, + IReadOnlyList? attributes = default) { Name = name; Type = type; @@ -58,6 +59,7 @@ public ParameterProvider( IsRef = isRef; IsOut = isOut; DefaultValue = defaultValue; + Attributes = attributes ?? Array.Empty(); } private ParameterValidationType GetParameterValidation(InputModelProperty property, CSharpType propertyType) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs index 7f0e7d61e9..a98875f901 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs @@ -7,6 +7,7 @@ using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Snippets; +using Microsoft.Generator.CSharp.Statements; namespace Microsoft.Generator.CSharp.Providers { @@ -18,8 +19,9 @@ public class PropertyProvider public CSharpType Type { get; } public string Name { get; } public PropertyBody Body { get; } - public IReadOnlyDictionary? Exceptions { get; } public CSharpType? ExplicitInterface { get; } + public XmlDocProvider XmlDocs { get; } + public PropertyProvider(InputModelProperty inputProperty) { var propertyType = CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(inputProperty.Type); @@ -32,17 +34,28 @@ public PropertyProvider(InputModelProperty inputProperty) Description = PropertyDescriptionBuilder.BuildPropertyDescription(inputProperty, propertyType, serializationFormat, !propHasSetter); Name = inputProperty.Name.FirstCharToUpperCase(); Body = new AutoPropertyBody(propHasSetter, setterModifier, GetPropertyInitializationValue(propertyType, inputProperty)); + XmlDocs = GetXmlDocs(); } - public PropertyProvider(FormattableString? description, MethodSignatureModifiers modifiers, CSharpType type, string name, PropertyBody body, IReadOnlyDictionary? exceptions = null, CSharpType? explicitInterface = null) + public PropertyProvider(FormattableString? description, MethodSignatureModifiers modifiers, CSharpType type, string name, PropertyBody body, CSharpType? explicitInterface = null) { Description = [description ?? PropertyDescriptionBuilder.CreateDefaultPropertyDescription(name, !body.HasSetter)]; Modifiers = modifiers; Type = type; Name = name; Body = body; - Exceptions = exceptions; ExplicitInterface = explicitInterface; + XmlDocs = GetXmlDocs(); + } + + private XmlDocProvider GetXmlDocs() + { + // TODO -- should write parameter xml doc if this is an IndexerDeclaration: https://github.com/microsoft/typespec/issues/3276 + + return new XmlDocProvider() + { + Summary = new XmlDocSummaryStatement(Description), + }; } /// diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/XmlDocProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/XmlDocProvider.cs new file mode 100644 index 0000000000..50b6aecdaf --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/XmlDocProvider.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Microsoft.Generator.CSharp.Statements; + +namespace Microsoft.Generator.CSharp.Providers +{ + public class XmlDocProvider + { + public XmlDocProvider() + { + Params = new List(); + Exceptions = new List(); + } + + public XmlDocSummaryStatement? Summary { get; set; } + public IList Params { get; } + public XmlDocReturnsStatement? Returns { get; set; } + public IList Exceptions { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.Argument.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.Argument.cs index 3efd786a69..3b6a722c89 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.Argument.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.Argument.cs @@ -26,15 +26,12 @@ public static MethodBodyStatement AssertNotNullOrWhiteSpace(ValueExpression vari return ArgumentProvider.Instance.AssertNotNullOrWhiteSpace(variable); } - public static MethodBodyStatement ValidateParameter(ParameterProvider parameter) + public static MethodBodyStatement ValidateParameter(ParameterProvider parameter) => parameter.Validation switch { - return parameter.Validation switch - { - ParameterValidationType.AssertNotNullOrEmpty => AssertNotNullOrEmpty(parameter), - ParameterValidationType.AssertNotNull => AssertNotNull(parameter), - _ => EmptyStatement - }; - } + ParameterValidationType.AssertNotNullOrEmpty => AssertNotNullOrEmpty(parameter), + ParameterValidationType.AssertNotNull => AssertNotNull(parameter), + _ => EmptyStatement + }; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.cs index 991a2391cd..d3f9854baf 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.cs @@ -11,8 +11,18 @@ namespace Microsoft.Generator.CSharp.Snippets { public static partial class Snippet { + private class PrivateEmptyLineStatement : MethodBodyStatement + { + internal override void Write(CodeWriter writer) + { + writer.WriteLine(); + } + } + + public readonly static MethodBodyStatement EmptyStatement = new(); + public readonly static MethodBodyStatement EmptyLineStatement = new PrivateEmptyLineStatement(); + public static ExtensibleSnippets Extensible => CodeModelPlugin.Instance.ExtensibleSnippets; - public static MethodBodyStatement EmptyStatement { get; } = new(); public static MethodBodyStatement AsStatement(this IEnumerable statements) => statements.ToArray(); public static ValueExpression Dash { get; } = new KeywordExpression("_", null); @@ -67,7 +77,6 @@ public static BoolSnippet Is(ValueExpression left, ValueExpression right) public static BoolSnippet And(BoolSnippet left, BoolSnippet right) => new(new BinaryOperatorExpression("&&", left.Untyped, right.Untyped)); public static BoolSnippet Not(BoolSnippet operand) => new(new UnaryOperatorExpression("!", operand, false)); - public static MethodBodyStatement EmptyLine => new EmptyLineStatement(); public static KeywordStatement Continue => new("continue", null); public static KeywordStatement Break => new("break", null); public static KeywordStatement Return(ValueExpression expression) => new("return", expression); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueIfNullStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueIfNullStatement.cs index 1ea8b33a16..007041ac0e 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueIfNullStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueIfNullStatement.cs @@ -5,8 +5,17 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record AssignValueIfNullStatement(ValueExpression To, ValueExpression From) : MethodBodyStatement + public sealed class AssignValueIfNullStatement : MethodBodyStatement { + public ValueExpression To { get; } + public ValueExpression From { get; } + + public AssignValueIfNullStatement(ValueExpression to, ValueExpression from) + { + To = to; + From = from; + } + internal override void Write(CodeWriter writer) { To.Write(writer); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueStatement.cs index 8ccd3ed39a..13b47c8b4d 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AssignValueStatement.cs @@ -5,8 +5,17 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record AssignValueStatement(ValueExpression To, ValueExpression From) : MethodBodyStatement + public sealed class AssignValueStatement : MethodBodyStatement { + public ValueExpression To { get; } + public ValueExpression From { get; } + + public AssignValueStatement(ValueExpression to, ValueExpression from) + { + To = to; + From = from; + } + internal override void Write(CodeWriter writer) { To.Write(writer); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AttributeStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AttributeStatement.cs index 7bb0adcf6f..dce1f8924c 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AttributeStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/AttributeStatement.cs @@ -7,8 +7,17 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record AttributeStatement(CSharpType Type, IReadOnlyList Arguments) : MethodBodyStatement + public sealed class AttributeStatement : MethodBodyStatement { + public CSharpType Type { get; } + public IReadOnlyList Arguments { get; } + + public AttributeStatement(CSharpType type, IReadOnlyList arguments) + { + Type = type; + Arguments = arguments; + } + public AttributeStatement(CSharpType type, params ValueExpression[] arguments) : this(type, (IReadOnlyList)arguments) { } internal override void Write(CodeWriter writer) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareLocalFunctionStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareLocalFunctionStatement.cs index c6c1c718ee..22f429c3c3 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareLocalFunctionStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareLocalFunctionStatement.cs @@ -8,13 +8,28 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record DeclareLocalFunctionStatement(CodeWriterDeclaration Name, IReadOnlyList Parameters, CSharpType ReturnType, ValueExpression? BodyExpression, MethodBodyStatement? BodyStatement) : MethodBodyStatement + public sealed class DeclareLocalFunctionStatement : MethodBodyStatement { - internal DeclareLocalFunctionStatement(CodeWriterDeclaration Name, IReadOnlyList Parameters, CSharpType ReturnType, MethodBodyStatement BodyStatement) - : this(Name, Parameters, ReturnType, null, BodyStatement) { } + public CodeWriterDeclaration Name { get; } + public IReadOnlyList Parameters { get; } + public CSharpType ReturnType { get; } + public ValueExpression? BodyExpression { get; } + public MethodBodyStatement? BodyStatement { get; } - internal DeclareLocalFunctionStatement(CodeWriterDeclaration Name, IReadOnlyList Parameters, CSharpType ReturnType, ValueExpression BodyExpression) - : this(Name, Parameters, ReturnType, BodyExpression, null) { } + private DeclareLocalFunctionStatement(CodeWriterDeclaration name, IReadOnlyList parameters, CSharpType returnType, ValueExpression? bodyExpression, MethodBodyStatement? bodyStatement) + { + Name = name; + Parameters = parameters; + ReturnType = returnType; + BodyExpression = bodyExpression; + BodyStatement = bodyStatement; + } + + internal DeclareLocalFunctionStatement(CodeWriterDeclaration name, IReadOnlyList parameters, CSharpType returnType, MethodBodyStatement bodyStatement) + : this(name, parameters, returnType, null, bodyStatement) { } + + internal DeclareLocalFunctionStatement(CodeWriterDeclaration name, IReadOnlyList parameters, CSharpType returnType, ValueExpression bodyExpression) + : this(name, parameters, returnType, bodyExpression, null) { } internal override void Write(CodeWriter writer) { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareVariableStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareVariableStatement.cs index deb33d6fc7..3fb539183f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareVariableStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/DeclareVariableStatement.cs @@ -5,8 +5,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record DeclareVariableStatement(CSharpType? Type, CodeWriterDeclaration Name, ValueExpression Value) : MethodBodyStatement + public sealed class DeclareVariableStatement : MethodBodyStatement { + public CodeWriterDeclaration Name { get; } + public ValueExpression Value { get; } + public CSharpType? Type { get; } + + public DeclareVariableStatement(CSharpType? type, CodeWriterDeclaration name, ValueExpression value) + { + Name = name; + Value = value; + Type = type; + } + internal override void Write(CodeWriter writer) { if (Type != null) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/EmptyLineStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/EmptyLineStatement.cs deleted file mode 100644 index eaf525b15d..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/EmptyLineStatement.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Generator.CSharp.Statements -{ - public sealed record EmptyLineStatement() : MethodBodyStatement - { - internal override void Write(CodeWriter writer) - { - writer.WriteLine(); - } - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForStatement.cs index 647a8e2a42..a23d39734e 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForStatement.cs @@ -7,8 +7,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record ForStatement(AssignmentExpression? IndexerAssignment, ValueExpression? Condition, ValueExpression? IncrementExpression) : MethodBodyStatement, IEnumerable + public sealed class ForStatement : MethodBodyStatement, IEnumerable { + public ValueExpression? IndexExpression { get; set; } + public ValueExpression? Condition { get; set; } + public ValueExpression? IncrementExpression { get; set; } + + public ForStatement(ValueExpression? indexExpression, ValueExpression? condition, ValueExpression? incrementExpression) + { + IndexExpression = indexExpression; + Condition = condition; + IncrementExpression = incrementExpression; + } + private readonly List _body = new(); public IReadOnlyList Body => _body; @@ -21,7 +32,7 @@ internal override void Write(CodeWriter writer) using (writer.AmbientScope()) { writer.AppendRaw("for ("); - IndexerAssignment?.Write(writer); + IndexExpression?.Write(writer); writer.AppendRaw("; "); Condition?.Write(writer); writer.AppendRaw("; "); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForeachStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForeachStatement.cs index 39b0e3b2f4..111f1bd587 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForeachStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ForeachStatement.cs @@ -8,8 +8,21 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record ForeachStatement(CSharpType? ItemType, CodeWriterDeclaration Item, ValueExpression Enumerable, bool IsAsync) : MethodBodyStatement, IEnumerable + public sealed class ForeachStatement : MethodBodyStatement, IEnumerable { + public CSharpType? ItemType { get; } + public CodeWriterDeclaration Item { get; } + public ValueExpression Enumerable { get; } + public bool IsAsync { get; } + + public ForeachStatement(CSharpType? itemType, CodeWriterDeclaration item, ValueExpression enumerable, bool isAsync) + { + ItemType = itemType; + Item = item; + Enumerable = enumerable; + IsAsync = isAsync; + } + private readonly List _body = new(); public IReadOnlyList Body => _body; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElsePreprocessorStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElsePreprocessorStatement.cs index 3688139eca..893902bd57 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElsePreprocessorStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElsePreprocessorStatement.cs @@ -3,8 +3,18 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record IfElsePreprocessorStatement(string Condition, MethodBodyStatement If, MethodBodyStatement? Else) : MethodBodyStatement + public sealed class IfElsePreprocessorStatement : MethodBodyStatement { + public string Condition { get; } + public MethodBodyStatement If { get; } + public MethodBodyStatement? Else { get; } + + public IfElsePreprocessorStatement(string condition, MethodBodyStatement ifStatement, MethodBodyStatement? elseStatement) + { + Condition = condition; + If = ifStatement; + Else = elseStatement; + } internal override void Write(CodeWriter writer) { writer.WriteLine($"#if {Condition}"); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElseStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElseStatement.cs index c61dd89550..bd077d0b32 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElseStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfElseStatement.cs @@ -2,13 +2,21 @@ // Licensed under the MIT License. using Microsoft.Generator.CSharp.Expressions; -using Microsoft.Generator.CSharp.Snippets; namespace Microsoft.Generator.CSharp.Statements { - public sealed record IfElseStatement(IfStatement If, MethodBodyStatement? Else) : MethodBodyStatement + public sealed class IfElseStatement : MethodBodyStatement { - public IfElseStatement(BoolSnippet condition, MethodBodyStatement ifStatement, MethodBodyStatement? elseStatement, bool inline = false, bool addBraces = true) + public IfStatement If { get; } + public MethodBodyStatement? Else { get; } + + public IfElseStatement(IfStatement ifStatement, MethodBodyStatement? elseStatement) + { + If = ifStatement; + Else = elseStatement; + } + + public IfElseStatement(ValueExpression condition, MethodBodyStatement ifStatement, MethodBodyStatement? elseStatement, bool inline = false, bool addBraces = true) : this(new IfStatement(condition, inline, addBraces) { ifStatement }, elseStatement) {} internal override void Write(CodeWriter writer) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfStatement.cs index dc0065abaf..9e61669407 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/IfStatement.cs @@ -7,8 +7,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record IfStatement(ValueExpression Condition, bool Inline = false, bool AddBraces = true) : MethodBodyStatement, IEnumerable + public sealed class IfStatement : MethodBodyStatement, IEnumerable { + public ValueExpression Condition { get; } + public bool Inline { get; } + public bool AddBraces { get; } + + public IfStatement(ValueExpression condition, bool inline = false, bool addBraces = true) + { + Condition = condition; + Inline = inline; + AddBraces = addBraces; + } + private readonly List _body = new(); public MethodBodyStatement Body => _body; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeInstanceMethodStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeInstanceMethodStatement.cs index 73a61e9f66..11d711f946 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeInstanceMethodStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeInstanceMethodStatement.cs @@ -7,8 +7,21 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record InvokeInstanceMethodStatement(ValueExpression? InstanceReference, string MethodName, IReadOnlyList Arguments, bool CallAsAsync) : MethodBodyStatement + public sealed class InvokeInstanceMethodStatement : MethodBodyStatement { + public ValueExpression? InstanceReference { get; } + public string MethodName { get; } + public IReadOnlyList Arguments { get; } + public bool CallAsAsync { get; } + + public InvokeInstanceMethodStatement(ValueExpression? instance, string methodName, IReadOnlyList arguments, bool callAsAsync) + { + InstanceReference = instance; + MethodName = methodName; + Arguments = arguments; + CallAsAsync = callAsAsync; + } + public InvokeInstanceMethodStatement(ValueExpression? instance, string methodName) : this(instance, methodName, Array.Empty(), false) { } public InvokeInstanceMethodStatement(ValueExpression? instance, string methodName, ValueExpression arg) : this(instance, methodName, new[] { arg }, false) { } public InvokeInstanceMethodStatement(ValueExpression? instance, string methodName, ValueExpression arg1, ValueExpression arg2) : this(instance, methodName, new[] { arg1, arg2 }, false) { } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeStaticMethodStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeStaticMethodStatement.cs index aadd7e0640..026c42488b 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeStaticMethodStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/InvokeStaticMethodStatement.cs @@ -7,13 +7,30 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record InvokeStaticMethodStatement(CSharpType? MethodType, string MethodName, IReadOnlyList Arguments, IReadOnlyList? TypeArguments = null, bool CallAsExtension = false, bool CallAsAsync = false) : MethodBodyStatement + public sealed class InvokeStaticMethodStatement : MethodBodyStatement { + public CSharpType? MethodType { get; } + public string MethodName { get; } + public IReadOnlyList Arguments { get; } + public IReadOnlyList TypeArguments { get; } + public bool CallAsExtension { get; } + public bool CallAsAsync { get; } + + public InvokeStaticMethodStatement(CSharpType? methodType, string methodName, IReadOnlyList arguments, IReadOnlyList? typeArguments = null, bool callAsExtension = false, bool callAsAsync = false) + { + MethodType = methodType; + MethodName = methodName; + Arguments = arguments; + TypeArguments = typeArguments ?? Array.Empty(); + CallAsExtension = callAsExtension; + CallAsAsync = callAsAsync; + } + public InvokeStaticMethodStatement(CSharpType? methodType, string methodName) : this(methodType, methodName, Array.Empty()) { } public InvokeStaticMethodStatement(CSharpType? methodType, string methodName, ValueExpression arg) : this(methodType, methodName, new[] { arg }) { } public InvokeStaticMethodStatement(CSharpType? methodType, string methodName, ValueExpression arg1, ValueExpression arg2) : this(methodType, methodName, new[] { arg1, arg2 }) { } - public static InvokeStaticMethodStatement Extension(CSharpType? methodType, string methodName, ValueExpression instanceReference) => new(methodType, methodName, new[] { instanceReference }, CallAsExtension: true); - public static InvokeStaticMethodStatement Extension(CSharpType? methodType, string methodName, ValueExpression instanceReference, ValueExpression arg) => new(methodType, methodName, new[] { instanceReference, arg }, CallAsExtension: true); + public static InvokeStaticMethodStatement Extension(CSharpType? methodType, string methodName, ValueExpression instanceReference) => new(methodType, methodName, new[] { instanceReference }, callAsExtension: true); + public static InvokeStaticMethodStatement Extension(CSharpType? methodType, string methodName, ValueExpression instanceReference, ValueExpression arg) => new(methodType, methodName, new[] { instanceReference, arg }, callAsExtension: true); internal override void Write(CodeWriter writer) { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/KeywordStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/KeywordStatement.cs index 0233b5abd2..68d3805843 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/KeywordStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/KeywordStatement.cs @@ -5,8 +5,17 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record KeywordStatement(string Keyword, ValueExpression? Expression) : MethodBodyStatement + public sealed class KeywordStatement : MethodBodyStatement { + public string Keyword { get; } + public ValueExpression? Expression { get; } + + public KeywordStatement(string keyword, ValueExpression? expression) + { + Keyword = keyword; + Expression = expression; + } + internal override void Write(CodeWriter writer) { writer.AppendRaw(Keyword); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatement.cs index 8aade9e3f7..669e050cc9 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatement.cs @@ -5,10 +5,10 @@ namespace Microsoft.Generator.CSharp.Statements { - public record MethodBodyStatement + public class MethodBodyStatement { internal virtual void Write(CodeWriter writer) { } - public static implicit operator MethodBodyStatement(MethodBodyStatement[] statements) => new MethodBodyStatements(Statements: statements); - public static implicit operator MethodBodyStatement(List statements) => new MethodBodyStatements(Statements: statements); + public static implicit operator MethodBodyStatement(MethodBodyStatement[] statements) => new MethodBodyStatements(statements); + public static implicit operator MethodBodyStatement(List statements) => new MethodBodyStatements(statements); } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatements.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatements.cs index b698846f2d..c18c3f0c3d 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatements.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/MethodBodyStatements.cs @@ -5,8 +5,15 @@ namespace Microsoft.Generator.CSharp.Statements { - public record MethodBodyStatements(IReadOnlyList Statements) : MethodBodyStatement + public class MethodBodyStatements : MethodBodyStatement { + public IReadOnlyList Statements { get; } + + public MethodBodyStatements(IReadOnlyList statements) + { + Statements = statements; + } + internal override void Write(CodeWriter writer) { foreach (var statement in Statements) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ParameterValidationStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ParameterValidationStatement.cs deleted file mode 100644 index 05c79f72af..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ParameterValidationStatement.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using Microsoft.Generator.CSharp.Providers; - -namespace Microsoft.Generator.CSharp.Statements -{ - public sealed record ParameterValidationStatement(IReadOnlyList Parameters) : MethodBodyStatement - { - internal sealed override void Write(CodeWriter writer) - { - writer.WriteParametersValidation(Parameters); - } - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SingleLineCommentStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SingleLineCommentStatement.cs index 5ce27857d9..ae2ab0c60b 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SingleLineCommentStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SingleLineCommentStatement.cs @@ -5,8 +5,15 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record SingleLineCommentStatement(FormattableString Message) : MethodBodyStatement + public sealed class SingleLineCommentStatement : MethodBodyStatement { + public FormattableString Message { get; } + + public SingleLineCommentStatement(FormattableString message) + { + Message = message; + } + public SingleLineCommentStatement(string message) : this(FormattableStringHelpers.FromString(message)) { } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchCaseStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchCaseStatement.cs index fa6d80fa44..c1b098d9a4 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchCaseStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchCaseStatement.cs @@ -8,8 +8,21 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record SwitchCaseStatement(IReadOnlyList Matches, MethodBodyStatement Statement, bool Inline = false, bool AddScope = false) : MethodBodyStatement + public sealed class SwitchCaseStatement : MethodBodyStatement { + public IReadOnlyList Matches { get; } + public MethodBodyStatement Statement { get; } + public bool Inline { get; } + public bool AddScope { get; } + + public SwitchCaseStatement(IReadOnlyList matches, MethodBodyStatement statement, bool inline = false, bool addScope = false) + { + Matches = matches; + Statement = statement; + Inline = inline; + AddScope = addScope; + } + public SwitchCaseStatement(ValueExpression match, MethodBodyStatement statement, bool inline = false, bool addScope = false) : this(new[] { match }, statement, inline, addScope) { } public static SwitchCaseStatement Default(MethodBodyStatement statement, bool inline = false, bool addScope = false) => new(Array.Empty(), statement, inline, addScope); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchStatement.cs index c206ad0a10..17df9fdcc1 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/SwitchStatement.cs @@ -7,8 +7,15 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record SwitchStatement(ValueExpression MatchExpression) : MethodBodyStatement, IEnumerable + public sealed class SwitchStatement : MethodBodyStatement, IEnumerable { + public ValueExpression MatchExpression { get; } + + public SwitchStatement(ValueExpression matchExpression) + { + MatchExpression = matchExpression; + } + public SwitchStatement(ValueExpression matchExpression, IEnumerable cases) : this(matchExpression) { _cases.AddRange(cases); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ThrowStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ThrowStatement.cs index 35ed3f06ff..c06b997708 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ThrowStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/ThrowStatement.cs @@ -5,8 +5,15 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record ThrowStatement(ValueExpression ThrowExpression) : MethodBodyStatement + public sealed class ThrowStatement : MethodBodyStatement { + public ValueExpression ThrowExpression { get; } + + public ThrowStatement(ValueExpression throwExpression) + { + ThrowExpression = throwExpression; + } + internal override void Write(CodeWriter writer) { ThrowExpression.Write(writer); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/TryCatchFinallyStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/TryCatchFinallyStatement.cs index d8c1261192..b63a044d1a 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/TryCatchFinallyStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/TryCatchFinallyStatement.cs @@ -7,8 +7,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record TryCatchFinallyStatement(MethodBodyStatement Try, IReadOnlyList Catches, MethodBodyStatement? Finally) : MethodBodyStatement + public sealed class TryCatchFinallyStatement : MethodBodyStatement { + public MethodBodyStatement Try { get; } + public IReadOnlyList Catches { get; } + public MethodBodyStatement? Finally { get; } + + public TryCatchFinallyStatement(MethodBodyStatement tryStatement, IReadOnlyList catches, MethodBodyStatement? finallyStatement) + { + Try = tryStatement; + Catches = catches; + Finally = finallyStatement; + } + public TryCatchFinallyStatement(MethodBodyStatement Try) : this(Try, Array.Empty(), null) { } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UnaryOperatorStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UnaryOperatorStatement.cs index 2f039b2c28..d4a8f59705 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UnaryOperatorStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UnaryOperatorStatement.cs @@ -5,8 +5,15 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record UnaryOperatorStatement(UnaryOperatorExpression Expression) : MethodBodyStatement + public sealed class UnaryOperatorStatement : MethodBodyStatement { + public UnaryOperatorExpression Expression { get; } + + public UnaryOperatorStatement(UnaryOperatorExpression expression) + { + Expression = expression; + } + internal override void Write(CodeWriter writer) { Expression.Write(writer); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingDeclareVariableStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingDeclareVariableStatement.cs index 8fc6987a9c..de29cdcf79 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingDeclareVariableStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingDeclareVariableStatement.cs @@ -5,8 +5,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record UsingDeclareVariableStatement(CSharpType? Type, CodeWriterDeclaration Name, ValueExpression Value) : MethodBodyStatement + public sealed class UsingDeclareVariableStatement : MethodBodyStatement { + public CSharpType? Type { get; } + public CodeWriterDeclaration Name { get; } + public ValueExpression Value { get; } + + public UsingDeclareVariableStatement(CSharpType? type, CodeWriterDeclaration name, ValueExpression value) + { + Type = type; + Name = name; + Value = value; + } + internal override void Write(CodeWriter writer) { if (Type != null) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingScopeStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingScopeStatement.cs index d345d5f603..48ca48583f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingScopeStatement.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/UsingScopeStatement.cs @@ -8,8 +8,19 @@ namespace Microsoft.Generator.CSharp.Statements { - public sealed record UsingScopeStatement(CSharpType? Type, CodeWriterDeclaration Variable, ValueExpression Value) : MethodBodyStatement, IEnumerable + public sealed class UsingScopeStatement : MethodBodyStatement, IEnumerable { + public CSharpType? Type { get; } + public CodeWriterDeclaration Variable { get; } + public ValueExpression Value { get; } + + public UsingScopeStatement(CSharpType? type, CodeWriterDeclaration variable, ValueExpression value) + { + Type = type; + Variable = variable; + Value = value; + } + private readonly List _body = new(); public IReadOnlyList Body => _body; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocExceptionStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocExceptionStatement.cs new file mode 100644 index 0000000000..5131babee0 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocExceptionStatement.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Generator.CSharp.Providers; + +namespace Microsoft.Generator.CSharp.Statements +{ + public class XmlDocExceptionStatement : MethodBodyStatement + { + //($"", "", Text) + public Type ExceptionType { get; } + public IReadOnlyList Parameters { get; } + + private string _reason; + + public XmlDocExceptionStatement(ParameterValidationType validationType, IReadOnlyList parameters) + { + ExceptionType = GetExceptionType(validationType); + Parameters = parameters; + _reason = GetText(validationType); + } + + private static Type GetExceptionType(ParameterValidationType validationType) => validationType switch + { + ParameterValidationType.AssertNotNull => typeof(ArgumentNullException), + ParameterValidationType.AssertNotNullOrEmpty => typeof(ArgumentException), + _ => throw new ArgumentOutOfRangeException(nameof(validationType), validationType, $"Cannot create an XmlDocExceptionStatement with {validationType} validationType") + }; + + private static string GetText(ParameterValidationType validationType) => validationType switch + { + ParameterValidationType.AssertNotNull => "is null.", + ParameterValidationType.AssertNotNullOrEmpty => "is an empty string, and was expected to be non-empty.", + _ => throw new ArgumentOutOfRangeException(nameof(validationType), validationType, $"Cannot create an XmlDocExceptionStatement with {validationType} validationType") + }; + + internal override void Write(CodeWriter writer) + { + using var scope = new CodeWriter.XmlDocWritingScope(writer); + + writer.Append($"/// "); + + writer.Append($" "); + for (int i = 1; i < Parameters.Count - 1; i++) + { + writer.Append($", "); + } + if (Parameters.Count > 1) + writer.Append($" or "); + + writer.WriteLine($" {_reason} "); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocParamStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocParamStatement.cs new file mode 100644 index 0000000000..d4931c4eaf --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocParamStatement.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Generator.CSharp.Statements +{ + public sealed class XmlDocParamStatement : XmlDocStatement + { + public XmlDocParamStatement(string paramName, FormattableString text) + : base($"", "", [text]) + { + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocReturnsStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocReturnsStatement.cs new file mode 100644 index 0000000000..59e690ae2b --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocReturnsStatement.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Generator.CSharp.Statements +{ + public sealed class XmlDocReturnsStatement : XmlDocStatement + { + public XmlDocReturnsStatement(FormattableString text) + : base("", "", [text]) + { + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocStatement.cs new file mode 100644 index 0000000000..053c34df64 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocStatement.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Generator.CSharp.Statements +{ + public class XmlDocStatement : MethodBodyStatement + { + private const string SingleArgFormat = "{0}"; + + public string StartTag { get; init; } + public string EndTag { get; init; } + public IReadOnlyList Lines { get; init; } + + public XmlDocStatement(string startTag, string endTag, IReadOnlyList lines) + { + StartTag = startTag; + EndTag = endTag; + Lines = lines; + } + + internal override void Write(CodeWriter writer) + { + using var scope = new CodeWriter.XmlDocWritingScope(writer); + + if (Lines.Count == 0 || IsEmptySingleLine(Lines)) + { + writer.WriteLine($"/// {StartTag}{EndTag}"); + } + else if (Lines.Count == 1) + { + string periodOrEmpty = GetPeriodOrEmpty(Lines[0]); + writer.WriteLine($"/// {StartTag} {Lines[0]}{periodOrEmpty} {EndTag}"); + } + else + { + writer.WriteLine($"/// {StartTag}"); + foreach (var line in Lines) + { + writer.WriteLine($"/// {line}"); + } + writer.WriteLine($"/// {EndTag}"); + } + } + + private string GetPeriodOrEmpty(FormattableString formattableString) + { + // for single line comment we always want the line to end in a period. + + string lineFormat = Lines[0].Format; + string stringToCheck = lineFormat; + if (lineFormat == SingleArgFormat && Lines[0].ArgumentCount == 1 && Lines[0].GetArgument(0) is string strLine) + { + stringToCheck = strLine; + } + return stringToCheck.EndsWith(".") ? string.Empty : "."; + } + + private static bool IsEmptySingleLine(IReadOnlyList lines) + { + if (lines.Count != 1) + { + return false; + } + + string lineFormat = lines[0].Format; + if (lineFormat.Equals(string.Empty)) + { + return true; + } + + if (lineFormat != SingleArgFormat) + { + return false; + } + + var firstArg = lines[0].GetArgument(0); + return firstArg is not null && firstArg.Equals(string.Empty); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocSummaryStatement.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocSummaryStatement.cs new file mode 100644 index 0000000000..ddc64d5f24 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Statements/XmlDocSummaryStatement.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Generator.CSharp.Statements +{ + public sealed class XmlDocSummaryStatement : XmlDocStatement + { + public XmlDocSummaryStatement(IReadOnlyList lines) + : base("", "", lines) + { + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.Documentation.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.Documentation.cs deleted file mode 100644 index 48f4fdf38b..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.Documentation.cs +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using Microsoft.Generator.CSharp.Providers; - -namespace Microsoft.Generator.CSharp -{ - internal sealed partial class CodeWriter - { - private const string SingleArgFormat = "{0}"; - - public CodeWriter WriteXmlDocumentationSummary(IReadOnlyList lines) - { - return WriteXmlDocumentation("summary", lines); - } - - public CodeWriter WriteXmlDocumentation(string tag, IReadOnlyList lines) - { - return WriteDocumentationLines($"<{tag}>", $"", lines); - } - - public CodeWriter WriteXmlDocumentationParameters(IEnumerable parameters) - { - foreach (var parameter in parameters) - { - WriteXmlDocumentationParameter(parameter); - } - - return this; - } - - public CodeWriter WriteXmlDocumentationParameter(string name, IReadOnlyList lines) - { - return WriteDocumentationLines($"", $"", lines); - } - - /// - /// Writes XML documentation for a parameter of a method using a "param" tag. - /// - /// Writer to which code is written to. - /// The definition of the parameter, including name and description. - /// - public CodeWriter WriteXmlDocumentationParameter(ParameterProvider parameter) - { - return WriteXmlDocumentationParameter(parameter.Name, [parameter.Description]); - } - - public CodeWriter WriteXmlDocumentationException(CSharpType exception, IReadOnlyList lines) - { - return WriteDocumentationLines($"", $"", lines); - } - - public CodeWriter WriteXmlDocumentationReturns(FormattableString text) - { - return WriteDocumentationLines($"", $"", [text]); - } - - public CodeWriter WriteXmlDocumentationInclude(string filename, MethodSignature methodSignature, out string memberId) - { - // We use short names of types for external doc reference member id - // This is not good enough for cref, but for now works as member id - // Change to cref-style names if needed - var sb = new StringBuilder(); - sb.Append(methodSignature.Name).Append("("); - foreach (var parameter in methodSignature.Parameters) - { - AppendTypeWithShortNames(parameter.Type, sb); - sb.Append(","); - } - - sb.Remove(sb.Length - 1, 1); - sb.Append(")"); - - memberId = sb.ToString(); - return WriteRawLine($"/// "); - } - - private static void AppendTypeWithShortNames(CSharpType type, StringBuilder sb) - { - sb.Append(type.TryGetCSharpFriendlyName(out var keywordName) ? keywordName : type.Name); - - if (type.Arguments.Any()) - { - sb.Append("{"); - foreach (var typeArgument in type.Arguments) - { - AppendTypeWithShortNames(typeArgument, sb); - sb.Append(","); - } - sb.Remove(sb.Length - 1, 1); - sb.Append("}"); - } - - if (type is { IsNullable: true, IsValueType: true }) - { - sb.Append("?"); - } - } - - public CodeWriter WriteXmlDocumentationRequiredParametersException(IEnumerable parameters) - { - return WriteXmlDocumentationParametersExceptions(typeof(ArgumentNullException), parameters.Where(p => p.Validation is ParameterValidationType.AssertNotNull or ParameterValidationType.AssertNotNullOrEmpty).ToArray(), " is null."); - } - - public CodeWriter WriteXmlDocumentationNonEmptyParametersException(IEnumerable parameters) - { - return WriteXmlDocumentationParametersExceptions(typeof(ArgumentException), parameters.Where(p => p.Validation == ParameterValidationType.AssertNotNullOrEmpty).ToArray(), " is an empty string, and was expected to be non-empty."); - } - - private CodeWriter WriteXmlDocumentationParametersExceptions(Type exceptionType, IReadOnlyCollection parameters, string reason) - { - if (parameters.Count == 0) - { - return this; - } - - var formatBuilder = new StringBuilder(); - for (var i = 0; i < parameters.Count - 2; ++i) - { - formatBuilder.Append(", "); - } - - if (parameters.Count > 1) - { - formatBuilder.Append(" or "); - } - - formatBuilder.Append(""); - formatBuilder.Append(reason); - - var description = FormattableStringFactory.Create(formatBuilder.ToString(), parameters.Select(p => (object)p.Name).ToArray()); - return WriteXmlDocumentationException(exceptionType, [description]); - } - - public CodeWriter WriteDocumentationLines(FormattableString startTag, FormattableString endTag, IReadOnlyList lines) - => AppendXmlDocumentation(startTag, endTag, lines); - - public CodeWriter WriteMethodDocumentation(MethodSignatureBase methodBase) - { - if (methodBase.NonDocumentComment is { } comment) - { - WriteLine($"// {comment}"); - } - - if (methodBase.SummaryText is { } summaryText) - { - WriteXmlDocumentationSummary([summaryText]); - } - - return WriteMethodDocumentationSignature(methodBase); - } - - public CodeWriter WriteMethodDocumentationSignature(MethodSignatureBase methodBase) - { - WriteXmlDocumentationParameters(methodBase.Modifiers.HasFlag(MethodSignatureModifiers.Public) ? methodBase.Parameters : methodBase.Parameters.Where(p => p.Description is not null)); - - WriteXmlDocumentationRequiredParametersException((IEnumerable)methodBase.Parameters); - WriteXmlDocumentationNonEmptyParametersException((IEnumerable)methodBase.Parameters); - if (methodBase is MethodSignature { ReturnDescription: { } } method) - { - WriteXmlDocumentationReturns(method.ReturnDescription); - } - - return this; - } - - public CodeWriter WriteXmlDocumentationInheritDoc(CSharpType? crefType = null) - => crefType == null - ? WriteLine($"/// ") - : WriteLine($"/// "); - - internal CodeWriter AppendXmlDocumentation(FormattableString startTag, FormattableString endTag, params FormattableString[] lines) - => AppendXmlDocumentation(startTag, endTag, (IReadOnlyList)lines); - - - internal CodeWriter AppendXmlDocumentation(FormattableString startTag, FormattableString endTag, IReadOnlyList lines) - { - Debug.Assert(!HasNewLines(lines, out var offendingLine), $"'{offendingLine!.ToString()}': contains a newline character. Split this into multiple entries instead."); - - _writingXmlDocumentation = true; - - if (lines.Count == 0 || IsEmpty(lines)) - { - WriteLine($"/// {startTag}{endTag}"); - } - else if (lines.Count == 1) - { - //should we auto add the '.'? - string lineFormat = lines[0].Format; - string stringToCheck = lineFormat; - if (lineFormat == SingleArgFormat && lines[0].ArgumentCount == 1 && lines[0].GetArgument(0) is string strLine) - { - stringToCheck = strLine; - } - string period = stringToCheck.EndsWith(".") ? string.Empty : "."; - WriteLine($"/// {startTag} {lines[0]}{period} {endTag}"); - } - else - { - WriteLine($"/// {startTag}"); - foreach (var line in lines) - { - WriteLine($"/// {line}"); - } - WriteLine($"/// {endTag}"); - } - - _writingXmlDocumentation = false; - - return this; - } - - private static bool IsEmpty(IReadOnlyList lines) - { - if (lines.Count != 1) - { - return false; - } - - string lineFormat = lines[0].Format; - if (lineFormat.Equals(string.Empty)) - { - return true; - } - - if (lineFormat != SingleArgFormat) - { - return false; - } - - var firstArg = lines[0].GetArgument(0); - return firstArg is not null && firstArg.Equals(string.Empty); - } - - private static bool HasNewLines(IReadOnlyList lines, [MaybeNullWhen(false)] out FormattableString offendingLine) - { - offendingLine = null; - foreach (var line in lines) - { - if (line.Format.Contains(_newLine)) - { - offendingLine = line; - return true; - } - for (int i = 0; i < line.ArgumentCount; i++) - { - if (line.GetArgument(i) is string str && str.Contains(_newLine)) - { - offendingLine = line; - return true; - } - } - } - return false; - } - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.XmlDocWritingScope.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.XmlDocWritingScope.cs new file mode 100644 index 0000000000..0226c8b156 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.XmlDocWritingScope.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Generator.CSharp +{ + internal partial class CodeWriter + { + internal class XmlDocWritingScope : IDisposable + { + private readonly CodeWriter _writer; + public XmlDocWritingScope(CodeWriter writer) + { + _writer = writer; + _writer._writingXmlDocumentation = true; + } + + public void Dispose() + { + _writer._writingXmlDocumentation = false; + } + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.cs index 3a849bf8b1..4800b7642b 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Writers/CodeWriter.cs @@ -24,8 +24,8 @@ internal sealed partial class CodeWriter : IDisposable private readonly Stack _scopes; private string? _currentNamespace; private UnsafeBufferSequence _builder; - private bool _writingXmlDocumentation; private bool _atBeginningOfLine; + private bool _writingXmlDocumentation; internal CodeWriter() { @@ -210,7 +210,7 @@ public void WriteMethod(MethodProvider method) { ArgumentNullException.ThrowIfNull(method, nameof(method)); - WriteMethodDocumentation(method.Signature); + WriteXmlDocs(method.XmlDocs); if (method.BodyStatements is { } body) { @@ -230,22 +230,35 @@ public void WriteMethod(MethodProvider method) } } - public void WriteProperty(PropertyProvider property) + private void WriteXmlDocs(XmlDocProvider? docs) { - if (property.Description is not null) + if (docs is null) + return; + + if (docs.Summary is not null) { - WriteXmlDocumentationSummary(property.Description); + docs.Summary.Write(this); } - // TODO -- should write parameter xml doc if this is an IndexerDeclaration: https://github.com/microsoft/typespec/issues/3276 + foreach (var param in docs.Params) + { + param.Write(this); + } - if (property.Exceptions is not null) + foreach (var exception in docs.Exceptions) { - foreach (var (exceptionType, description) in property.Exceptions) - { - WriteXmlDocumentationException(exceptionType, [description]); - } + exception.Write(this); + } + + if (docs.Returns is not null) + { + docs.Returns.Write(this); } + } + + public void WriteProperty(PropertyProvider property) + { + WriteXmlDocs(property.XmlDocs); var modifiers = property.Modifiers; AppendRawIf("public ", modifiers.HasFlag(MethodSignatureModifiers.Public)) @@ -359,42 +372,32 @@ public CodeWriter AppendRawIf(string str, bool condition) return this; } - public void WriteParameter(ParameterProvider clientParameter) + public void WriteParameter(ParameterProvider parameter) { - if (clientParameter.Attributes.Any()) + if (parameter.Attributes.Count > 0) { - AppendRaw("["); - for (int i = 0; i < clientParameter.Attributes.Length; i++) + parameter.Attributes[0].Write(this); + for (int i = 1; i < parameter.Attributes.Count; i++) { - if (i == 0) - { - Append($"{clientParameter.Attributes[i].Type}"); - } - else - { - Append($", {clientParameter.Attributes[i].Type}"); - } + AppendRaw(" "); + parameter.Attributes[i].Write(this); } - AppendRaw("]"); } - AppendRawIf("out ", clientParameter.IsOut); - AppendRawIf("ref ", clientParameter.IsRef); + AppendRawIf("out ", parameter.IsOut); + AppendRawIf("ref ", parameter.IsRef); - Append($"{clientParameter.Type} {clientParameter.Name:D}"); - if (clientParameter.DefaultValue != null) + Append($"{parameter.Type} {parameter.Name:D}"); + if (parameter.DefaultValue != null) { AppendRaw(" = "); - clientParameter.DefaultValue.Write(this); + parameter.DefaultValue.Write(this); } } public CodeWriter WriteField(FieldProvider field) { - if (field.Description != null) - { - WriteXmlDocumentationSummary([field.Description]); - } + WriteXmlDocs(field.XmlDocs); var modifiers = field.Modifiers; @@ -422,22 +425,6 @@ public CodeWriter WriteField(FieldProvider field) return WriteLine($";"); } - public CodeWriter WriteParametersValidation(IEnumerable parameters) - { - bool wroteValidation = false; - foreach (ParameterProvider parameter in parameters) - { - MethodBodyStatement validationStatement = Argument.ValidateParameter(parameter); - wroteValidation |= !validationStatement.Equals(EmptyStatement); - validationStatement.Write(this); - } - if (wroteValidation) - { - WriteLine(); - } - return this; - } - internal string GetTemporaryVariable(string s) { if (IsAvailable(s)) @@ -905,7 +892,7 @@ internal void WriteTypeModifiers(TypeSignatureModifiers modifiers) public void WriteTypeArguments(IEnumerable? typeArguments) { - if (typeArguments is null) + if (typeArguments is null || !typeArguments.Any()) { return; } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodCollectionTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodCollectionTests.cs index dd08e09b9e..df1ffec017 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodCollectionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodCollectionTests.cs @@ -47,7 +47,7 @@ public void Teardown() // Validate that the default method collection consists of the expected method kind(s) [TestCaseSource(nameof(DefaultCSharpMethodCollectionTestCases))] - public void TestDefaultCSharpMethodCollection(InputOperation inputOperation, CSharpMethodKinds expectedMethodKind) + public void TestDefaultCSharpMethodCollection(InputOperation inputOperation) { var methodCollection = CSharpMethodCollection.DefaultCSharpMethodCollection(inputOperation); @@ -55,8 +55,6 @@ public void TestDefaultCSharpMethodCollection(InputOperation inputOperation, CSh Assert.AreEqual(1, methodCollection?.Count); var method = methodCollection![0]; - Assert.AreEqual(expectedMethodKind, method.Kind); - var signature = method.Signature; Assert.IsNotNull(signature); Assert.AreEqual($"Create{inputOperation.Name.ToCleanName()}Request", signature.Name); @@ -92,7 +90,7 @@ public static IEnumerable DefaultCSharpMethodCollectionTestCases paging: null, generateProtocolMethod: true, generateConvenienceMethod: true - ), CSharpMethodKinds.CreateMessage); + )); } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodKindsTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodKindsTests.cs deleted file mode 100644 index 98c2e86f2b..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CSharpMethodKindsTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using NUnit.Framework; - -namespace Microsoft.Generator.CSharp.Tests -{ - internal class CSharpMethodKindsTests - { - [Test] - public void TestCustomKind() - { - var customKind = new CSharpMethodKinds("CustomKind"); - Assert.IsTrue("CustomKind" == customKind); - } - - [Test] - public void TestEquals() - { - Assert.IsTrue(CSharpMethodKinds.Convenience == "convenience"); - Assert.IsTrue(CSharpMethodKinds.Protocol == "protocol"); - Assert.IsTrue(CSharpMethodKinds.CreateMessage == "createMessage"); - - Assert.IsFalse(CSharpMethodKinds.Convenience == CSharpMethodKinds.Protocol); - Assert.IsFalse(CSharpMethodKinds.Protocol == CSharpMethodKinds.CreateMessage); - Assert.IsFalse(CSharpMethodKinds.CreateMessage == CSharpMethodKinds.Convenience); - } - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterExtensionTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterExtensionTests.cs index c7630a0168..2252c1b26a 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterExtensionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterExtensionTests.cs @@ -127,12 +127,9 @@ private static MethodProvider ConstructMockMethod() new KeywordStatement("return", responseVar) }; - var method = new MethodProvider - ( + var method = new MethodProvider( new MethodSignature(methodName, summary, description, methodSignatureModifiers, returnType, returnDescription, parameters), - resultStatements, - "GET" - ); + resultStatements); return method; } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterTests.cs index 383b359dd7..9b25fdde1c 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/CodeWriterTests.cs @@ -8,6 +8,7 @@ using System.Text; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Providers; +using Microsoft.Generator.CSharp.Statements; using NUnit.Framework; using static Microsoft.Generator.CSharp.Snippets.Snippet; @@ -164,7 +165,8 @@ public void EnumerableFormatInFormat() [Test] public void SingleLineSummary() { - _codeWriter.WriteXmlDocumentationSummary([$"Some {typeof(string)} summary."]); + var summary = new XmlDocSummaryStatement([$"Some {typeof(string)} summary."]); + summary.Write(_codeWriter); var expected = "/// Some string summary. " + NewLine; var sb = new StringBuilder(); sb.Append(_header); @@ -176,7 +178,8 @@ public void SingleLineSummary() [Test] public void NoEmptySummary() { - _codeWriter.WriteXmlDocumentationSummary([$"{string.Empty}"]); + var summary = new XmlDocSummaryStatement([$"{string.Empty}"]); + summary.Write(_codeWriter); var expected = "/// " + NewLine; var sb = new StringBuilder(); sb.Append(expected); @@ -193,7 +196,8 @@ public void NoEmptySummary() public void SeeCRefType(Type type, bool isNullable, string expectedWritten, string ns) { var csType = new CSharpType(type).WithNullable(isNullable); - _codeWriter.WriteXmlDocumentationSummary([$"Some {csType:C} summary."]); + var summary = new XmlDocSummaryStatement([$"Some {csType:C} summary."]); + summary.Write(_codeWriter); var expected = $"/// Some {expectedWritten} summary. " + NewLine; var sb = new StringBuilder(); sb.Append(_header); @@ -246,7 +250,8 @@ public void MultiLineSummary() fs.Add($"L15"); fs.Add($"L16"); - _codeWriter.WriteXmlDocumentationSummary(fs); + var summary = new XmlDocSummaryStatement(fs); + summary.Write(_codeWriter); var sb = new StringBuilder(); sb.Append(_header); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Models/PropertyDescriptionTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Models/PropertyDescriptionTests.cs index b4a18a6231..664cfd0356 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Models/PropertyDescriptionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Models/PropertyDescriptionTests.cs @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using Microsoft.Generator.CSharp.Input; +using Microsoft.Generator.CSharp.Statements; using NUnit.Framework; -using System.Collections.Generic; -using System; -using System.Linq; namespace Microsoft.Generator.CSharp.Tests { @@ -48,7 +48,8 @@ public void TestGetUnionTypesDescriptions() Assert.AreEqual(7, descriptions.Count); using var codeWriter = new CodeWriter(); - codeWriter.AppendXmlDocumentation($"", $"", descriptions); + var xmlDoc = new XmlDocStatement($"", $"", descriptions); + xmlDoc.Write(codeWriter); var actual = codeWriter.ToString(false); var expected = string.Join("\n", diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/ParameterProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/ParameterProviderTests.cs index cd94342cda..fbd67a7fcc 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/ParameterProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/ParameterProviderTests.cs @@ -45,14 +45,8 @@ private static IEnumerable NotEqualsTestCases() new ParameterProvider("name1", $"Description", new CSharpType(typeof(string))), false); yield return new TestCaseData( - new ParameterProvider("name", $"Description", new CSharpType(typeof(string))) - { - Attributes = [new(new CSharpType(typeof(int)), [])] - }, - new ParameterProvider("name1", $"Description", new CSharpType(typeof(string))) - { - Attributes = [new(new CSharpType(typeof(string)), [])] - }, + new ParameterProvider("name", $"Description", new CSharpType(typeof(string)), attributes: [new(new CSharpType(typeof(int)), [])]), + new ParameterProvider("name1", $"Description", new CSharpType(typeof(string)), attributes: [new(new CSharpType(typeof(string)), [])]), false); } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/StatementTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/StatementTests.cs index 077af7aba5..5863a2c8f1 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/StatementTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/StatementTests.cs @@ -137,7 +137,7 @@ public void IfStatementWithDefaultOptions() public void IfStatementInlineOptionTrue() { var condition = new BoolSnippet(BoolSnippet.True); - var ifStatement = new IfStatement(condition, Inline: true); + var ifStatement = new IfStatement(condition, inline: true); Assert.IsTrue(ifStatement.Inline); } @@ -146,7 +146,7 @@ public void IfStatementInlineOptionTrue() public void IfStatementAddBracesOptionFalse() { var condition = new BoolSnippet(BoolSnippet.True); - var ifStatement = new IfStatement(condition, AddBraces: false); + var ifStatement = new IfStatement(condition, addBraces: false); Assert.IsFalse(ifStatement.AddBraces); } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/UnbrandedTypeSpecClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/UnbrandedTypeSpecClient.cs index 93fb6a361f..51ef756e33 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/UnbrandedTypeSpecClient.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/UnbrandedTypeSpecClient.cs @@ -15,7 +15,6 @@ public partial class UnbrandedTypeSpecClient /// /// /// - /// , , or is null. internal void CreateSayHiRequest(System.Uri unbrandedTypeSpecUrl, string headParameter, string queryParameter, string optionalQuery, string accept) { } @@ -27,7 +26,6 @@ internal void CreateSayHiRequest(System.Uri unbrandedTypeSpecUrl, string headPar /// /// /// - /// , , , , or is null. internal void CreateHelloAgainRequest(System.Uri unbrandedTypeSpecUrl, string p1, string contentType, string p2, RoundTripModel action, string accept) { } @@ -39,7 +37,6 @@ internal void CreateHelloAgainRequest(System.Uri unbrandedTypeSpecUrl, string p1 /// /// /// - /// , , , , or is null. internal void CreateNoContentTypeRequest(System.Uri unbrandedTypeSpecUrl, string p1, string p2, RoundTripModel action, string accept, string contentType) { } @@ -47,7 +44,6 @@ internal void CreateNoContentTypeRequest(System.Uri unbrandedTypeSpecUrl, string /// Return hi in demo2. /// /// - /// or is null. internal void CreateHelloDemo2Request(System.Uri unbrandedTypeSpecUrl, string accept) { } @@ -57,7 +53,6 @@ internal void CreateHelloDemo2Request(System.Uri unbrandedTypeSpecUrl, string ac /// /// /// - /// , , or is null. internal void CreateCreateLiteralRequest(System.Uri unbrandedTypeSpecUrl, Thing body, string accept, string contentType) { } @@ -68,7 +63,6 @@ internal void CreateCreateLiteralRequest(System.Uri unbrandedTypeSpecUrl, Thing /// /// /// - /// , , , or is null. internal void CreateHelloLiteralRequest(System.Uri unbrandedTypeSpecUrl, string p1, int p2, bool p3, string accept) { } @@ -77,7 +71,6 @@ internal void CreateHelloLiteralRequest(System.Uri unbrandedTypeSpecUrl, string /// /// /// - /// , or is null. internal void CreateTopActionRequest(System.Uri unbrandedTypeSpecUrl, DateTimeOffset action, string accept) { } @@ -85,7 +78,6 @@ internal void CreateTopActionRequest(System.Uri unbrandedTypeSpecUrl, DateTimeOf /// top level method2. /// /// - /// or is null. internal void CreateTopAction2Request(System.Uri unbrandedTypeSpecUrl, string accept) { } @@ -95,7 +87,6 @@ internal void CreateTopAction2Request(System.Uri unbrandedTypeSpecUrl, string ac /// /// /// - /// , , or is null. internal void CreatePatchActionRequest(System.Uri unbrandedTypeSpecUrl, Thing body, string accept, string contentType) { } @@ -105,7 +96,6 @@ internal void CreatePatchActionRequest(System.Uri unbrandedTypeSpecUrl, Thing bo /// A model with a few properties of literal types. /// /// - /// , , or is null. internal void CreateAnonymousBodyRequest(System.Uri unbrandedTypeSpecUrl, Thing Thing, string accept, string contentType) { } @@ -115,7 +105,6 @@ internal void CreateAnonymousBodyRequest(System.Uri unbrandedTypeSpecUrl, Thing /// this is not a friendly model but with a friendly name. /// /// - /// , , or is null. internal void CreateFriendlyModelRequest(System.Uri unbrandedTypeSpecUrl, Friend Friend, string accept, string contentType) { } @@ -124,7 +113,6 @@ internal void CreateFriendlyModelRequest(System.Uri unbrandedTypeSpecUrl, Friend /// /// /// - /// or is null. internal void CreateAddTimeHeaderRequest(System.Uri unbrandedTypeSpecUrl, DateTimeOffset repeatabilityFirstSent, string accept) { } @@ -134,7 +122,6 @@ internal void CreateAddTimeHeaderRequest(System.Uri unbrandedTypeSpecUrl, DateTi /// this is a model with a projected name. /// /// - /// , , or is null. internal void CreateProjectedNameModelRequest(System.Uri unbrandedTypeSpecUrl, ProjectedModel ProjectedModel, string accept, string contentType) { } @@ -142,7 +129,6 @@ internal void CreateProjectedNameModelRequest(System.Uri unbrandedTypeSpecUrl, P /// return anonymous model. /// /// - /// or is null. internal void CreateReturnsAnonymousModelRequest(System.Uri unbrandedTypeSpecUrl, string accept) { } @@ -150,7 +136,6 @@ internal void CreateReturnsAnonymousModelRequest(System.Uri unbrandedTypeSpecUrl /// get extensible enum. /// /// - /// or is null. internal void CreateGetUnknownValueRequest(System.Uri unbrandedTypeSpecUrl, string accept) { } @@ -160,7 +145,6 @@ internal void CreateGetUnknownValueRequest(System.Uri unbrandedTypeSpecUrl, stri /// /// /// - /// , , or is null. internal void CreateInternalProtocolRequest(System.Uri unbrandedTypeSpecUrl, Thing body, string accept, string contentType) { } @@ -168,7 +152,6 @@ internal void CreateInternalProtocolRequest(System.Uri unbrandedTypeSpecUrl, Thi /// When set protocol false and convenient true, the convenient method should be generated even it has the same signature as protocol one. /// /// - /// or is null. internal void CreateStillConvenientRequest(System.Uri unbrandedTypeSpecUrl, string accept) { } @@ -177,7 +160,6 @@ internal void CreateStillConvenientRequest(System.Uri unbrandedTypeSpecUrl, stri /// /// /// - /// , or is null. internal void CreateHeadAsBooleanRequest(System.Uri unbrandedTypeSpecUrl, string id, string accept) { }