From d2923d5587ec9b6658cc46fd28e1223b15919bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:11:40 -0800 Subject: [PATCH 1/2] Move TryGetRecordConstructor from Microsoft.DotNet.GenAPI.INamedTypeSymbolExtesions up to Microsoft.DotNet.ApiSymbolExtensions.SymbolExtensions. --- .../INamedTypeSymbolExtensions.cs | 31 +------------------ .../Microsoft.DotNet.GenAPI.csproj | 4 --- .../SyntaxGeneratorExtensions.cs | 1 + ...icrosoft.DotNet.ApiSymbolExtensions.csproj | 1 + .../SymbolExtensions.cs | 29 +++++++++++++++++ 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/INamedTypeSymbolExtensions.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/INamedTypeSymbolExtensions.cs index fdbee7992df1..6d5d6ec8e054 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/INamedTypeSymbolExtensions.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/INamedTypeSymbolExtensions.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -224,7 +223,7 @@ static bool IncludeInternalSymbols(ISymbolFilter filter) => yield return constructor; } - // Synthesize a base class initializer. + // Synthesize a base class initializer. public static ConstructorInitializerSyntax GenerateBaseConstructorInitializer(this IMethodSymbol baseTypeConstructor) { return SyntaxFactory.ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, baseTypeConstructor.CreateDefaultArgumentList()); @@ -248,33 +247,5 @@ public static ArgumentListSyntax CreateDefaultArgumentList(this IMethodSymbol me return argumentList; } - - // Locates constructor generated by the compiler for `record Foo(...)` syntax - // If the type is a record and the compiler generated constructor is found it will be returned, otherwise null. - // The compiler will not generate a constructor in the case where the user defined it themself without using an argument list - // in the record declaration, or if the record has no parameters. - public static bool TryGetRecordConstructor(this INamedTypeSymbol type, [NotNullWhen(true)] out IMethodSymbol? recordConstructor) - { - if (!type.IsRecord) - { - recordConstructor = null; - return false; - } - - // Locate the compiler generated Deconstruct method. - var deconstructMethod = (IMethodSymbol?)type.GetMembers("Deconstruct") - .FirstOrDefault(m => m is IMethodSymbol && m.IsCompilerGenerated()); - - // Locate the compiler generated constructor by matching parameters to Deconstruct - since we cannot locate it with an attribute. - recordConstructor = (IMethodSymbol?)type.GetMembers(".ctor") - .FirstOrDefault(m => m is IMethodSymbol method && - method.MethodKind == MethodKind.Constructor && - (deconstructMethod == null ? - method.Parameters.IsEmpty : - method.Parameters.Select(p => p.Type).SequenceEqual( - deconstructMethod.Parameters.Select(p => p.Type), SymbolEqualityComparer.Default))); - - return recordConstructor != null; - } } } diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/Microsoft.DotNet.GenAPI.csproj b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/Microsoft.DotNet.GenAPI.csproj index 1966bb66ab05..0c382c85d75f 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/Microsoft.DotNet.GenAPI.csproj +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/Microsoft.DotNet.GenAPI.csproj @@ -4,10 +4,6 @@ $(NetToolMinimum);$(NetFrameworkToolCurrent) - - - - diff --git a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/SyntaxGeneratorExtensions.cs b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/SyntaxGeneratorExtensions.cs index 1201e4db2336..6618d47a20b1 100644 --- a/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/SyntaxGeneratorExtensions.cs +++ b/src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/SyntaxGeneratorExtensions.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; +using Microsoft.DotNet.ApiSymbolExtensions; using Microsoft.DotNet.ApiSymbolExtensions.Filtering; namespace Microsoft.DotNet.GenAPI diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Microsoft.DotNet.ApiSymbolExtensions.csproj b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Microsoft.DotNet.ApiSymbolExtensions.csproj index c531b3bd79a7..c9d256170375 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Microsoft.DotNet.ApiSymbolExtensions.csproj +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Microsoft.DotNet.ApiSymbolExtensions.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs index 8e7e44b929bc..c8a9b5239cb7 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; namespace Microsoft.DotNet.ApiSymbolExtensions @@ -126,5 +127,33 @@ public static bool IsEventAdderOrRemover(this IMethodSymbol method) => method.MethodKind == MethodKind.EventRemove || method.Name.StartsWith("add_", StringComparison.Ordinal) || method.Name.StartsWith("remove_", StringComparison.Ordinal); + + // Locates constructor generated by the compiler for `record Foo(...)` syntax + // If the type is a record and the compiler generated constructor is found it will be returned, otherwise null. + // The compiler will not generate a constructor in the case where the user defined it themself without using an argument list + // in the record declaration, or if the record has no parameters. + public static bool TryGetRecordConstructor(this INamedTypeSymbol type, [NotNullWhen(true)] out IMethodSymbol? recordConstructor) + { + if (!type.IsRecord) + { + recordConstructor = null; + return false; + } + + // Locate the compiler generated Deconstruct method. + var deconstructMethod = (IMethodSymbol?)type.GetMembers("Deconstruct") + .FirstOrDefault(m => m is IMethodSymbol && m.IsCompilerGenerated()); + + // Locate the compiler generated constructor by matching parameters to Deconstruct - since we cannot locate it with an attribute. + recordConstructor = (IMethodSymbol?)type.GetMembers(".ctor") + .FirstOrDefault(m => m is IMethodSymbol method && + method.MethodKind == MethodKind.Constructor && + (deconstructMethod == null ? + method.Parameters.IsEmpty : + method.Parameters.Select(p => p.Type).SequenceEqual( + deconstructMethod.Parameters.Select(p => p.Type), SymbolEqualityComparer.Default))); + + return recordConstructor != null; + } } } From 31f48748862518f6c75c523957e99d03da999b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 9 Jan 2025 08:08:45 -0800 Subject: [PATCH 2/2] Triple slash comments properly formatted. --- .../SymbolExtensions.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs index c8a9b5239cb7..b37fde068940 100644 --- a/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs +++ b/src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/SymbolExtensions.cs @@ -128,10 +128,14 @@ public static bool IsEventAdderOrRemover(this IMethodSymbol method) => method.Name.StartsWith("add_", StringComparison.Ordinal) || method.Name.StartsWith("remove_", StringComparison.Ordinal); - // Locates constructor generated by the compiler for `record Foo(...)` syntax - // If the type is a record and the compiler generated constructor is found it will be returned, otherwise null. - // The compiler will not generate a constructor in the case where the user defined it themself without using an argument list - // in the record declaration, or if the record has no parameters. + /// + /// Attempts to locate and return the constructor generated by the compiler for `record Foo(...)` syntax. + /// The compiler will not generate a constructor in the case where the user defined it themself without using an argument list + /// in the record declaration, or if the record has no parameters. + /// + /// The type to check for a compiler generated constructor. + /// When this method returns , then the compiler generated constructor for the record is stored in this out parameter, otherwise it becomes . + /// if the type is a record and the compiler generated constructor is found, otherwise . public static bool TryGetRecordConstructor(this INamedTypeSymbol type, [NotNullWhen(true)] out IMethodSymbol? recordConstructor) { if (!type.IsRecord)