From eab1de1896fc7f46bdeb4cedf8cb54308edfe408 Mon Sep 17 00:00:00 2001 From: Timothy Makkison Date: Thu, 10 Oct 2024 14:27:36 +0100 Subject: [PATCH] feat: use `ToArray`, rename variables --- InterfaceStubGenerator.Shared/Emitter.cs | 39 +++++++++---------- .../ImmutableEquatableArray.cs | 6 ++- InterfaceStubGenerator.Shared/Parser.cs | 38 +++++++++++------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/InterfaceStubGenerator.Shared/Emitter.cs b/InterfaceStubGenerator.Shared/Emitter.cs index 5f42378a9..48a3948e8 100644 --- a/InterfaceStubGenerator.Shared/Emitter.cs +++ b/InterfaceStubGenerator.Shared/Emitter.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis.Text; namespace Refit.Generator; @@ -116,24 +117,24 @@ partial class {model.Ns}{model.ClassDeclaration} // Handle Refit Methods foreach (var method in model.RefitMethods) { - EmitRefitMethod(source, method, true, memberNames); + WriteRefitMethod(source, method, true, memberNames); } foreach (var method in model.DerivedRefitMethods) { - EmitRefitMethod(source, method, false, memberNames); + WriteRefitMethod(source, method, false, memberNames); } // Handle non-refit Methods that aren't static or properties or have a method body foreach (var method in model.NonRefitMethods) { - ProcessNonRefitMethod(source, method); + WriteNonRefitMethod(source, method); } // Handle Dispose if (model.DisposeMethod) { - ProcessDisposableMethod(source); + WriteDisposableMethod(source); } source.Append( @@ -155,7 +156,7 @@ partial class {model.Ns}{model.ClassDeclaration} /// /// True if directly from the type we're generating for, false for methods found on base interfaces /// Contains the unique member names in the interface scope. - private static void EmitRefitMethod( + private static void WriteRefitMethod( StringBuilder source, MethodModel methodModel, bool isTopLevel, @@ -185,26 +186,24 @@ HashSet memberNames WriteMethodOpening(source, methodModel, !isTopLevel, isAsync); // Build the list of args for the array - var argList = new List(); - foreach (var param in methodModel.Parameters) - { - argList.Add($"@{param.MetadataName}"); - } + var argList = methodModel + .Parameters.AsArray() + .Select(static param => $"@{param.MetadataName}") + .ToArray(); // List of generic arguments - var genericList = new List(); - foreach (var typeParam in methodModel.Constraints) - { - genericList.Add($"typeof({typeParam.DeclaredName})"); - } + var genericList = methodModel + .Constraints.AsArray() + .Select(static typeParam => $"typeof({typeParam.DeclaredName})") + .ToArray(); var argumentsArrayString = - argList.Count == 0 + argList.Length == 0 ? "global::System.Array.Empty()" : $"new object[] {{ {string.Join(", ", argList)} }}"; var genericString = - genericList.Count > 0 + genericList.Length > 0 ? $", new global::System.Type[] {{ {string.Join(", ", genericList)} }}" : string.Empty; @@ -220,7 +219,7 @@ HashSet memberNames WriteMethodClosing(source); } - private static void ProcessNonRefitMethod(StringBuilder source, MethodModel methodModel) + private static void WriteNonRefitMethod(StringBuilder source, MethodModel methodModel) { WriteMethodOpening(source, methodModel, true); @@ -236,7 +235,7 @@ private static void ProcessNonRefitMethod(StringBuilder source, MethodModel meth // TODO: This assumes that the Dispose method is a void that takes no parameters. // The previous version did not. // Does the bool overload cause an issue here. - private static void ProcessDisposableMethod(StringBuilder source) + private static void WriteDisposableMethod(StringBuilder source) { source.Append( """ diff --git a/InterfaceStubGenerator.Shared/ImmutableEquatableArray.cs b/InterfaceStubGenerator.Shared/ImmutableEquatableArray.cs index 865cee1bc..ba3e07102 100644 --- a/InterfaceStubGenerator.Shared/ImmutableEquatableArray.cs +++ b/InterfaceStubGenerator.Shared/ImmutableEquatableArray.cs @@ -2,7 +2,7 @@ namespace Refit.Generator; -public static class ImmutableEquatableArray +internal static class ImmutableEquatableArray { public static ImmutableEquatableArray Empty() where T : IEquatable => ImmutableEquatableArray.Empty; @@ -17,7 +17,7 @@ this IEnumerable? values /// Provides an immutable list implementation which implements sequence equality. /// TODO: Convert to struct /// -public sealed class ImmutableEquatableArray +internal sealed class ImmutableEquatableArray : IEquatable>, IReadOnlyList where T : IEquatable @@ -32,6 +32,8 @@ public sealed class ImmutableEquatableArray public ImmutableEquatableArray(IEnumerable values) => _values = values.ToArray(); + public T[] AsArray() => _values; + public bool Equals(ImmutableEquatableArray? other) => other != null && ((ReadOnlySpan)_values).SequenceEqual(other._values); diff --git a/InterfaceStubGenerator.Shared/Parser.cs b/InterfaceStubGenerator.Shared/Parser.cs index 6665c5a1b..04a5e7b97 100644 --- a/InterfaceStubGenerator.Shared/Parser.cs +++ b/InterfaceStubGenerator.Shared/Parser.cs @@ -71,7 +71,10 @@ CancellationToken cancellationToken foreach (var method in group) { // Get the symbol being declared by the method - var methodSymbol = model.GetDeclaredSymbol(method, cancellationToken: cancellationToken); + var methodSymbol = model.GetDeclaredSymbol( + method, + cancellationToken: cancellationToken + ); if (!IsRefitMethod(methodSymbol, httpMethodBaseAttributeSymbol)) continue; @@ -89,11 +92,11 @@ CancellationToken cancellationToken m => m.ContainingType, SymbolEqualityComparer.Default ) - .ToDictionary, INamedTypeSymbol, List>( - g => g.Key, - v => [.. v], - SymbolEqualityComparer.Default - ); + .ToDictionary< + IGrouping, + INamedTypeSymbol, + List + >(g => g.Key, v => [.. v], SymbolEqualityComparer.Default); // Look through the candidate interfaces var interfaceSymbols = new List(); @@ -103,7 +106,10 @@ CancellationToken cancellationToken foreach (var iface in group) { // get the symbol belonging to the interface - var ifaceSymbol = model.GetDeclaredSymbol(iface, cancellationToken: cancellationToken); + var ifaceSymbol = model.GetDeclaredSymbol( + iface, + cancellationToken: cancellationToken + ); // See if we already know about it, might be a dup if (ifaceSymbol is null || interfaces.ContainsKey(ifaceSymbol)) @@ -170,7 +176,11 @@ sealed class PreserveAttribute : global::System.Attribute // Is it needed in order to get the preserve attribute display name. // Will the compilation ever change this. compilation = compilation.AddSyntaxTrees( - CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options, cancellationToken: cancellationToken) + CSharpSyntaxTree.ParseText( + SourceText.From(attributeText, Encoding.UTF8), + options, + cancellationToken: cancellationToken + ) ); // get the newly bound attribute @@ -266,7 +276,7 @@ bool nullableEnabled .OfType() .Except(refitMethods, SymbolEqualityComparer.Default) .Cast() - .ToList(); + .ToArray(); // get methods for all inherited var derivedMethods = interfaceSymbol @@ -288,11 +298,11 @@ bool nullableEnabled // Pull out the refit methods from the derived types var derivedRefitMethods = derivedMethods .Where(m => IsRefitMethod(m, httpMethodBaseAttributeSymbol)) - .ToList(); + .ToArray(); var derivedNonRefitMethods = derivedMethods .Except(derivedMethods, SymbolEqualityComparer.Default) .Cast() - .ToList(); + .ToArray(); var memberNames = interfaceSymbol .GetMembers() @@ -369,7 +379,7 @@ List diagnostics diagnostics.Add(diagnostic); } - return ParseMethod(methodSymbol, true); + return ParseMethod(methodSymbol, false); } private static bool IsRefitMethod( @@ -476,7 +486,7 @@ private static bool ContainsTypeParameter(ITypeSymbol symbol) return false; } - private static MethodModel ParseMethod(IMethodSymbol methodSymbol, bool isExplicitInterface) + private static MethodModel ParseMethod(IMethodSymbol methodSymbol, bool isImplicitInterface) { var returnType = methodSymbol.ReturnType.ToDisplayString( SymbolDisplayFormat.FullyQualifiedFormat @@ -495,7 +505,7 @@ private static MethodModel ParseMethod(IMethodSymbol methodSymbol, bool isExplic var parameters = methodSymbol.Parameters.Select(ParseParameter).ToImmutableEquatableArray(); - var constraints = GenerateConstraints(methodSymbol.TypeParameters, !isExplicitInterface); + var constraints = GenerateConstraints(methodSymbol.TypeParameters, !isImplicitInterface); return new MethodModel( methodSymbol.Name,