Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsabel Serrato <56236284+iserrato@users.noreply.github.com>2022-08-18 20:21:57 +0300
committerGitHub <noreply@github.com>2022-08-18 20:21:57 +0300
commit696c2166078b1a70f12407840c3ab0f90d73211b (patch)
tree991f1db1b2b5473fad4d339e4d1e493bad9c79af
parentbc1f05f234bf70219687c255587e79439de9d6ee (diff)
CodeFix Support for Additional DAM IDs (#2939)
* Expand Code Fix support to 23 DynamicallyAccessedMembers trim warnings * Pass information about where and what attribute needs to be added from the analyzer to the diagnostic so the Code Fix can target a greater number of warnings * Include additional tests to ensure that Code Fix is provided as expected, and check edge cases * Multiple annotations and merging of existing annotations is unsupported
-rw-r--r--src/ILLink.CodeFix/DAMCodeFixProvider.cs132
-rw-r--r--src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs78
-rw-r--r--src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs13
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/DiagnosticContext.cs41
-rw-r--r--src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs24
-rw-r--r--src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs2
-rw-r--r--src/linker/Linker.Dataflow/DiagnosticContext.cs7
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs23
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersCodeFixTests.cs2755
9 files changed, 2711 insertions, 364 deletions
diff --git a/src/ILLink.CodeFix/DAMCodeFixProvider.cs b/src/ILLink.CodeFix/DAMCodeFixProvider.cs
index 5aac3eb0c..a8c13d89f 100644
--- a/src/ILLink.CodeFix/DAMCodeFixProvider.cs
+++ b/src/ILLink.CodeFix/DAMCodeFixProvider.cs
@@ -13,7 +13,6 @@ using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Simplification;
@@ -25,9 +24,39 @@ namespace ILLink.CodeFix
{
private static ImmutableArray<DiagnosticDescriptor> GetSupportedDiagnostics ()
{
- return ImmutableArray.Create (
- DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter),
- DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter));
+ // Commented-out are currently unsupported Generic Parameter DiagnosticIDs
+ var diagDescriptorsArrayBuilder = ImmutableArray.CreateBuilder<DiagnosticDescriptor> ();
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsGenericParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsGenericParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsMethodReturnType));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsField));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsGenericParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsField));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsThisParameter));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsGenericParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnImplicitThisBetweenOverrides));
+ // diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides));
+
+ return diagDescriptorsArrayBuilder.ToImmutable ();
}
public static ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => GetSupportedDiagnostics ();
@@ -38,18 +67,22 @@ namespace ILLink.CodeFix
private static string FullyQualifiedAttributeName => DynamicallyAccessedMembersAnalyzer.FullyQualifiedDynamicallyAccessedMembersAttribute;
- private static SyntaxNode[] GetAttributeArguments (ISymbol targetSymbol, SyntaxGenerator syntaxGenerator, Diagnostic diagnostic)
- {
- object id = Enum.Parse (typeof (DiagnosticId), diagnostic.Id.Substring (2));
- switch (id) {
- case DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter:
- return new[] { syntaxGenerator.AttributeArgument (syntaxGenerator.TypedConstantExpression (targetSymbol.GetAttributes ().First (attr => attr.AttributeClass?.ToDisplayString () == DynamicallyAccessedMembersAnalyzer.FullyQualifiedDynamicallyAccessedMembersAttribute).ConstructorArguments[0])) };
- case DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter:
- return new[] { syntaxGenerator.AttributeArgument (syntaxGenerator.TypedConstantExpression (targetSymbol.GetAttributes ().First (attr => attr.AttributeClass?.ToDisplayString () == DynamicallyAccessedMembersAnalyzer.FullyQualifiedDynamicallyAccessedMembersAttribute).ConstructorArguments[0])) };
- default:
- return Array.Empty<SyntaxNode> ();
- }
- }
+ private static readonly string[] AttributeOnReturn = {
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter.AsString (),
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType.AsString() ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField.AsString (),
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter.AsString () ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides.AsString ()
+ };
+
+ private static readonly string[] AttributeOnGeneric = {
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter.AsString(),
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType.AsString () ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField.AsString(),
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter.AsString(),
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter.AsString(),
+ DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides.AsString()
+ };
public sealed override FixAllProvider GetFixAllProvider ()
{
@@ -63,55 +96,32 @@ namespace ILLink.CodeFix
if (await document.GetSyntaxRootAsync (context.CancellationToken).ConfigureAwait (false) is not { } root)
return;
var diagnostic = context.Diagnostics[0];
- SyntaxNode diagnosticNode = root.FindNode (diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
- if (await document.GetSemanticModelAsync (context.CancellationToken).ConfigureAwait (false) is not { } model)
+ if (diagnostic.AdditionalLocations.Count == 0)
return;
- // Note: We get the target symbol from the diagnostic location.
- // This works when the diagnostic location is a method call, because the target symbol will be the called method with annotations, but won't work in general for other kinds of diagnostics.
- if (model.GetSymbolInfo (diagnosticNode).Symbol is not { } targetSymbol)
+ if (root.FindNode (diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true) is not SyntaxNode attributableNode)
return;
- if (model.Compilation.GetTypeByMetadataName (FullyQualifiedAttributeName) is not { } attributeSymbol)
+ // currently not supporting multiple DAM argument, hence the check for commas in the string arguments
+ if (diagnostic.Properties[DynamicallyAccessedMembersAnalyzer.attributeArgument] is not string stringArgs || stringArgs.Contains (","))
return;
- if (diagnosticNode is not InvocationExpressionSyntax invocationExpression)
- return;
-
- var arguments = invocationExpression.ArgumentList.Arguments;
-
- if (arguments.Count > 1)
- return;
-
- if (arguments.Count == 1) {
- if (arguments[0].Expression is not LiteralExpressionSyntax literalSyntax
- || literalSyntax.Kind () is not SyntaxKind.StringLiteralExpression) {
- return;
- }
- }
-
- // N.B. May be null for FieldDeclaration, since field declarations can declare multiple variables
- var attributableSymbol = (invocationExpression.Expression is MemberAccessExpressionSyntax simpleMember
- && simpleMember.Expression is IdentifierNameSyntax name) ? model.GetSymbolInfo (name).Symbol : null;
-
-
- if (attributableSymbol is null)
+ var syntaxGenerator = SyntaxGenerator.GetGenerator (document);
+ var attributeArguments = new[] { syntaxGenerator.AttributeArgument (syntaxGenerator.MemberAccessExpression (syntaxGenerator.DottedName ("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes"), stringArgs)) };
+ if (await document.GetSemanticModelAsync (context.CancellationToken).ConfigureAwait (false) is not { } model)
return;
-
- var attributableNodeList = attributableSymbol.DeclaringSyntaxReferences;
-
- if (attributableNodeList.Length != 1)
+ if (model.Compilation.GetTypeByMetadataName (FullyQualifiedAttributeName) is not { } attributeSymbol)
return;
-
- var attributableNode = attributableNodeList[0].GetSyntax ();
-
- if (attributableNode is null) return;
-
- var attributeArguments = GetAttributeArguments (targetSymbol, SyntaxGenerator.GetGenerator (document), diagnostic);
var codeFixTitle = CodeFixTitle.ToString ();
context.RegisterCodeFix (CodeAction.Create (
title: codeFixTitle,
createChangedDocument: ct => AddAttributeAsync (
- document, attributableNode, attributeArguments, attributeSymbol, ct),
+ document,
+ attributableNode,
+ attributeArguments,
+ attributeSymbol,
+ addAsReturnAttribute: AttributeOnReturn.Contains (diagnostic.Id),
+ addGenericParameterAttribute: AttributeOnGeneric.Contains (diagnostic.Id),
+ ct),
equivalenceKey: codeFixTitle), diagnostic);
}
@@ -120,6 +130,8 @@ namespace ILLink.CodeFix
SyntaxNode targetNode,
SyntaxNode[] attributeArguments,
ITypeSymbol attributeSymbol,
+ bool addAsReturnAttribute,
+ bool addGenericParameterAttribute,
CancellationToken cancellationToken)
{
var editor = await DocumentEditor.CreateAsync (document, cancellationToken).ConfigureAwait (false);
@@ -128,7 +140,17 @@ namespace ILLink.CodeFix
generator.TypeExpression (attributeSymbol), attributeArguments)
.WithAdditionalAnnotations (Simplifier.Annotation, Simplifier.AddImportsAnnotation);
- editor.AddAttribute (targetNode, attribute);
+ if (addAsReturnAttribute) {
+ // don't use AddReturnAttribute because it's the same as AddAttribute https://github.com/dotnet/roslyn/pull/63084
+ editor.ReplaceNode (targetNode, (d, g) => g.AddReturnAttributes (d, new[] { attribute }));
+ } else if (addGenericParameterAttribute) {
+ // AddReturnAttributes currently doesn't support adding attributes to type arguments https://github.com/dotnet/roslyn/pull/63292
+ var newNode = (TypeParameterSyntax) targetNode;
+ var nodeWithAttribute = newNode.AddAttributeLists ((AttributeListSyntax) attribute);
+ editor.ReplaceNode (targetNode, nodeWithAttribute);
+ } else {
+ editor.AddAttribute (targetNode, attribute);
+ }
return editor.GetChangedDocument ();
}
}
diff --git a/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs b/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
index 0e095dbc5..e847010a0 100644
--- a/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
@@ -22,6 +22,7 @@ namespace ILLink.RoslynAnalyzer
{
internal const string DynamicallyAccessedMembers = nameof (DynamicallyAccessedMembers);
internal const string DynamicallyAccessedMembersAttribute = nameof (DynamicallyAccessedMembersAttribute);
+ public const string attributeArgument = "attributeArgument";
public const string FullyQualifiedDynamicallyAccessedMembersAttribute = "System.Diagnostics.CodeAnalysis." + DynamicallyAccessedMembersAttribute;
public static ImmutableArray<DiagnosticDescriptor> GetSupportedDiagnostics ()
@@ -205,27 +206,70 @@ namespace ILLink.RoslynAnalyzer
static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbol method, IMethodSymbol overriddenMethod)
{
- if (FlowAnnotations.GetMethodReturnValueAnnotation (method) != FlowAnnotations.GetMethodReturnValueAnnotation (overriddenMethod))
+ var methodReturnAnnotations = FlowAnnotations.GetMethodReturnValueAnnotation (method);
+ var overriddenMethodReturnAnnotations = FlowAnnotations.GetMethodReturnValueAnnotation (overriddenMethod);
+ if (methodReturnAnnotations != overriddenMethodReturnAnnotations) {
+
+ (IMethodSymbol attributableMethod, DynamicallyAccessedMemberTypes missingAttribute) = GetTargetAndRequirements (method,
+ overriddenMethod, methodReturnAnnotations, overriddenMethodReturnAnnotations);
+
+ Location attributableSymbolLocation = attributableMethod.Locations[0];
+
+ // code fix does not support merging multiple attributes. If an attribute is present or the method is not in source, do not provide args for code fix.
+ (Location[]? sourceLocation, Dictionary<string, string?>? DAMArgs) = (!attributableSymbolLocation.IsInSource
+ || (method.TryGetReturnAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _)
+ && overriddenMethod.TryGetReturnAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _))
+ ) ? (null, null) : CreateArguments (attributableSymbolLocation, missingAttribute);
+
context.ReportDiagnostic (Diagnostic.Create (
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides),
- method.Locations[0], method.GetDisplayName (), overriddenMethod.GetDisplayName ()));
+ method.Locations[0], sourceLocation, DAMArgs?.ToImmutableDictionary (), method.GetDisplayName (), overriddenMethod.GetDisplayName ()));
+ }
for (int i = 0; i < method.Parameters.Length; i++) {
- if (FlowAnnotations.GetMethodParameterAnnotation (method.Parameters[i]) != FlowAnnotations.GetMethodParameterAnnotation (overriddenMethod.Parameters[i])) {
+ var methodParameterAnnotation = FlowAnnotations.GetMethodParameterAnnotation (method.Parameters[i]);
+ var overriddenParameterAnnotation = FlowAnnotations.GetMethodParameterAnnotation (overriddenMethod.Parameters[i]);
+ if (methodParameterAnnotation != overriddenParameterAnnotation) {
+
+ (IMethodSymbol attributableMethod, DynamicallyAccessedMemberTypes missingAttribute) = GetTargetAndRequirements (method,
+ overriddenMethod, methodParameterAnnotation, overriddenParameterAnnotation);
+
+ Location attributableSymbolLocation = attributableMethod.Parameters[i].Locations[0];
+
+ // code fix does not support merging multiple attributes. If an attribute is present or the method is not in source, do not provide args for code fix.
+ (Location[]? sourceLocation, Dictionary<string, string?>? DAMArgs) = (!attributableSymbolLocation.IsInSource
+ || (method.Parameters[i].TryGetAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _)
+ && overriddenMethod.Parameters[i].TryGetAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _))
+ ) ? (null, null) : CreateArguments (attributableSymbolLocation, missingAttribute);
+
context.ReportDiagnostic (Diagnostic.Create (
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides),
- method.Parameters[i].Locations[0],
+ method.Parameters[i].Locations[0], sourceLocation, DAMArgs?.ToImmutableDictionary (),
method.Parameters[i].GetDisplayName (), method.GetDisplayName (), overriddenMethod.Parameters[i].GetDisplayName (), overriddenMethod.GetDisplayName ()));
}
}
for (int i = 0; i < method.TypeParameters.Length; i++) {
- if (method.TypeParameters[i].GetDynamicallyAccessedMemberTypes () != overriddenMethod.TypeParameters[i].GetDynamicallyAccessedMemberTypes ())
+ var methodTypeParameterAnnotation = method.TypeParameters[i].GetDynamicallyAccessedMemberTypes ();
+ var overriddenMethodTypeParameterAnnotation = overriddenMethod.TypeParameters[i].GetDynamicallyAccessedMemberTypes ();
+ if (methodTypeParameterAnnotation != overriddenMethodTypeParameterAnnotation) {
+
+ (IMethodSymbol attributableMethod, DynamicallyAccessedMemberTypes missingAttribute) = GetTargetAndRequirements (method, overriddenMethod, methodTypeParameterAnnotation, overriddenMethodTypeParameterAnnotation);
+
+ Location attributableSymbolLocation = attributableMethod.TypeParameters[i].Locations[0];
+
+ // code fix does not support merging multiple attributes. If an attribute is present or the method is not in source, do not provide args for code fix.
+ (Location[]? sourceLocation, Dictionary<string, string?>? DAMArgs) = (!attributableSymbolLocation.IsInSource
+ || (method.TypeParameters[i].TryGetAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _)
+ && overriddenMethod.TypeParameters[i].TryGetAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _))
+ ) ? (null, null) : CreateArguments (attributableSymbolLocation, missingAttribute);
+
context.ReportDiagnostic (Diagnostic.Create (
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides),
- method.TypeParameters[i].Locations[0],
+ method.TypeParameters[i].Locations[0], sourceLocation, DAMArgs?.ToImmutableDictionary (),
method.TypeParameters[i].GetDisplayName (), method.GetDisplayName (),
overriddenMethod.TypeParameters[i].GetDisplayName (), overriddenMethod.GetDisplayName ()));
+ }
}
if (!method.IsStatic && method.GetDynamicallyAccessedMemberTypes () != overriddenMethod.GetDynamicallyAccessedMemberTypes ())
@@ -265,5 +309,27 @@ namespace ILLink.RoslynAnalyzer
return;
}
}
+
+ private static (IMethodSymbol Method, DynamicallyAccessedMemberTypes Requirements) GetTargetAndRequirements (IMethodSymbol method, IMethodSymbol overriddenMethod, DynamicallyAccessedMemberTypes methodAnnotation, DynamicallyAccessedMemberTypes overriddenMethodAnnotation)
+ {
+ DynamicallyAccessedMemberTypes mismatchedArgument;
+ IMethodSymbol paramNeedsAttributes;
+ if (methodAnnotation == DynamicallyAccessedMemberTypes.None) {
+ mismatchedArgument = overriddenMethodAnnotation;
+ paramNeedsAttributes = method;
+ } else {
+ mismatchedArgument = methodAnnotation;
+ paramNeedsAttributes = overriddenMethod;
+ }
+ return (paramNeedsAttributes, mismatchedArgument);
+ }
+
+ private static (Location[]?, Dictionary<string, string?>?) CreateArguments (Location attributableSymbolLocation, DynamicallyAccessedMemberTypes mismatchedArgument)
+ {
+ Dictionary<string, string?>? DAMArgument = new ();
+ Location[]? sourceLocation = new Location[] { attributableSymbolLocation };
+ DAMArgument.Add (DynamicallyAccessedMembersAnalyzer.attributeArgument, mismatchedArgument.ToString ());
+ return (sourceLocation, DAMArgument);
+ }
}
}
diff --git a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
index fa262c760..0d39282d3 100644
--- a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
+++ b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
@@ -58,6 +58,19 @@ namespace ILLink.RoslynAnalyzer
return (DynamicallyAccessedMemberTypes) dynamicallyAccessedMembers.ConstructorArguments[0].Value!;
}
+ internal static bool TryGetReturnAttribute (this IMethodSymbol member, string attributeName, [NotNullWhen (returnValue: true)] out AttributeData? attribute)
+ {
+ attribute = null;
+ foreach (var attr in member.GetReturnTypeAttributes ()) {
+ if (attr.AttributeClass is { } attrClass && attrClass.HasName (attributeName)) {
+ attribute = attr;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
internal static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesOnAssociatedSymbol (this IMethodSymbol methodSymbol) =>
methodSymbol.AssociatedSymbol is ISymbol associatedSymbol ? GetDynamicallyAccessedMemberTypes (associatedSymbol) : DynamicallyAccessedMemberTypes.None;
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/DiagnosticContext.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/DiagnosticContext.cs
index a47704f77..a59bd1cc0 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/DiagnosticContext.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/DiagnosticContext.cs
@@ -1,7 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using ILLink.RoslynAnalyzer;
using Microsoft.CodeAnalysis;
@@ -27,5 +29,44 @@ namespace ILLink.Shared.TrimAnalysis
Diagnostics.Add (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (id), Location, args));
}
+
+ public partial void AddDiagnostic (DiagnosticId id, ValueWithDynamicallyAccessedMembers actualValue, ValueWithDynamicallyAccessedMembers expectedAnnotationsValue, params string[] args)
+ {
+ if (Location == null)
+ return;
+
+ if (actualValue is NullableValueWithDynamicallyAccessedMembers nv)
+ actualValue = nv.UnderlyingTypeValue;
+
+ ISymbol symbol = actualValue switch {
+ FieldValue field => field.FieldSymbol,
+ MethodParameterValue mpv => mpv.ParameterSymbol,
+ MethodReturnValue mrv => mrv.MethodSymbol,
+ MethodThisParameterValue mtpv => mtpv.MethodSymbol,
+ GenericParameterValue gpv => gpv.GenericParameter.TypeParameterSymbol,
+ _ => throw new InvalidOperationException ()
+ };
+
+ Location[]? sourceLocation;
+ Dictionary<string, string?>? DAMArgument = new Dictionary<string, string?> ();
+
+ // not supporting merging differing attributes, check to make sure symbol has no other attributes
+ if (symbol.DeclaringSyntaxReferences.Length == 0
+ || (actualValue is not MethodReturnValue
+ && symbol.TryGetAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _))
+ || (actualValue is MethodReturnValue
+ && symbol is IMethodSymbol method
+ && method.TryGetReturnAttribute (DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute, out var _))) {
+ sourceLocation = null;
+ DAMArgument = null;
+ } else {
+ Location symbolLocation;
+ symbolLocation = symbol.DeclaringSyntaxReferences[0].GetSyntax ().GetLocation ();
+ DAMArgument.Add ("attributeArgument", expectedAnnotationsValue.DynamicallyAccessedMemberTypes.ToString ());
+ sourceLocation = new Location[] { symbolLocation };
+ }
+
+ Diagnostics.Add (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (id), Location, sourceLocation, DAMArgument?.ToImmutableDictionary (), args));
+ }
}
}
diff --git a/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs b/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
index 95c984d7f..ad380383c 100644
--- a/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
+++ b/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
@@ -6,19 +6,25 @@
namespace ILLink.Shared.TrimAnalysis
{
+ /// <summary>
+ /// The diagnostic context may be entirely disabled or some kinds of warnings may be suppressed.
+ /// The suppressions are determined based on the <paramref name="id"/>.
+ /// Typically the suppressions will be based on diagnostic category <see cref="DiagnosticCategory"/>:
+ /// - Trimmer warnings (suppressed by RequiresUnreferencedCodeAttribute)
+ /// - AOT warnings (suppressed by RequiresDynamicCodeAttribute)
+ /// - Single-file warnings (suppressed by RequiresAssemblyFilesAttribute)
+ /// Note that not all categories are used/supported by all tools, for example the ILLink only handles trimmer warnings and ignores the rest.
+ /// </summary>
readonly partial struct DiagnosticContext
{
- /// <summary>
- /// The diagnostic context may be entirely disabled or some kinds of warnings may be suppressed.
- /// The suppressions are determined based on the <paramref name="id"/>.
- /// Typically the suppressions will be based on diagnostic category <see cref="DiagnosticCategory"/>:
- /// - Trimmer warnings (suppressed by RequiresUnreferencedCodeAttribute)
- /// - AOT warnings (suppressed by RequiresDynamicCodeAttribute)
- /// - Single-file warnings (suppressed by RequiresAssemblyFilesAttribute)
- /// Note that not all categories are used/supported by all tools, for example the ILLink only handles trimmer warnings and ignores the rest.
- /// </summary>
/// <param name="id">The diagnostic ID, this will be used to determine the category of diagnostic (trimmer, AOT, single-file)</param>
/// <param name="args">The arguments for diagnostic message.</param>
public partial void AddDiagnostic (DiagnosticId id, params string[] args);
+
+ /// <param name="id">The diagnostic ID, this will be used to determine the category of diagnostic (trimmer, AOT, single-file)</param>
+ /// <param name="actualValue">The value for the source of the diagnostic</param>
+ /// <param name="expectedAnnotationsValue">The value for the symbol causing the diagnostic</param>
+ /// <param name="args">The arguments for diagnostic message.</param>
+ public partial void AddDiagnostic (DiagnosticId id, ValueWithDynamicallyAccessedMembers actualValue, ValueWithDynamicallyAccessedMembers expectedAnnotationsValue, params string[] args);
}
}
diff --git a/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs b/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs
index 9eb5db788..389116f97 100644
--- a/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs
+++ b/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs
@@ -35,7 +35,7 @@ namespace ILLink.Shared.TrimAnalysis
var availableMemberTypes = valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes;
if (!Annotations.SourceHasRequiredAnnotations (availableMemberTypes, targetValue.DynamicallyAccessedMemberTypes, out var missingMemberTypes)) {
(var diagnosticId, var diagnosticArguments) = Annotations.GetDiagnosticForAnnotationMismatch (valueWithDynamicallyAccessedMembers, targetValue, missingMemberTypes);
- _diagnosticContext.AddDiagnostic (diagnosticId, diagnosticArguments);
+ _diagnosticContext.AddDiagnostic (diagnosticId, valueWithDynamicallyAccessedMembers, targetValue, diagnosticArguments);
}
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
MarkTypeForDynamicallyAccessedMembers (systemTypeValue.RepresentedType, targetValue.DynamicallyAccessedMemberTypes);
diff --git a/src/linker/Linker.Dataflow/DiagnosticContext.cs b/src/linker/Linker.Dataflow/DiagnosticContext.cs
index 67fb9ec08..5e0f18a45 100644
--- a/src/linker/Linker.Dataflow/DiagnosticContext.cs
+++ b/src/linker/Linker.Dataflow/DiagnosticContext.cs
@@ -19,5 +19,12 @@ namespace ILLink.Shared.TrimAnalysis
if (DiagnosticsEnabled)
_context.LogWarning (Origin, id, args);
}
+
+#pragma warning disable IDE0060, CA1822
+ public partial void AddDiagnostic (DiagnosticId id, ValueWithDynamicallyAccessedMembers actualValue, ValueWithDynamicallyAccessedMembers expectedAnnotationsValue, params string[] args)
+ {
+ AddDiagnostic (id, args);
+ }
+#pragma warning restore IDE0060, CA1822
}
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs
index 90a7de166..ff70b7f58 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs
@@ -87,6 +87,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
.WithSpan (21, 3, 21, 38)
+ .WithSpan (19, 24, 19, 33)
.WithArguments ("parameter",
"C.NeedsPublicMethodsOnParameter(Type)",
"type",
@@ -126,6 +127,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType)
.WithSpan (18, 10, 18, 14)
+ .WithSpan (16, 24, 16, 33)
.WithArguments ("C.M(Type)",
"type",
"C.M(Type)",
@@ -166,6 +168,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField)
.WithSpan (17, 3, 17, 11)
+ .WithSpan (15, 24, 15, 33)
.WithArguments ("C.f",
"type",
"C.M(Type)",
@@ -203,6 +206,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter)
.WithSpan (16, 3, 16, 24)
+ .WithSpan (14, 24, 14, 33)
.WithArguments ("System.Type.GetMethod(String)",
"type",
"C.M(Type)",
@@ -247,6 +251,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
.WithSpan (12, 3, 12, 40)
+ .WithSpan (20, 2, 23, 3)
.WithArguments ("type", "C.NeedsPublicMethodsOnParameter(Type)", "C.GetT()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -287,6 +292,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType)
.WithSpan (18, 10, 18, 18)
+ .WithSpan (21, 2, 24, 3)
.WithArguments ("C.M()", "C.GetFoo()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -324,6 +330,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField)
.WithSpan (12, 3, 12, 10)
+ .WithSpan (15, 2, 18, 3)
.WithArguments ("C.f",
"C.M()",
"'DynamicallyAccessedMemberTypes.PublicMethods'"));
@@ -361,6 +368,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
.WithSpan (11, 3, 11, 28)
+ .WithSpan (15, 2, 18, 3)
.WithArguments ("System.Type.GetMethod(String)", "C.GetFoo()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
#endregion
@@ -399,6 +407,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsParameter)
.WithSpan (14, 3, 14, 24)
+ .WithSpan (10, 22, 10, 37)
.WithArguments ("type",
"C.NeedsPublicMethods(Type)",
"C.f",
@@ -439,6 +448,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsMethodReturnType)
.WithSpan (20, 10, 20, 11)
+ .WithSpan (10, 22, 10, 37)
.WithArguments ("C.M()", "C.f",
"'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -473,6 +483,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsField)
.WithSpan (17, 3, 17, 10)
+ .WithSpan (10, 22, 10, 38)
.WithArguments ("C.f2",
"C.f1",
"'DynamicallyAccessedMemberTypes.PublicMethods'"));
@@ -506,6 +517,7 @@ namespace ILLink.RoslynAnalyzer.Tests
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter)
.WithSpan (13, 3, 13, 21)
+ .WithSpan (9, 22, 9, 37)
.WithArguments ("System.Type.GetMethod(String)",
"C.f",
"'DynamicallyAccessedMemberTypes.PublicMethods'"));
@@ -514,7 +526,7 @@ namespace ILLink.RoslynAnalyzer.Tests
#region SourceMethod
- static string GetSystemTypeBase ()
+ public static string GetSystemTypeBase ()
{
return $$"""
// Licensed to the .NET Foundation under one or more agreements.
@@ -740,6 +752,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetParameterWithAnnotations),
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter)
.WithSpan (198, 4, 198, 12)
+ .WithSpan (196, 3, 199, 4)
.WithArguments ("type", "System.C.M2(Type)", "System.C.M1()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -779,6 +792,7 @@ namespace System
// (203,4): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'. The return value of method 'System.ConvertsToType.implicit operator Type(ConvertsToType)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
.WithSpan (203, 4, 203, 28)
+ .WithSpan (191, 3, 191, 89)
.WithArguments ("type", "System.C.M2(Type)", "System.ConvertsToType.implicit operator Type(ConvertsToType)", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -891,6 +905,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodReturnTypeWithAnnotations),
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType)
.WithSpan (200, 11, 200, 15)
+ .WithSpan (196, 3, 201, 4)
.WithArguments ("System.C.M()", "System.C.M()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -925,6 +940,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetFieldWithAnnotations),
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsField)
.WithSpan (198, 4, 198, 12)
+ .WithSpan (196, 3, 199, 4)
.WithArguments ("System.C.f",
"System.C.M()",
"'DynamicallyAccessedMemberTypes.PublicMethods'"));
@@ -957,6 +973,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodWithAnnotations),
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsThisParameter)
.WithSpan (198, 4, 198, 21)
+ .WithSpan (196, 3, 199, 4)
.WithArguments ("System.Type.GetMethods()", "System.C.M()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
#endregion
@@ -993,6 +1010,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter)
.WithSpan (18, 3, 18, 16)
+ .WithSpan (16, 25, 16, 26)
.WithArguments ("type", "C.M1(Type)", "T", "C.M2<T>()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
@@ -1024,6 +1042,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType)
.WithSpan (14, 10, 14, 19)
+ .WithSpan (12, 24, 12, 25)
.WithArguments ("C.M<T>()", "T", "C.M<T>()", "'DynamicallyAccessedMemberTypes.PublicConstructors'"));
}
@@ -1057,6 +1076,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField)
.WithSpan (16, 3, 16, 16)
+ .WithSpan (14, 24, 14, 25)
.WithArguments ("C.f",
"T",
"C.M<T>()",
@@ -1093,6 +1113,7 @@ namespace System
return VerifyDynamicallyAccessedMembersAnalyzer (TargetGenericParameterWithAnnotations,
VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter)
.WithSpan (16, 3, 16, 8)
+ .WithSpan (14, 25, 14, 26)
.WithArguments ("T", "C.M1<T>()", "S", "C.M2<S>()", "'DynamicallyAccessedMemberTypes.PublicMethods'"));
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersCodeFixTests.cs b/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersCodeFixTests.cs
index 4bda78a88..4eed3b026 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersCodeFixTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersCodeFixTests.cs
@@ -40,6 +40,289 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
return test.RunAsync ();
}
+ [Fact]
+ public async Task CodeFix_IL2067_MismatchParamTargetsParam ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ static void M(Type t) {
+ M2(t);
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) {}
+ }
+ """;
+
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) {
+ M2(t);
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) {}
+ }
+ """;
+
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(7,3): warning IL2067: 't' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'C.M2(Type)'.
+ // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
+ .WithSpan(7, 3, 7, 8)
+ .WithSpan(6, 16, 6, 22)
+ .WithArguments("t",
+ "C.M2(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.All'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2067_MismatchParamTargetsParam_WithReturn ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ static string M(Type t) {
+ M2(t);
+ return "Foo";
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {}
+ }
+ """;
+
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ static string M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ M2(t);
+ return "Foo";
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {}
+ }
+ """;
+
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(7,3): warning IL2067: 't' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'C.M2(Type)'.
+ // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
+ .WithSpan(8, 3, 8, 8)
+ .WithSpan(7, 18, 7, 24)
+ .WithArguments("t",
+ "C.M2(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2067_TwoAttributesTurnsOffDiagnostic ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ static void M(Type t) {
+ M2(t);
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicFields)] Type t) {}
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(7,3): warning IL2067: 't' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'C.M2(Type)'.
+ // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
+ .WithSpan(7, 3, 7, 8)
+ .WithSpan(6, 16, 6, 22)
+ .WithArguments("t",
+ "C.M2(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicFields'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2067_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ static string M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ M2(t);
+ return "Foo";
+ }
+
+ static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {}
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(7,3): warning IL2067: 't' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'C.M2(Type)'.
+ // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
+ .WithSpan(8, 3, 8, 8)
+ .WithArguments("t",
+ "C.M2(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2068_MismatchParamTargetsMethodReturn ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
+ Type M(Type t) {
+ return t;
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
+ Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) {
+ return t;
+ }
+ }
+ """;
+
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,10): warning IL2068: 'C.M(Type)' method return value does not satisfy 'DynamicallyAccessedMemberTypes.All' requirements. The parameter 't' of method 'C.M(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType)
+ .WithSpan (8, 10, 8, 11)
+ .WithSpan (7, 9, 7, 15)
+ .WithArguments ("C.M(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.All'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2068_ArgumentTurnsOffCodeFix_None ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
+ Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)] Type t) {
+ return t;
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(8,10): warning IL2068: 'C.M(Type)' method return value does not satisfy 'DynamicallyAccessedMemberTypes.All' requirements. The parameter 't' of method 'C.M(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType)
+ .WithSpan (8, 10, 8, 11)
+ .WithArguments ("C.M(Type)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.All'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2069_MismatchParamTargetsField_PublicMethods ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M(typeof(C));
+ }
+
+ private static void M(Type type)
+ {
+ f = type;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f = typeof(C);
+ }
+ """;
+
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M(typeof(C));
+ }
+
+ private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ f = type;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f = typeof(C);
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(13,3): warning IL2069: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ //The parameter 'type' of method 'C.M(Type)' does not have matching annotations.
+ //The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField)
+ .WithSpan(13, 3, 13, 11)
+ .WithSpan(11, 24, 11, 33)
+ .WithArguments ("C.f",
+ "type",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
[Fact]
public async Task CodeFix_IL2070_MismatchParamTargetsThisParam_PublicMethods ()
@@ -77,25 +360,25 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
}
""";
await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(12,3): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'.
- // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
- // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ // /0/Test0.cs(12,3): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'. The parameter 't' of method 'C.M(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter)
.WithSpan(12, 3, 12, 17)
+ .WithSpan(10, 16, 10, 22)
.WithArguments("System.Type.GetMethods()",
"t",
"C.M(Type)",
- "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
fixedExpected: Array.Empty<DiagnosticResult> ());
}
[Fact]
- public async Task CodeFix_IL2070_ArgsTurnOffCodeFix ()
+ public async Task CodeFix_IL2070_NonPublicMethods ()
{
var test = $$"""
using System;
using System.Reflection;
-
+ using System.Diagnostics.CodeAnalysis;
+
class C
{
public static void Main()
@@ -108,17 +391,40 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
}
}
""";
- var diag = new[] {
- // /0/Test0.cs(12,3): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.NonPublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'.
- // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
- // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter)
- .WithSpan (12, 3, 12, 39)
- .WithArguments ("System.Type.GetMethods(BindingFlags)",
- "t",
- "C.M(Type)",
- "'DynamicallyAccessedMemberTypes.NonPublicMethods'") };
- await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+
+ var fixtest = $$"""
+ using System;
+ using System.Reflection;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M(typeof(C));
+ }
+ static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t)
+ {
+ t.GetMethods(BindingFlags.NonPublic);
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(13,3): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.NonPublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'.
+ // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter)
+ .WithSpan(13, 3, 13, 39)
+ .WithSpan(11, 16, 11, 22)
+ .WithArguments("System.Type.GetMethods(BindingFlags)",
+ "t",
+ "C.M(Type)",
+ "'DynamicallyAccessedMemberTypes.NonPublicMethods'")}, new[] {
+ // /0/Test0.cs(9,3): warning IL2111: Method 'C.M(Type)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection.
+ // Trimmer can't guarantee availability of the requirements of the method.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection)
+ .WithSpan (9, 3, 9, 15)
+ .WithArguments ("C.M(Type)") });
}
[Fact]
@@ -165,230 +471,1977 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
""";
await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(10,27): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'. The parameter 't' of method 'System.C.Main(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter).WithSpan(10, 27, 10, 41).WithArguments("System.Type.GetMethods()", "t", "System.C.Main(Type)", "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ // /0/Test0.cs(10,27): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'.
+ // The parameter 't' of method 'System.C.Main(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter)
+ .WithSpan(10, 27, 10, 41)
+ .WithSpan(8, 20, 8, 26)
+ .WithArguments("System.Type.GetMethods()",
+ "t",
+ "System.C.Main(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
fixedExpected: Array.Empty<DiagnosticResult> ());
}
[Fact]
- public async Task CodeFix_IL2080_MismatchFieldTargetsPrivateParam_PublicMethods ()
+ public async Task CodeFix_IL2072_MismatchMethodReturnTargetsParam ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+
+ class C
+ {
+ public static void Main()
+ {
+ NeedsPublicMethodsOnParameter(GetC());
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+
+ private static Type GetC()
+ {
+ return typeof(C);
+ }
+ }
+ """;
+
+ var fixtest = """
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ NeedsPublicMethodsOnParameter(GetC());
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC()
+ {
+ return typeof(C);
+ }
+ }
+ """;
+
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,3): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'.
+ // The return value of method 'C.GetT()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
+ .WithSpan(8, 3, 8, 40)
+ .WithSpan(16, 2, 19, 3)
+ .WithArguments("type",
+ "C.NeedsPublicMethodsOnParameter(Type)",
+ "C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2072_MismatchMethodReturnTargetsParam_WithAttributes ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ NeedsPublicMethodsOnParameter(GetC(typeof(C)));
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+
+ private static Type GetC([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ return t;
+ }
+ }
+ """;
+
+ var fixtest = """
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
{
+ public static void Main()
+ {
+ NeedsPublicMethodsOnParameter(GetC(typeof(C)));
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ return t;
+ }
}
+ """;
+
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,3): warning IL2072: 't' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'.
+ // The return value of method 'C.GetC(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
+ .WithSpan(8, 3, 8, 49)
+ .WithSpan(16, 2, 19, 3)
+ .WithArguments("t",
+ "C.NeedsPublicMethodsOnParameter(Type)",
+ "C.GetC(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2072_AttributeTurnsOffCodeFix_None ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
class C
{
- private static Type f = typeof(Foo);
+ public static void Main()
+ {
+ NeedsPublicMethodsOnParameter(GetC());
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)]
+ private static Type GetC()
+ {
+ return typeof(C);
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(8,3): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'.
+ // The return value of method 'C.GetT()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
+ .WithSpan(8, 3, 8, 40)
+ .WithArguments("type",
+ "C.NeedsPublicMethodsOnParameter(Type)",
+ "C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2072_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
public static void Main()
{
- f.GetMethod("Bar");
+ NeedsPublicMethodsOnParameter(GetT());
+ }
+
+ private static void NeedsPublicMethodsOnParameter(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ private static Type GetT()
+ {
+ return typeof(C);
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(8,3): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'.
+ // The return value of method 'C.GetT()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter)
+ .WithSpan(8, 3, 8, 40)
+ .WithArguments("type",
+ "C.NeedsPublicMethodsOnParameter(Type)",
+ "C.GetT()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2073_MismatchMethodReturnTargetsMethodReturn ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C {
+ Type Main(Type t) {
+ return t;
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type M() {
+ return Main(typeof(C));
}
}
""";
var fixtest = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+
+ class C {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type Main([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ return t;
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type M() {
+ return Main(typeof(C));
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(11,10): warning IL2073: 'C.M()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The return value of method 'C.Main(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType)
+ .WithSpan(11, 10, 11, 25)
+ .WithSpan(5, 2, 7, 3)
+ .WithArguments("C.M()",
+ "C.Main(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> (), 2);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2073_MismatchMethodReturnTargetsMethodReturn_WithAttribute ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C {
+ Type Main([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ return t;
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ return Main(t);
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type Main([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ return t;
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
+ return Main(t);
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(11,10): warning IL2073: 'C.M(Type)' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The return value of method 'C.Main(Type)' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType)
+ .WithSpan(11, 10, 11, 17)
+ .WithSpan(5, 2, 7, 3)
+ .WithArguments("C.M(Type)",
+ "C.Main(Type)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2074_MismatchMethodReturnTargetsField ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
{
+ public static void Main()
+ {
+ f = M();
+ }
+
+ private static Type M()
+ {
+ return typeof(C);
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
}
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ f = M();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type M()
+ {
+ return typeof(C);
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,3): warning IL2074: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The return value of method 'C.M()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField)
+ .WithSpan(8, 3, 8, 10)
+ .WithSpan(11, 2, 14, 3)
+ .WithArguments("C.f",
+ "C.M()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> (), 1);
+
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2075_MethodReturnTargetsParam_PublicMethods ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ private static Type GetC ()
+ {
+ return typeof (C);
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC ()
+ {
+ return typeof (C);
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ //The return value of method 'C.GetFoo()' does not have matching annotations.
+ //The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
+ .WithSpan(8, 3, 8, 26)
+ .WithSpan(11, 2, 14, 3)
+ .WithArguments ("System.Type.GetMethod(String)",
+ "C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2075_MethodAttributeLeavesOnCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest), new[] {
+ // /0/Test0.cs(8,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ //The return value of method 'C.GetFoo()' does not have matching annotations.
+ //The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
+ .WithSpan(194, 4, 194, 27)
+ .WithSpan(197, 3, 200, 4)
+ .WithArguments("System.Type.GetMethod(String)",
+ "System.C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2075_MethodAttributeLeavesOnCodeFix_Reverse ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ GetC().GetMethod("Foo");
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest), new[] {
+ // /0/Test0.cs(8,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ //The return value of method 'C.GetFoo()' does not have matching annotations.
+ //The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
+ .WithSpan(193, 4, 193, 27)
+ .WithSpan(196, 3, 200, 4)
+ .WithArguments("System.Type.GetMethod(String)",
+ "System.C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2075_ReutrnAttributeLeavesOnCodeFix ()
+ {
+ var test = $$$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public static string Main()
+ {
+ GetC().GetMethod("Foo");
+ return "Foo";
+ }
+
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public static string Main()
+ {
+ GetC().GetMethod("Foo");
+ return "Foo";
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type GetC ()
+ {
+ return typeof(int);
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest), new[] {
+ // /0/Test0.cs(8,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ //The return value of method 'C.GetFoo()' does not have matching annotations.
+ //The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
+ .WithSpan(194, 4, 194, 27)
+ .WithSpan(198, 3, 201, 4)
+ .WithArguments("System.Type.GetMethod(String)",
+ "System.C.GetC()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2077_MismatchFieldTargetsParam ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ private static Type f = typeof(C);
+
+ public static void Main()
+ {
+ NeedsPublicMethods(f);
+ }
+
+ private static void NeedsPublicMethods(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
class C
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- private static Type f = typeof(Foo);
+ private static Type f = typeof(C);
public static void Main()
{
- f.GetMethod("Bar");
+ NeedsPublicMethods(f);
+ }
+
+ private static void NeedsPublicMethods(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
}
}
""";
await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(13,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
- // The field 'C.f' does not have matching annotations.
- // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter)
- .WithSpan(13, 3, 13, 21)
- .WithArguments("System.Type.GetMethod(String)",
- "C.f",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ // /0/Test0.cs(10,3): warning IL2077: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethods(Type)'.
+ // The field 'C.f' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsParameter)
+ .WithSpan(10, 3, 10, 24)
+ .WithSpan(6, 22, 6, 35)
+ .WithArguments("type",
+ "C.NeedsPublicMethods(Type)",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
fixedExpected: Array.Empty<DiagnosticResult> ());
}
+
[Fact]
- public async Task CodeFix_IL2080_MismatchFieldTargetsPublicParam_PublicMethods ()
+ public async Task CodeFix_IL2077_AttributeTurnsOffCodeFix ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+
+ class C
{
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ private static Type f = typeof(C);
+
+ public static void Main()
+ {
+ NeedsPublicMethods(f);
+ }
+
+ private static void NeedsPublicMethods(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
}
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(11,3): warning IL2077: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethods(Type)'.
+ // The field 'C.f' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsParameter)
+ .WithSpan(11, 3, 11, 24)
+ .WithArguments("type",
+ "C.NeedsPublicMethods(Type)",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+ [Fact]
+ public async Task CodeFix_IL2078_MismatchFieldTargetsMethodReturn ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
class C
{
- public static Type f = typeof(Foo);
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type Main()
+ {
+ return f;
+ }
+
+ private static Type f;
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type Main()
+ {
+ return f;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(9,10): warning IL2078: 'C.Main()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The field 'C.f' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsMethodReturnType)
+ .WithSpan(9, 10, 9, 11)
+ .WithSpan(12, 22, 12, 23)
+ .WithArguments("C.Main()",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2078_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type Main()
+ {
+ return f;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ private static Type f;
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(9,10): warning IL2078: 'C.Main()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The field 'C.f' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsMethodReturnType)
+ .WithSpan(9, 10, 9, 11)
+ .WithArguments("C.Main()",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2079_MismatchFieldTargetsField ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ private static Type f1 = typeof(C);
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f2 = typeof(C);
public static void Main()
{
- f.GetMethod("Bar");
+ f2 = f1;
}
}
""";
var fixtest = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+
+ class C
+ {
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f1 = typeof(C);
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f2 = typeof(C);
+
+ public static void Main()
+ {
+ f2 = f1;
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(13,3): warning IL2079: value stored in field 'C.f2' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The field 'C.f1' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsField)
+ .WithSpan(13, 3, 13, 10)
+ .WithSpan(6, 22, 6, 36)
+ .WithArguments("C.f2",
+ "C.f1",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2079_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ private static Type f1 = typeof(C);
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f2 = typeof(C);
+
+ public static void Main()
+ {
+ f2 = f1;
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(14,3): warning IL2079: value stored in field 'C.f2' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The field 'C.f1' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsField)
+ .WithSpan(14, 3, 14, 10)
+ .WithArguments("C.f2",
+ "C.f1",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2080_MismatchFieldTargetsPrivateParam_PublicMethods ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
{
+ private static Type f = typeof(C);
+
+ public static void Main()
+ {
+ f.GetMethod("Foo");
+ }
}
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
class C
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- public static Type f = typeof(Foo);
+ private static Type f = typeof(C);
public static void Main()
{
- f.GetMethod("Bar");
+ f.GetMethod("Foo");
}
}
""";
await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(13,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ // /0/Test0.cs(10,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
// The field 'C.f' does not have matching annotations.
// The source value must declare at least the same requirements as those declared on the target location it is assigned to.
VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter)
- .WithSpan(13, 3, 13, 21)
- .WithArguments("System.Type.GetMethod(String)",
- "C.f",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ .WithSpan(10, 3, 10, 21)
+ .WithSpan(6, 22, 6, 35)
+ .WithArguments("System.Type.GetMethod(String)",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
fixedExpected: Array.Empty<DiagnosticResult> ());
}
[Fact]
- public async Task CodeFix_IL2080_MismatchFieldTargetsPublicParam_Int ()
+ public async Task CodeFix_IL2080_MismatchFieldTargetsPublicParam_PublicMethods ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
- {
- }
class C
{
- public static Type f = typeof(Foo);
+ public static Type f = typeof(C);
public static void Main()
{
- f.GetMethod("Bar");
+ f.GetMethod("Foo");
}
}
""";
var fixtest = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
- {
- }
class C
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- public static Type f = typeof(Foo);
+ public static Type f = typeof(C);
public static void Main()
{
- f.GetMethod("Bar");
+ f.GetMethod("Foo");
}
}
""";
await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(13,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ // /0/Test0.cs(10,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
// The field 'C.f' does not have matching annotations.
// The source value must declare at least the same requirements as those declared on the target location it is assigned to.
VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter)
- .WithSpan(13, 3, 13, 21)
- .WithArguments("System.Type.GetMethod(String)",
- "C.f",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ .WithSpan(10, 3, 10, 21)
+ .WithSpan(6, 21, 6, 34)
+ .WithArguments("System.Type.GetMethod(String)",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
fixedExpected: Array.Empty<DiagnosticResult> ());
}
- // these diagnosticIDs are currently unsupported, and as such will currently return no CodeFixers. However, they will soon be supported and as such comments have been left to indicate the error and fix they will accomplish.
+ [Fact]
+ public async Task CodeFix_IL2080_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public static Type f = typeof(C);
+
+ public static void Main()
+ {
+ f.GetMethod("Foo");
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(11,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
+ // The field 'C.f' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter)
+ .WithSpan(11, 3, 11, 21)
+ .WithArguments("System.Type.GetMethod(String)",
+ "C.f",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
[Fact]
- public async Task CodeFix_IL2067_MismatchParamTargetsParam_PublicMethods ()
+ public async Task CodeFix_IL2082_MismatchThisParamTargetsParam ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ private void M1()
+ {
+ M2(this);
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M1()
+ {
+ M2(this);
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(198,4): warning IL2082: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter)
+ .WithSpan(198, 4, 198, 12)
+ .WithSpan(196, 3, 199, 4)
+ .WithArguments("t",
+ "System.C.M2(Type)",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2082_ReturnKeepsOnCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private string M1()
+ {
+ M2(this);
+ return "Foo";
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private string M1()
+ {
+ M2(this);
+ return "Foo";
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(198,4): warning IL2082: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter)
+ .WithSpan(199, 4, 199, 12)
+ .WithSpan(196, 3, 201, 4)
+ .WithArguments("t",
+ "System.C.M2(Type)",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2082_ParamAttributeKeepsOnCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ private string M1([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] string s)
+ {
+ M2(this);
+ return s;
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private string M1([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] string s)
+ {
+ M2(this);
+ return s;
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(198,4): warning IL2082: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter)
+ .WithSpan(199, 4, 199, 12)
+ .WithSpan(196, 3, 201, 4)
+ .WithArguments("t",
+ "System.C.M2(Type)",
+ "System.C.M1(String)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 21)
+ .WithArguments("System.C.M1(String)")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2082_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ private void M1()
+ {
+ M2(this);
+ }
+
+ private static void M2([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t)
+ {
+ }
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(199,4): warning IL2082: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter)
+ .WithSpan(199, 4, 199, 12)
+ .WithArguments("t",
+ "System.C.M2(Type)",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'"),
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")};
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test), diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2083_MismatchThisParamTargetsMethodReturn ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private Type M1()
+ {
+ return this;
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private Type M1()
+ {
+ return this;
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(199,11): warning IL2083: 'System.C.M1()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType)
+ .WithSpan(199, 11, 199, 15)
+ .WithSpan(196, 3, 200, 4)
+ .WithArguments("System.C.M1()",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2083_ParamAttributeKeepsCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private Type M1([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] string s)
+ {
+ s.AsSpan();
+ return this;
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1("Foo");
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private Type M1([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] string s)
+ {
+ s.AsSpan();
+ return this;
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(199,11): warning IL2083: 'System.C.M1()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType)
+ .WithSpan(200, 11, 200, 15)
+ .WithSpan(196, 3, 201, 4)
+ .WithArguments("System.C.M1(String)",
+ "System.C.M1(String)",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 21)
+ .WithArguments("System.C.M1(String)")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2083_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ private Type M1()
+ {
+ return this;
+ }
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(200,11): warning IL2083: 'System.C.M1()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType)
+ .WithSpan(200, 11, 200, 15)
+ .WithArguments("System.C.M1()",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'"),
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")};
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test), diag, diag);
+ }
+
+
+ [Fact]
+ public async Task CodeFix_IL2084_MismatchThisParamTargetsField ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M();
+ }
+
+ private void M()
+ {
+ f = this;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M()
+ {
+ f = this;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(198,4): warning IL2084: value stored in field 'System.C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
+ // The implicit 'this' argument of method 'System.C.M()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsField)
+ .WithSpan(198, 4, 198, 12)
+ .WithSpan(196, 3, 199, 4)
+ .WithArguments("System.C.f",
+ "System.C.M()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'") },
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 15)
+ .WithArguments("System.C.M()")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2085_MismatchThisParamTargetsThisParam ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ private void M1()
+ {
+ this.M2();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M2()
+ {
+ }
+ }
+ }
+ """;
+
+ var fixtest = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M1()
+ {
+ this.M2();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M2()
+ {
+ }
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), fixtest),
+ new[] {
+ // /0/Test0.cs(198,4): warning IL2085: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2()'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsThisParameter)
+ .WithSpan(198, 4, 198, 13)
+ .WithSpan(196, 3, 199, 4)
+ .WithArguments("System.C.M2()",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ new[] {
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")});
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2085_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ namespace System
+ {
+ class C : TestSystemTypeBase
+ {
+ public static void Main()
+ {
+ new C().M1();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
+ private void M1()
+ {
+ this.M2();
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private void M2()
+ {
+ }
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(199,4): warning IL2085: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2()'.
+ // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsThisParameter)
+ .WithSpan(199, 4, 199, 13)
+ .WithArguments("System.C.M2()",
+ "System.C.M1()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'"),
+ // /0/Test0.cs(193,4): warning IL2065: Value passed to implicit 'this' parameter of method 'System.C.M1()' can not be statically determined
+ // and may not meet 'DynamicallyAccessedMembersAttribute' requirements.
+ VerifyCS.Diagnostic(DiagnosticId.ImplicitThisCannotBeStaticallyDetermined)
+ .WithSpan(193, 4, 193, 16)
+ .WithArguments("System.C.M1()")};
+ await VerifyDynamicallyAccessedMembersCodeFix (string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test),
+ string.Concat (DynamicallyAccessedMembersAnalyzerTests.GetSystemTypeBase (), test), diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2087_MismatchTypeArgumentTargetsParameter ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+ class C
{
+ public static void Main()
+ {
+ M2<int>();
+ }
+
+ private static void M1(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+
+ private static void M2<T>()
+ {
+ M1(typeof(T));
+ }
}
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
class C
{
public static void Main()
{
- M(typeof(Foo));
+ M2<int>();
}
- private static void NeedsPublicMethodsOnParameter(
- [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type parameter)
+ private static void M1(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
{
}
- private static void M(Type type)
+ private static void M2<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ M1(typeof(T));
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(18,3): warning IL2087: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.M1(Type)'.
+ // The generic parameter 'T' of 'C.M2<T>()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter)
+ .WithSpan(18, 3, 18, 16)
+ .WithSpan(16, 25, 16, 26)
+ .WithArguments("type",
+ "C.M1(Type)",
+ "T",
+ "C.M2<T>()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2088_MismatchTypeArgumentTargetsMethodReturnType ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M<int>();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ private static Type M<T>()
+ {
+ return typeof(T);
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M<int>();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ private static Type M<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>()
+ {
+ return typeof(T);
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(14,10): warning IL2088: 'C.M<T>()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' requirements.
+ // The generic parameter 'T' of 'C.M<T>()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType)
+ .WithSpan(14, 10, 14, 19)
+ .WithSpan(12, 24, 12, 25)
+ .WithArguments("C.M<T>()",
+ "T",
+ "C.M<T>()",
+ "'DynamicallyAccessedMemberTypes.PublicConstructors'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2088_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M<int>();
+ }
+
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ private static Type M<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ return typeof(T);
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(14,10): warning IL2088: 'C.M<T>()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' requirements.
+ // The generic parameter 'T' of 'C.M<T>()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType)
+ .WithSpan(14, 10, 14, 19)
+ .WithArguments("C.M<T>()",
+ "T",
+ "C.M<T>()",
+ "'DynamicallyAccessedMemberTypes.PublicConstructors'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2089_MismatchTypeArgumentTargetsField ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main<T>()
+ {
+ f = typeof(T);
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ f = typeof(T);
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(8,3): warning IL2089: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. The generic parameter 'T' of 'C.Main<T>()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField)
+ .WithSpan(8, 3, 8, 16)
+ .WithSpan(6, 26, 6, 27)
+ .WithArguments("C.f",
+ "T",
+ "C.Main<T>()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2089_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] T>()
+ {
+ f = typeof(T);
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ private static Type f;
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(8,3): warning IL2089: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. The generic parameter 'T' of 'C.Main<T>()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField)
+ .WithSpan(8, 3, 8, 16)
+ .WithArguments("C.f",
+ "T",
+ "C.Main<T>()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
+
+
+ [Fact]
+ public async Task CodeFix_IL2090_MismatchTypeArgumentTargetsThisParameter ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C<T> {
+
+ void M()
+ {
+ typeof(T).GetMethods();
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> {
+
+ void M()
+ {
+ typeof(T).GetMethods();
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest,
+ new[] {
+ // /0/Test0.cs(8,3): warning IL2090: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'.
+ // The generic parameter 'T' of 'C<T>' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter)
+ .WithSpan(8, 3, 8, 25)
+ .WithSpan(4, 9, 4, 10)
+ .WithArguments("System.Type.GetMethods()",
+ "T",
+ "C<T>",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2090_AttributeTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T> {
+
+ void M()
+ {
+ typeof(T).GetMethods();
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test,
+ new[] {
+ // /0/Test0.cs(8,3): warning IL2090: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'.
+ // The generic parameter 'T' of 'C<T>' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter)
+ .WithSpan(8, 3, 8, 25)
+ .WithArguments("System.Type.GetMethods()",
+ "T",
+ "C<T>",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2090_AttributeTurnsOffCodeFix_None ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ class C<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)] T> {
+
+ void M()
+ {
+ typeof(T).GetMethods();
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test,
+ new[] {
+ // /0/Test0.cs(8,3): warning IL2090: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'.
+ // The generic parameter 'T' of 'C<T>' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter)
+ .WithSpan(8, 3, 8, 25)
+ .WithArguments("System.Type.GetMethods()",
+ "T",
+ "C<T>",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2091_MismatchTypeTargetsGenericParameter ()
+ {
+ var test = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M2<int>();
+ }
+
+ private static void M1<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ }
+
+ private static void M2<S>()
+ {
+ M1<S>();
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M2<int>();
+ }
+
+ private static void M1<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ }
+
+ private static void M2<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] S>()
{
- NeedsPublicMethodsOnParameter(type);
- }
- }
- """;
- // var fixtest = $$"""
- //using System;
- //using System.Diagnostics.CodeAnalysis;
-
- //public class Foo
- //{
- //}
-
- //class C
- //{
- //public static void Main()
- //{
- // M(typeof(Foo));
- //}
-
- //private static void NeedsPublicMethodsOnParameter(
- // [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type parameter)
- //{
- //}
-
- //private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
- //{
- // NeedsPublicMethodsOnParameter(type);
- //}
- //}
- //""";
- // await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new [] {
- // // /0/Test0.cs(22,3): warning IL2067: 'parameter' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'.
- // // The parameter 'type' of method 'C.M(Type)' does not have matching annotations.
- // // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter).WithSpan(22, 3, 22, 38).WithArguments("parameter", "C.NeedsPublicMethodsOnParameter(Type)", "type", "C.M(Type)", "'DynamicallyAccessedMemberTypes.PublicMethods'")},
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter)
- .WithSpan(22, 3, 22, 38)
- .WithArguments("parameter",
- "C.NeedsPublicMethodsOnParameter(Type)",
- "type", "C.M(Type)",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ M1<S>();
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest,
+ new[] {
+ // /0/Test0.cs(16,3): warning IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in 'C.M1<T>()'.
+ // The generic parameter 'S' of 'C.M2<S>()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter)
+ .WithSpan(16, 3, 16, 8)
+ .WithSpan(14, 25, 14, 26)
+ .WithArguments("T",
+ "C.M1<T>()",
+ "S",
+ "C.M2<S>()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2091_AttrbuteTurnsOffCodeFix ()
+ {
+ var test = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ class C
+ {
+ public static void Main()
+ {
+ M2<int>();
+ }
+
+ private static void M1<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>()
+ {
+ }
+
+ private static void M2<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)] S>()
+ {
+ M1<S>();
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(16,3): warning IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in 'C.M1<T>()'.
+ // The generic parameter 'S' of 'C.M2<S>()' does not have matching annotations.
+ // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter)
+ .WithSpan(16, 3, 16, 8)
+ .WithArguments("T",
+ "C.M1<T>()",
+ "S",
+ "C.M2<S>()",
+ "'DynamicallyAccessedMemberTypes.PublicMethods'")};
await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
}
@@ -401,7 +2454,7 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
public class Base
{
- public virtual void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
}
public class C : Base
@@ -409,44 +2462,38 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
public override void M(Type t) {}
public static void Main() {
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ public class Base
+ {
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+ }
+
+ public class C : Base
+ {
+ public override void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+
+ public static void Main() {
}
}
""";
- // var fixtest = $$"""
- //using System;
- //using System.Diagnostics.CodeAnalysis;
-
- //public class Base
- //{
- // public virtual void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
- //}
-
- //public class C : Base
- //{
- // public override void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
-
- // public static void Main() {
-
- //}
- //}
- //""";
- // await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new [] {
- // // /0/Test0.cs(11,33): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
- // // don't match overridden parameter 't' of method 'Base.M(Type)'.
- // // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
- // .WithSpan(11, 30, 11, 31)
- // .WithArguments("t", "C.M(Type)",
- // "t",
- // "Base.M(Type)") },
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
- .WithSpan(11, 30, 11, 31)
- .WithArguments("t", "C.M(Type)",
- "t",
- "Base.M(Type)") };
- await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(11,30): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
+ // don't match overridden parameter 't' of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
+ .WithSpan(11, 30, 11, 31)
+ .WithSpan(11, 30, 11, 31)
+ .WithArguments("t",
+ "C.M(Type)",
+ "t",
+ "Base.M(Type)") },
+ fixedExpected: Array.Empty<DiagnosticResult> (), 1);
}
[Fact]
@@ -463,215 +2510,339 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
public class C : Base
{
- public override void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+ public override void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
public static void Main() {
}
}
""";
- //var fixtest = $$"""
- //using System;
- //using System.Diagnostics.CodeAnalysis;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
- //public class Base
- //{
- // public virtual void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
- //}
+ public class Base
+ {
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+ }
- //public class C : Base
- //{
- // public override void M([DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+ public class C : Base
+ {
+ public override void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
- // public static void Main() {
+ public static void Main() {
- //}
- //}
- //""";
- // await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new [] {
- // // /0/Test0.cs(11,140): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
- // // don't match overridden parameter 't' of method 'Base.M(Type)'.
- // // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
- // .WithSpan(11, 140, 11, 141)
- // .WithArguments("t", "C.M(Type)",
- // "t",
- // "Base.M(Type)") },
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
- .WithSpan(11, 140, 11, 141)
- .WithArguments("t", "C.M(Type)",
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(11,108): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
+ // don't match overridden parameter 't' of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
+ .WithSpan(11, 108, 11, 109)
+ .WithSpan(6, 29, 6, 30)
+ .WithArguments("t",
+ "C.M(Type)",
+ "t",
+ "Base.M(Type)") },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2092_BothAttributesTurnOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ public class Base
+ {
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {}
+ }
+
+ public class C : Base
+ {
+ public override void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+
+ public static void Main() {
+
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(11,108): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
+ // don't match overridden parameter 't' of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
+ .WithSpan(11, 108, 11, 109)
+ .WithArguments("t",
+ "C.M(Type)",
"t",
"Base.M(Type)") };
await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
}
[Fact]
- public async Task CodeFix_IL2069_MismatchParamTargetsField_PublicMethods ()
+ public async Task CodeFix_IL2092_TwoAttributesTurnOffCodeFix ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- public class Foo
+ public class Base
{
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicFields)] Type t) {}
}
- class C
+ public class C : Base
{
- public static void Main()
- {
- M(typeof(Foo));
- }
+ public override void M(Type t) {}
+
+ public static void Main() {
- private static void M(Type type)
- {
- f = type;
}
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(11,108): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
+ // don't match overridden parameter 't' of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
+ .WithSpan(11, 30, 11, 31)
+ .WithSpan(11, 30, 11, 31)
+ .WithArguments("t",
+ "C.M(Type)",
+ "t",
+ "Base.M(Type)") };
+ await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
+ }
- [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- private static Type f = typeof(Foo);
- }
- """;
-
- //var fixtest = $$"""
- //using System;
- //using System.Diagnostics.CodeAnalysis;
-
- //public class Foo
- //{
- //}
-
- //class C
- //{
- // public static void Main()
- // {
- // M(typeof(Foo));
- // }
-
- // private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
- // {
- // f = type;
- // }
-
- // [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- // private static Type f = typeof(Foo);
- //}
- //""";
- // await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new [] {
- // // /0/Test0.cs(17,3): warning IL2069: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements.
- // // The parameter 'type' of method 'C.M(Type)' does not have matching annotations.
- // // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField)
- // .WithSpan(17, 3, 17, 11)
- // .WithArguments("C.f",
- // "type",
- // "C.M(Type)",
- // "'DynamicallyAccessedMemberTypes.PublicMethods'")},
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField)
- .WithSpan(17, 3, 17, 11)
- .WithArguments("C.f",
- "type",
+ [Fact]
+ public async Task CodeFix_IL2092_BothAttributesTurnOffCodeFix_None ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ public class Base
+ {
+ public virtual void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)] Type t) {}
+ }
+
+ public class C : Base
+ {
+ public override void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {}
+
+ public static void Main() {
+
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(11,108): warning IL2092: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 't' of method 'C.M(Type)'
+ // don't match overridden parameter 't' of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides)
+ .WithSpan(11, 108, 11, 109)
+ .WithArguments("t",
"C.M(Type)",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ "t",
+ "Base.M(Type)") };
await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
}
[Fact]
- public async Task CodeFix_IL2075_MethodReturnTargetsParam_PublicMethods ()
+ public async Task CodeFix_IL2093_MismatchOnMethodReturnValueBetweenOverrides ()
{
var test = $$"""
using System;
+ using System.Diagnostics.CodeAnalysis;
- public class Foo
+ public class Base
{
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
}
- class C
+ public class C : Base
{
- public static void Main()
- {
- GetFoo().GetMethod("Bar");
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
}
- private static Type GetFoo ()
- {
- return typeof (Foo);
+ public static void Main() {
}
}
""";
- // var fixtest = $$"""
- //using System;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
- //public class Foo
- //{
- //}
+ public class Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+ }
- //class C
- //{
- // public static void Main()
- // {
- // GetFoo().GetMethod("Bar");
- //}
+ public class C : Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
- // [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
- //private static Type GetFoo ()
- //{
- // return typeof (Foo);
- //}
- //}
- //""";
- //await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
- // // /0/Test0.cs(11,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'.
- // // The return value of method 'C.GetFoo()' does not have matching annotations.
- // // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
- // .WithSpan(11, 3, 11, 28)
- // .WithArguments("System.Type.GetMethod(String)",
- // "C.GetFoo()",
- // "'DynamicallyAccessedMemberTypes.PublicMethods'")},
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter)
- .WithSpan(11, 3, 11, 28)
- .WithArguments("System.Type.GetMethod(String)",
- "C.GetFoo()",
- "'DynamicallyAccessedMemberTypes.PublicMethods'")};
+ public static void Main() {
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(14,23): warning IL2093: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'C.M(Type)'
+ // don't match overridden return value of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides)
+ .WithSpan(14, 23, 14, 24)
+ .WithSpan(14, 23, 14, 24)
+ .WithArguments("C.M(Type)",
+ "Base.M(Type)")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2093_MismatchOnMethodReturnValueBetweenOverrides_Reversed ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ public class Base
+ {
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+ }
+
+ public class C : Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+
+ public static void Main() {
+ }
+ }
+ """;
+ var fixtest = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ public class Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+ }
+
+ public class C : Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+
+ public static void Main() {
+ }
+ }
+ """;
+ await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new[] {
+ // /0/Test0.cs(14,23): warning IL2093: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'C.M(Type)'
+ // don't match overridden return value of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides)
+ .WithSpan(14, 23, 14, 24)
+ .WithSpan(6, 25, 6, 26)
+ .WithArguments("C.M(Type)",
+ "Base.M(Type)")},
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public async Task CodeFix_IL2093_BothAttributesTurnOffCodeFix ()
+ {
+ var test = $$"""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ public class Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+ }
+
+ public class C : Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+
+ public static void Main() {
+ }
+ }
+ """;
+ var diag = new[] {
+ // /0/Test0.cs(15,23): warning IL2093: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'C.M(Type)'
+ // don't match overridden return value of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides)
+ .WithSpan(15, 23, 15, 24)
+ .WithArguments("C.M(Type)",
+ "Base.M(Type)")};
await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
}
[Fact]
- public async Task CodeFix_IL2068_MismatchParamTargetsMethodReturn ()
+ public async Task CodeFix_IL2093_AttributesTurnOffCodeFix_None ()
{
var test = $$"""
using System;
using System.Diagnostics.CodeAnalysis;
- class C
+ public class Base
{
- [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
- Type M(Type t) {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)]
+ public virtual Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
return t;
+ }
}
+
+ public class C : Base
+ {
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type t) {
+ return t;
+ }
+
+ public static void Main() {
+ }
}
""";
- // await VerifyDynamicallyAccessedMembersCodeFix (test, fixtest, new [] {
- // // /0/Test0.cs(8,10): warning IL2068: 'C.M(Type)' method return value does not satisfy 'DynamicallyAccessedMemberTypes.All' requirements.
- // // The parameter 't' of method 'C.M(Type)' does not have matching annotations.
- // // The source value must declare at least the same requirements as those declared on the target location it is assigned to.
- // VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType)
- // .WithSpan(8, 10, 8, 11)
- // .WithArguments("C.M(Type)",
- // "t",
- // "C.M(Type)",
- // "'DynamicallyAccessedMemberTypes.All'")},
- // fixedExpected: Array.Empty<DiagnosticResult> ());
- var diag = new[] {VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType)
- .WithSpan(8, 10, 8, 11)
- .WithArguments("C.M(Type)",
- "t",
- "C.M(Type)",
- "'DynamicallyAccessedMemberTypes.All'")};
+ var diag = new[] {
+ // /0/Test0.cs(15,23): warning IL2093: 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'C.M(Type)'
+ // don't match overridden return value of method 'Base.M(Type)'.
+ // All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.
+ VerifyCS.Diagnostic(DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides)
+ .WithSpan(15, 23, 15, 24)
+ .WithArguments("C.M(Type)",
+ "Base.M(Type)")};
await VerifyDynamicallyAccessedMembersCodeFix (test, test, diag, diag);
}
}