From 839a71266d20d143418ad2e30bbacc8a300084d7 Mon Sep 17 00:00:00 2001 From: Mateo Torres Ruiz Date: Thu, 2 Sep 2021 18:19:12 -0700 Subject: [PATCH 1/5] Add support in RUC analyzer for new() constraint on generics --- .../ISymbolExtensions.cs | 13 ++++++ .../RequiresAnalyzerBase.cs | 2 +- .../RequiresUnreferencedCodeAnalyzer.cs | 44 ++++++++++++++++++- .../RequiresUnreferencedCodeCapability.cs | 3 +- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs index 5693bd507981..952d6ecbc5cd 100644 --- a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs +++ b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs @@ -22,6 +22,19 @@ internal static bool HasAttribute (this ISymbol symbol, string attributeName) return false; } + internal static bool TryGetAttribute (this ISymbol member, string attributeName, [NotNullWhen (returnValue: true)] out AttributeData? attribute) + { + attribute = null; + foreach (var attr in member.GetAttributes ()) { + if (attr.AttributeClass is { } attrClass && attrClass.HasName (attributeName)) { + attribute = attr; + return true; + } + } + + return false; + } + internal static bool TryGetOverriddenMember (this ISymbol? symbol, [NotNullWhen (returnValue: true)] out ISymbol? overridenMember) { overridenMember = symbol switch { diff --git a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs index 7befde2450a5..bae7f3806f2d 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs @@ -263,7 +263,7 @@ private void ReportMismatchInAttributesDiagnostic (SymbolAnalysisContext symbolA protected abstract string GetMessageFromAttribute (AttributeData requiresAttribute); - private string GetUrlFromAttribute (AttributeData? requiresAttribute) + public static string GetUrlFromAttribute (AttributeData? requiresAttribute) { var url = requiresAttribute?.NamedArguments.FirstOrDefault (na => na.Key == "Url").Value.Value?.ToString (); return MessageFormat.FormatRequiresAttributeUrlArg (url); diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs index 0beae2c75988..e31a12d163e7 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs @@ -7,6 +7,7 @@ using ILLink.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; namespace ILLink.RoslynAnalyzer { @@ -31,6 +32,38 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase operationContext.Operation.Syntax.GetLocation ())); }; + static readonly Action s_constructorConstraint = operationContext => { + var invocationOperation = (IInvocationOperation) operationContext.Operation; + if (FindContainingSymbol (operationContext, DiagnosticTargets.All) is not ISymbol containingSymbol || + containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute)) + return; + + var targetMethod = invocationOperation.TargetMethod; + if (!targetMethod.IsGenericMethod) + return; + + for (int i = 0; i < targetMethod.TypeParameters.Length; i++) { + var typeParameter = targetMethod.TypeParameters[i]; + var typeArgument = targetMethod.TypeArguments[i]; + if (!typeParameter.HasConstructorConstraint) + continue; + + var typeArgCtors = ((INamedTypeSymbol) typeArgument).InstanceConstructors; + foreach (var instanceCtor in typeArgCtors) { + if (instanceCtor.Arity > 0) + continue; + + if (instanceCtor.TryGetAttribute (RequiresUnreferencedCodeAttribute, out var requiresUnreferencedCodeAttribute)) { + operationContext.ReportDiagnostic (Diagnostic.Create (s_requiresUnreferencedCodeRule, + operationContext.Operation.Syntax.GetLocation (), + containingSymbol.GetDisplayName (), + (string) requiresUnreferencedCodeAttribute.ConstructorArguments[0].Value!, + GetUrlFromAttribute (requiresUnreferencedCodeAttribute))); + } + } + } + }; + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (s_dynamicTypeInvocationRule, s_requiresUnreferencedCodeRule, s_requiresUnreferencedCodeAttributeMismatch); @@ -47,8 +80,15 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation compilation) => options.IsMSBuildPropertyValueTrue (MSBuildPropertyOptionNames.EnableTrimAnalyzer, compilation); - private protected override ImmutableArray<(Action Action, OperationKind[] OperationKind)> ExtraOperationActions => - ImmutableArray.Create ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation })); + private protected override ImmutableArray<(Action Action, OperationKind[] OperationKind)> ExtraOperationActions { + get { + var diagsBuilder = ImmutableArray.CreateBuilder<(Action, OperationKind[])> (); + diagsBuilder.Add ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation })); + diagsBuilder.Add ((s_constructorConstraint, new OperationKind[] { OperationKind.Invocation })); + + return diagsBuilder.ToImmutable (); + } + } protected override bool VerifyAttributeArguments (AttributeData attribute) => attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg; diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs index ac6dab4e052d..406dcfb5b7b6 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs @@ -778,8 +778,7 @@ public NewConstrainTestType () { } static void GenericMethod () where T : new() { } - // https://github.com/mono/linker/issues/2117 - [ExpectedWarning ("IL2026", "--NewConstrainTestType.ctor--", GlobalAnalysisOnly = true)] + [ExpectedWarning ("IL2026", "--NewConstrainTestType.ctor--")] public static void Test () { GenericMethod (); From d1e24681c5b7e1b45a93b63cd98cf6c3e2010e8c Mon Sep 17 00:00:00 2001 From: Mateo Torres Ruiz Date: Fri, 3 Sep 2021 14:16:32 -0700 Subject: [PATCH 2/5] Support `new()` constraint on types --- .../RequiresAnalyzerBase.cs | 2 +- .../RequiresUnreferencedCodeAnalyzer.cs | 28 +++++++++++++------ .../RequiresUnreferencedCodeCapability.cs | 21 ++++++++++---- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs index bae7f3806f2d..9bdaaf265910 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs @@ -35,8 +35,8 @@ public override void Initialize (AnalysisContext context) var compilation = context.Compilation; if (!IsAnalyzerEnabled (context.Options, compilation)) return; - var incompatibleMembers = GetSpecialIncompatibleMembers (compilation); + var incompatibleMembers = GetSpecialIncompatibleMembers (compilation); context.RegisterSymbolAction (symbolAnalysisContext => { var methodSymbol = (IMethodSymbol) symbolAnalysisContext.Symbol; CheckMatchingAttributesInOverrides (symbolAnalysisContext, methodSymbol); diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs index e31a12d163e7..28e756212e6b 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using ILLink.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -32,19 +33,30 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase operationContext.Operation.Syntax.GetLocation ())); }; + [SuppressMessage ("MicrosoftCodeAnalysisPerformance", "RS1008", + Justification = "This action is registered through a compilation start action, so that the instances which " + + "can register this operation action will not outlive a compilation's lifetime, avoiding the possibility of " + + "this data causing stale compilations to remain in memory.")] static readonly Action s_constructorConstraint = operationContext => { - var invocationOperation = (IInvocationOperation) operationContext.Operation; if (FindContainingSymbol (operationContext, DiagnosticTargets.All) is not ISymbol containingSymbol || containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute)) return; - var targetMethod = invocationOperation.TargetMethod; - if (!targetMethod.IsGenericMethod) - return; + var typeParams = ImmutableArray.Empty; + var typeArgs = ImmutableArray.Empty; + if (operationContext.Operation is IObjectCreationOperation objectCreationOperation && + objectCreationOperation.Type is INamedTypeSymbol objectType && objectType.IsGenericType) { + typeParams = objectType.TypeParameters; + typeArgs = objectType.TypeArguments; + } else if (operationContext.Operation is IInvocationOperation invocationOperation && + invocationOperation.TargetMethod is IMethodSymbol targetMethod && targetMethod.IsGenericMethod) { + typeParams = targetMethod.TypeParameters; + typeArgs = targetMethod.TypeArguments; + } - for (int i = 0; i < targetMethod.TypeParameters.Length; i++) { - var typeParameter = targetMethod.TypeParameters[i]; - var typeArgument = targetMethod.TypeArguments[i]; + for (int i = 0; i < typeParams.Length; i++) { + var typeParameter = typeParams[i]; + var typeArgument = typeArgs[i]; if (!typeParameter.HasConstructorConstraint) continue; @@ -84,7 +96,7 @@ protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation get { var diagsBuilder = ImmutableArray.CreateBuilder<(Action, OperationKind[])> (); diagsBuilder.Add ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation })); - diagsBuilder.Add ((s_constructorConstraint, new OperationKind[] { OperationKind.Invocation })); + diagsBuilder.Add ((s_constructorConstraint, new OperationKind[] { OperationKind.Invocation, OperationKind.ObjectCreation })); return diagsBuilder.ToImmutable (); } diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs index 406dcfb5b7b6..7442a368fd7a 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs @@ -80,6 +80,7 @@ public static void Main () AccessThroughPInvoke.Test (); OnEventMethod.Test (); AccessThroughNewConstraint.Test (); + AccessThroughNewConstraint.TestNewConstraintOnTypeParameter (); AccessThroughLdToken.Test (); RequiresOnClass.Test (); } @@ -770,18 +771,28 @@ public static void Test () class AccessThroughNewConstraint { - class NewConstrainTestType + class NewConstraintTestType { - [RequiresUnreferencedCode ("Message for --NewConstrainTestType.ctor--")] - public NewConstrainTestType () { } + [RequiresUnreferencedCode ("Message for --NewConstraintTestType.ctor--")] + public NewConstraintTestType () { } } static void GenericMethod () where T : new() { } - [ExpectedWarning ("IL2026", "--NewConstrainTestType.ctor--")] + [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] public static void Test () { - GenericMethod (); + GenericMethod (); + } + + class NewConstaintOnTypeParameter where T : new() + { + } + + [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] + public static void TestNewConstraintOnTypeParameter () + { + _ = new NewConstaintOnTypeParameter (); } } From a5af97c60531f7a8815b262873676e65faf247a8 Mon Sep 17 00:00:00 2001 From: Mateo Torres Ruiz Date: Tue, 7 Sep 2021 18:37:26 -0700 Subject: [PATCH 3/5] Use SyntaxNodeAnalysisContext for constructor constraints --- .../RequiresAnalyzerBase.cs | 6 ++ .../RequiresUnreferencedCodeAnalyzer.cs | 55 ++++++++++--------- .../RequiresUnreferencedCodeCapability.cs | 12 ++++ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs index 9bdaaf265910..2ed43d286d02 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs @@ -8,6 +8,7 @@ using System.Linq; using ILLink.Shared; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; @@ -27,6 +28,8 @@ public abstract class RequiresAnalyzerBase : DiagnosticAnalyzer private protected virtual ImmutableArray<(Action Action, OperationKind[] OperationKind)> ExtraOperationActions { get; } = ImmutableArray<(Action Action, OperationKind[] OperationKind)>.Empty; + private protected virtual ImmutableArray<(Action Action, SyntaxKind[] SyntaxKind)> ExtraSyntaxNodeActions { get; } = ImmutableArray<(Action Action, SyntaxKind[] SyntaxKind)>.Empty; + public override void Initialize (AnalysisContext context) { context.EnableConcurrentExecution (); @@ -119,6 +122,9 @@ public override void Initialize (AnalysisContext context) foreach (var extraOperationAction in ExtraOperationActions) context.RegisterOperationAction (extraOperationAction.Action, extraOperationAction.OperationKind); + foreach (var extraSyntaxNodeAction in ExtraSyntaxNodeActions) + context.RegisterSyntaxNodeAction (extraSyntaxNodeAction.Action, extraSyntaxNodeAction.SyntaxKind); + void CheckStaticConstructors (OperationAnalysisContext operationContext, ImmutableArray staticConstructors) { diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs index 28e756212e6b..eb4acb90876d 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs @@ -7,8 +7,9 @@ using System.Diagnostics.CodeAnalysis; using ILLink.Shared; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Operations; namespace ILLink.RoslynAnalyzer { @@ -37,37 +38,43 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase Justification = "This action is registered through a compilation start action, so that the instances which " + "can register this operation action will not outlive a compilation's lifetime, avoiding the possibility of " + "this data causing stale compilations to remain in memory.")] - static readonly Action s_constructorConstraint = operationContext => { - if (FindContainingSymbol (operationContext, DiagnosticTargets.All) is not ISymbol containingSymbol || - containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute)) + static readonly Action s_constructorConstraint = syntaxNodeAnalysisContext => { + var model = syntaxNodeAnalysisContext.SemanticModel; + if (syntaxNodeAnalysisContext.ContainingSymbol is not ISymbol containingSymbol || containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute)) return; + GenericNameSyntax genericNameSyntaxNode = (GenericNameSyntax) syntaxNodeAnalysisContext.Node; var typeParams = ImmutableArray.Empty; var typeArgs = ImmutableArray.Empty; - if (operationContext.Operation is IObjectCreationOperation objectCreationOperation && - objectCreationOperation.Type is INamedTypeSymbol objectType && objectType.IsGenericType) { - typeParams = objectType.TypeParameters; - typeArgs = objectType.TypeArguments; - } else if (operationContext.Operation is IInvocationOperation invocationOperation && - invocationOperation.TargetMethod is IMethodSymbol targetMethod && targetMethod.IsGenericMethod) { - typeParams = targetMethod.TypeParameters; - typeArgs = targetMethod.TypeArguments; + switch (model.GetSymbolInfo (genericNameSyntaxNode).Symbol) { + case INamedTypeSymbol typeSymbol: + typeParams = typeSymbol.TypeParameters; + typeArgs = typeSymbol.TypeArguments; + break; + + case IMethodSymbol methodSymbol: + typeParams = methodSymbol.TypeParameters; + typeArgs = methodSymbol.TypeArguments; + break; + + default: + return; } for (int i = 0; i < typeParams.Length; i++) { - var typeParameter = typeParams[i]; - var typeArgument = typeArgs[i]; - if (!typeParameter.HasConstructorConstraint) + var typeParam = typeParams [i]; + var typeArg = typeArgs [i]; + if (!typeParam.HasConstructorConstraint) continue; - var typeArgCtors = ((INamedTypeSymbol) typeArgument).InstanceConstructors; + var typeArgCtors = ((INamedTypeSymbol) typeArg).InstanceConstructors; foreach (var instanceCtor in typeArgCtors) { if (instanceCtor.Arity > 0) continue; if (instanceCtor.TryGetAttribute (RequiresUnreferencedCodeAttribute, out var requiresUnreferencedCodeAttribute)) { - operationContext.ReportDiagnostic (Diagnostic.Create (s_requiresUnreferencedCodeRule, - operationContext.Operation.Syntax.GetLocation (), + syntaxNodeAnalysisContext.ReportDiagnostic (Diagnostic.Create (s_requiresUnreferencedCodeRule, + syntaxNodeAnalysisContext.Node.GetLocation (), containingSymbol.GetDisplayName (), (string) requiresUnreferencedCodeAttribute.ConstructorArguments[0].Value!, GetUrlFromAttribute (requiresUnreferencedCodeAttribute))); @@ -92,15 +99,11 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation compilation) => options.IsMSBuildPropertyValueTrue (MSBuildPropertyOptionNames.EnableTrimAnalyzer, compilation); - private protected override ImmutableArray<(Action Action, OperationKind[] OperationKind)> ExtraOperationActions { - get { - var diagsBuilder = ImmutableArray.CreateBuilder<(Action, OperationKind[])> (); - diagsBuilder.Add ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation })); - diagsBuilder.Add ((s_constructorConstraint, new OperationKind[] { OperationKind.Invocation, OperationKind.ObjectCreation })); + private protected override ImmutableArray<(Action Action, OperationKind[] OperationKind)> ExtraOperationActions => + ImmutableArray.Create ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation })); - return diagsBuilder.ToImmutable (); - } - } + private protected override ImmutableArray<(Action Action, SyntaxKind[] SyntaxKind)> ExtraSyntaxNodeActions => + ImmutableArray.Create ((s_constructorConstraint, new SyntaxKind[] { SyntaxKind.GenericName })); protected override bool VerifyAttributeArguments (AttributeData attribute) => attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg; diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs index 7442a368fd7a..d0fdf744fe44 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresUnreferencedCodeCapability.cs @@ -81,6 +81,7 @@ public static void Main () OnEventMethod.Test (); AccessThroughNewConstraint.Test (); AccessThroughNewConstraint.TestNewConstraintOnTypeParameter (); + AccessThroughNewConstraint.TestNewConstraintOnTypeParameterOfStaticType (); AccessThroughLdToken.Test (); RequiresOnClass.Test (); } @@ -785,6 +786,11 @@ public static void Test () GenericMethod (); } + static class NewConstraintOnTypeParameterOfStaticType where T : new() + { + public static void DoNothing () { } + } + class NewConstaintOnTypeParameter where T : new() { } @@ -794,6 +800,12 @@ public static void TestNewConstraintOnTypeParameter () { _ = new NewConstaintOnTypeParameter (); } + + [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] + public static void TestNewConstraintOnTypeParameterOfStaticType () + { + NewConstraintOnTypeParameterOfStaticType.DoNothing (); + } } class AccessThroughLdToken From 90cf840d68ab0a8f9ee3e06153483c493c9df95f Mon Sep 17 00:00:00 2001 From: Mateo Torres Ruiz Date: Tue, 7 Sep 2021 19:15:57 -0700 Subject: [PATCH 4/5] Lint --- src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs index eb4acb90876d..e927f4cdd0ef 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs @@ -62,8 +62,8 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase } for (int i = 0; i < typeParams.Length; i++) { - var typeParam = typeParams [i]; - var typeArg = typeArgs [i]; + var typeParam = typeParams[i]; + var typeArg = typeArgs[i]; if (!typeParam.HasConstructorConstraint) continue; From 03dfeb08d627f0bdd06f68b1281dc8a8f9124571 Mon Sep 17 00:00:00 2001 From: Mateo Torres Ruiz Date: Tue, 7 Sep 2021 23:56:08 -0700 Subject: [PATCH 5/5] Update justification --- .../RequiresUnreferencedCodeAnalyzer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs index e927f4cdd0ef..052c560e05b8 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs @@ -35,9 +35,10 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase }; [SuppressMessage ("MicrosoftCodeAnalysisPerformance", "RS1008", - Justification = "This action is registered through a compilation start action, so that the instances which " + - "can register this operation action will not outlive a compilation's lifetime, avoiding the possibility of " + - "this data causing stale compilations to remain in memory.")] + Justification = "Storing per-compilation data inside a diagnostic analyzer might cause stale compilations to remain alive." + + "This action is registered through a compilation start action, so that instances that register this syntax" + + " node action will not outlive a compilation's lifetime, avoiding the possibility of the locals stored in" + + " this function to cause for any stale compilations to remain in memory.")] static readonly Action s_constructorConstraint = syntaxNodeAnalysisContext => { var model = syntaxNodeAnalysisContext.SemanticModel; if (syntaxNodeAnalysisContext.ContainingSymbol is not ISymbol containingSymbol || containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute))