diff --git a/src/ILLink.RoslynAnalyzer/INamedTypeSymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/INamedTypeSymbolExtensions.cs
new file mode 100644
index 000000000000..bdccec06903a
--- /dev/null
+++ b/src/ILLink.RoslynAnalyzer/INamedTypeSymbolExtensions.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.CodeAnalysis;
+
+namespace ILLink.RoslynAnalyzer
+{
+ static class INamedTypeSymbolExtensions
+ {
+ ///
+ /// Returns true if has the same name as
+ ///
+ internal static bool HasName (this INamedTypeSymbol type, string typeName)
+ {
+ var roSpan = typeName.AsSpan ();
+ INamespaceOrTypeSymbol? currentType = type;
+ while (roSpan.Length > 0) {
+ var dot = roSpan.LastIndexOf ('.');
+ var currentName = dot < 0 ? roSpan : roSpan.Slice (dot + 1);
+ if (currentType is null ||
+ !currentName.Equals (currentType.Name.AsSpan (), StringComparison.Ordinal)) {
+ return false;
+ }
+ currentType = (INamespaceOrTypeSymbol?) currentType.ContainingType ?? currentType.ContainingNamespace;
+ roSpan = roSpan.Slice (0, dot > 0 ? dot : 0);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
new file mode 100644
index 000000000000..f458cc1fecb0
--- /dev/null
+++ b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.CodeAnalysis;
+
+namespace ILLink.RoslynAnalyzer
+{
+ static class ISymbolExtensions
+ {
+ ///
+ /// Returns true if symbol has an attribute with name .
+ ///
+ internal static bool HasAttribute (this ISymbol symbol, string attributeName)
+ {
+ foreach (var attr in symbol.GetAttributes ())
+ if (attr.AttributeClass?.Name == attributeName)
+ return true;
+
+ return false;
+ }
+
+ internal static bool TryGetRequiresAssemblyFileAttribute (this ISymbol symbol, out AttributeData? attribute)
+ {
+ attribute = null;
+ foreach (var _attribute in symbol.GetAttributes ()) {
+ if (_attribute.AttributeClass is var attrClass && attrClass != null &&
+ attrClass.HasName (RequiresAssemblyFilesAnalyzer.FullyQualifiedRequiresAssemblyFilesAttribute) &&
+ _attribute.ConstructorArguments.Length == 0) {
+ attribute = _attribute;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal static bool TryGetAttributeWithMessageOnCtor (this ISymbol symbol, string qualifiedAttributeName, out AttributeData? attribute)
+ {
+ attribute = null;
+ foreach (var _attribute in symbol.GetAttributes ()) {
+ if (_attribute.AttributeClass is var attrClass && attrClass != null &&
+ attrClass.HasName (qualifiedAttributeName) && _attribute.ConstructorArguments.Length >= 1 &&
+ _attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg) {
+ attribute = _attribute;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
new file mode 100644
index 000000000000..65006691c3c9
--- /dev/null
+++ b/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace ILLink.RoslynAnalyzer
+{
+ [DiagnosticAnalyzer (LanguageNames.CSharp)]
+ public sealed class RequiresAssemblyFilesAnalyzer : DiagnosticAnalyzer
+ {
+ public const string IL3002 = nameof (IL3002);
+ internal const string RequiresAssemblyFilesAttribute = nameof (RequiresAssemblyFilesAttribute);
+ internal const string FullyQualifiedRequiresAssemblyFilesAttribute = "System.Diagnostics.CodeAnalysis." + RequiresAssemblyFilesAttribute;
+
+ static readonly DiagnosticDescriptor s_requiresAssemblyFilesRule = new DiagnosticDescriptor (
+ IL3002,
+ new LocalizableResourceString (nameof (Resources.RequiresAssemblyFilesTitle),
+ Resources.ResourceManager, typeof (Resources)),
+ new LocalizableResourceString (nameof (Resources.RequiresAssemblyFilesMessage),
+ Resources.ResourceManager, typeof (Resources)),
+ DiagnosticCategory.SingleFile,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (s_requiresAssemblyFilesRule);
+
+ public override void Initialize (AnalysisContext context)
+ {
+ context.EnableConcurrentExecution ();
+ context.ConfigureGeneratedCodeAnalysis (GeneratedCodeAnalysisFlags.ReportDiagnostics);
+
+ context.RegisterCompilationStartAction (context => {
+ var compilation = context.Compilation;
+
+ var isSingleFilePublish = context.Options.GetMSBuildPropertyValue (MSBuildPropertyOptionNames.PublishSingleFile, compilation);
+ if (!string.Equals (isSingleFilePublish?.Trim (), "true", StringComparison.OrdinalIgnoreCase))
+ return;
+
+ var includesAllContent = context.Options.GetMSBuildPropertyValue (MSBuildPropertyOptionNames.IncludeAllContentForSelfExtract, compilation);
+ if (string.Equals (includesAllContent?.Trim (), "true", StringComparison.OrdinalIgnoreCase))
+ return;
+
+ context.RegisterOperationAction (operationContext => {
+ var methodInvocation = (IInvocationOperation) operationContext.Operation;
+ CheckCalledMember (operationContext, methodInvocation.TargetMethod);
+ }, OperationKind.Invocation);
+
+ context.RegisterOperationAction (operationContext => {
+ var objectCreation = (IObjectCreationOperation) operationContext.Operation;
+ CheckCalledMember (operationContext, objectCreation.Constructor);
+ }, OperationKind.ObjectCreation);
+
+ context.RegisterOperationAction (operationContext => {
+ var propAccess = (IPropertyReferenceOperation) operationContext.Operation;
+ var prop = propAccess.Property;
+ var usageInfo = propAccess.GetValueUsageInfo (prop);
+ if (usageInfo.HasFlag (ValueUsageInfo.Read) && prop.GetMethod != null)
+ CheckCalledMember (operationContext, prop.GetMethod);
+
+ if (usageInfo.HasFlag (ValueUsageInfo.Write) && prop.SetMethod != null)
+ CheckCalledMember (operationContext, prop.SetMethod);
+
+ CheckCalledMember (operationContext, prop);
+ }, OperationKind.PropertyReference);
+
+ context.RegisterOperationAction (operationContext => {
+ var eventRef = (IEventReferenceOperation) operationContext.Operation;
+ CheckCalledMember (operationContext, eventRef.Member);
+ }, OperationKind.EventReference);
+
+ static void CheckCalledMember (
+ OperationAnalysisContext operationContext,
+ ISymbol member)
+ {
+ // Do not emit any diagnostic if caller is annotated with the attribute too.
+ if (operationContext.ContainingSymbol.HasAttribute (RequiresAssemblyFilesAttribute))
+ return;
+
+ if (member.TryGetRequiresAssemblyFileAttribute (out AttributeData? requiresAssemblyFilesAttribute)) {
+ operationContext.ReportDiagnostic (Diagnostic.Create (
+ s_requiresAssemblyFilesRule,
+ operationContext.Operation.Syntax.GetLocation (),
+ member.OriginalDefinition.ToString (),
+ requiresAssemblyFilesAttribute?.NamedArguments.FirstOrDefault (na => na.Key == "Message").Value.Value?.ToString (),
+ requiresAssemblyFilesAttribute?.NamedArguments.FirstOrDefault (na => na.Key == "Url").Value.Value?.ToString ()));
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
index 1b93e3cf3971..50744cbb7884 100644
--- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
@@ -15,8 +15,10 @@ namespace ILLink.RoslynAnalyzer
public class RequiresUnreferencedCodeAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "IL2026";
+ const string RequiresUnreferencedCodeAttribute = nameof (RequiresUnreferencedCodeAttribute);
+ const string FullyQualifiedRequiresUnreferencedCodeAttribute = "System.Diagnostics.CodeAnalysis." + RequiresUnreferencedCodeAttribute;
- private static readonly DiagnosticDescriptor s_rule = new DiagnosticDescriptor (
+ static readonly DiagnosticDescriptor s_requiresUnreferencedCodeRule = new DiagnosticDescriptor (
DiagnosticId,
new LocalizableResourceString (nameof (Resources.RequiresUnreferencedCodeAnalyzerTitle),
Resources.ResourceManager, typeof (Resources)),
@@ -26,7 +28,7 @@ public class RequiresUnreferencedCodeAnalyzer : DiagnosticAnalyzer
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
- public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (s_rule);
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (s_requiresUnreferencedCodeRule);
public override void Initialize (AnalysisContext context)
{
@@ -46,46 +48,41 @@ public override void Initialize (AnalysisContext context)
if (call.IsVirtual && call.TargetMethod.OverriddenMethod != null)
return;
- CheckMethodOrCtorCall (operationContext, call.TargetMethod, call.Syntax.GetLocation ());
+ CheckMethodOrCtorCall (operationContext, call.TargetMethod);
}, OperationKind.Invocation);
context.RegisterOperationAction (operationContext => {
var call = (IObjectCreationOperation) operationContext.Operation;
- CheckMethodOrCtorCall (operationContext, call.Constructor, call.Syntax.GetLocation ());
+ CheckMethodOrCtorCall (operationContext, call.Constructor);
}, OperationKind.ObjectCreation);
context.RegisterOperationAction (operationContext => {
var propAccess = (IPropertyReferenceOperation) operationContext.Operation;
var prop = propAccess.Property;
var usageInfo = propAccess.GetValueUsageInfo (prop);
- if (usageInfo.HasFlag (ValueUsageInfo.Read) && prop.GetMethod != null) {
- CheckMethodOrCtorCall (
- operationContext,
- prop.GetMethod,
- propAccess.Syntax.GetLocation ());
- }
- if (usageInfo.HasFlag (ValueUsageInfo.Write) && prop.SetMethod != null) {
- CheckMethodOrCtorCall (
- operationContext,
- prop.SetMethod,
- propAccess.Syntax.GetLocation ());
- }
+ if (usageInfo.HasFlag (ValueUsageInfo.Read) && prop.GetMethod != null)
+ CheckMethodOrCtorCall (operationContext, prop.GetMethod);
+
+ if (usageInfo.HasFlag (ValueUsageInfo.Write) && prop.SetMethod != null)
+ CheckMethodOrCtorCall (operationContext, prop.SetMethod);
}, OperationKind.PropertyReference);
- void CheckMethodOrCtorCall (
+ static void CheckMethodOrCtorCall (
OperationAnalysisContext operationContext,
- IMethodSymbol method,
- Location location)
+ IMethodSymbol method)
{
- AttributeData? requiresUnreferencedCode;
// If parent method contains RequiresUnreferencedCodeAttribute then we shouldn't report diagnostics for this method
if (operationContext.ContainingSymbol is IMethodSymbol &&
- TryGetRequiresUnreferencedCodeAttribute (operationContext.ContainingSymbol.GetAttributes (), out requiresUnreferencedCode))
+ operationContext.ContainingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute))
+ return;
+
+ if (!method.HasAttribute (RequiresUnreferencedCodeAttribute))
return;
- if (TryGetRequiresUnreferencedCodeAttribute (method.GetAttributes (), out requiresUnreferencedCode)) {
+
+ if (method.TryGetAttributeWithMessageOnCtor (FullyQualifiedRequiresUnreferencedCodeAttribute, out AttributeData? requiresUnreferencedCode)) {
operationContext.ReportDiagnostic (Diagnostic.Create (
- s_rule,
- location,
+ s_requiresUnreferencedCodeRule,
+ operationContext.Operation.Syntax.GetLocation (),
method.OriginalDefinition.ToString (),
(string) requiresUnreferencedCode!.ConstructorArguments[0].Value!,
requiresUnreferencedCode!.NamedArguments.FirstOrDefault (na => na.Key == "Url").Value.Value?.ToString ()));
@@ -93,44 +90,5 @@ void CheckMethodOrCtorCall (
}
});
}
-
- ///
- /// Returns true if has the same name as
- ///
- internal static bool IsNamedType (INamedTypeSymbol type, string typeName)
- {
- var roSpan = typeName.AsSpan ();
- INamespaceOrTypeSymbol? currentType = type;
- while (roSpan.Length > 0) {
- var dot = roSpan.LastIndexOf ('.');
- var currentName = dot < 0 ? roSpan : roSpan.Slice (dot + 1);
- if (currentType is null ||
- !currentName.Equals (currentType.Name.AsSpan (), StringComparison.Ordinal)) {
- return false;
- }
- currentType = (INamespaceOrTypeSymbol?) currentType.ContainingType ?? currentType.ContainingNamespace;
- roSpan = roSpan.Slice (0, dot > 0 ? dot : 0);
- }
-
- return true;
- }
-
- ///
- /// Returns a RequiresUnreferencedCodeAttribute if found
- ///
- static bool TryGetRequiresUnreferencedCodeAttribute (ImmutableArray attributes, out AttributeData? requiresUnreferencedCode)
- {
- requiresUnreferencedCode = null;
- foreach (var attr in attributes) {
- if (attr.AttributeClass is { } attrClass &&
- IsNamedType (attrClass, "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute") &&
- attr.ConstructorArguments.Length == 1 &&
- attr.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg) {
- requiresUnreferencedCode = attr;
- return true;
- }
- }
- return false;
- }
}
}
diff --git a/src/ILLink.RoslynAnalyzer/Resources.resx b/src/ILLink.RoslynAnalyzer/Resources.resx
index 202514e6dcc2..86ac84a05afd 100644
--- a/src/ILLink.RoslynAnalyzer/Resources.resx
+++ b/src/ILLink.RoslynAnalyzer/Resources.resx
@@ -135,4 +135,10 @@
'{0}' will throw for assemblies embedded in a single-file app
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ILLink.RoslynAnalyzer/SingleFileAnalyzer.cs b/src/ILLink.RoslynAnalyzer/SingleFileAnalyzer.cs
index 536cd82f266c..15f17caf3cac 100644
--- a/src/ILLink.RoslynAnalyzer/SingleFileAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/SingleFileAnalyzer.cs
@@ -20,7 +20,7 @@ public sealed class AvoidAssemblyLocationInSingleFile : DiagnosticAnalyzer
public const string IL3000 = nameof (IL3000);
public const string IL3001 = nameof (IL3001);
- private static readonly DiagnosticDescriptor LocationRule = new DiagnosticDescriptor (
+ static readonly DiagnosticDescriptor s_locationRule = new DiagnosticDescriptor (
IL3000,
new LocalizableResourceString (nameof (Resources.AvoidAssemblyLocationInSingleFileTitle),
Resources.ResourceManager, typeof (Resources)),
@@ -30,7 +30,7 @@ public sealed class AvoidAssemblyLocationInSingleFile : DiagnosticAnalyzer
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
- private static readonly DiagnosticDescriptor GetFilesRule = new DiagnosticDescriptor (
+ static readonly DiagnosticDescriptor s_getFilesRule = new DiagnosticDescriptor (
IL3001,
new LocalizableResourceString (nameof (Resources.AvoidAssemblyGetFilesInSingleFileTitle),
Resources.ResourceManager, typeof (Resources)),
@@ -40,7 +40,7 @@ public sealed class AvoidAssemblyLocationInSingleFile : DiagnosticAnalyzer
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
- public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (LocationRule, GetFilesRule);
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create (s_locationRule, s_getFilesRule);
public override void Initialize (AnalysisContext context)
{
@@ -88,7 +88,7 @@ public override void Initialize (AnalysisContext context)
return;
}
- operationContext.ReportDiagnostic (Diagnostic.Create (LocationRule, access.Syntax.GetLocation (), property));
+ operationContext.ReportDiagnostic (Diagnostic.Create (s_locationRule, access.Syntax.GetLocation (), property));
}, OperationKind.PropertyReference);
context.RegisterOperationAction (operationContext => {
@@ -98,7 +98,7 @@ public override void Initialize (AnalysisContext context)
return;
}
- operationContext.ReportDiagnostic (Diagnostic.Create (GetFilesRule, invocation.Syntax.GetLocation (), targetMethod));
+ operationContext.ReportDiagnostic (Diagnostic.Create (s_getFilesRule, invocation.Syntax.GetLocation (), targetMethod));
}, OperationKind.Invocation);
return;
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs
new file mode 100644
index 000000000000..466f81db88be
--- /dev/null
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Testing;
+using Xunit;
+using VerifyCS = ILLink.RoslynAnalyzer.Tests.CSharpAnalyzerVerifier<
+ ILLink.RoslynAnalyzer.RequiresAssemblyFilesAnalyzer>;
+
+namespace ILLink.RoslynAnalyzer.Tests
+{
+ public class RequiresAssemblyFilesAnalyzerTests
+ {
+ static Task VerifyRequiresAssemblyFilesAnalyzer (string source, params DiagnosticResult[] expected)
+ {
+ // TODO: Remove this once we have the new attribute in the runtime.
+ source = @"namespace System.Diagnostics.CodeAnalysis
+{
+#nullable enable
+ [AttributeUsage(AttributeTargets.Constructor |
+ AttributeTargets.Event |
+ AttributeTargets.Method |
+ AttributeTargets.Property,
+ Inherited = false,
+ AllowMultiple = false)]
+ public sealed class RequiresAssemblyFilesAttribute : Attribute
+ {
+ public RequiresAssemblyFilesAttribute() { }
+ public string? Message { get; set; }
+ public string? Url { get; set; }
+ }
+}" + Environment.NewLine + source;
+ return VerifyCS.VerifyAnalyzerAsync (source,
+ TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.PublishSingleFile),
+ expected);
+ }
+
+ [Fact]
+ public Task SimpleDiagnosticOnEvent ()
+ {
+ var TestRequiresAssemblyFieldsOnEvent = @"
+class C
+{
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles]
+ event System.EventHandler? E;
+
+ void M()
+ {
+ var handler = E;
+ }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFieldsOnEvent,
+ VerifyCS.Diagnostic ().WithSpan (25, 17, 25, 18).WithArguments ("C.E"));
+ }
+
+ [Fact]
+ public Task SimpleDiagnosticOnMethod ()
+ {
+ var TestRequiresAssemblyFilesOnMethod = @"
+class C
+{
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles]
+ void M1()
+ {
+ }
+
+ void M2()
+ {
+ M1();
+ }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnMethod,
+ VerifyCS.Diagnostic ().WithSpan (27, 3, 27, 7).WithArguments ("C.M2()"));
+ }
+
+ [Fact]
+ public Task SimpleDiagnosticOnProperty ()
+ {
+ var TestRequiresAssemblyFilesOnProperty = @"
+class C
+{
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles]
+ bool P { get; set; }
+
+ void M()
+ {
+ P = false;
+ bool b = P;
+ }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnProperty,
+ VerifyCS.Diagnostic ().WithSpan (25, 3, 25, 4).WithArguments ("C.P"),
+ VerifyCS.Diagnostic ().WithSpan (26, 12, 26, 13).WithArguments ("C.P"));
+ }
+
+ [Fact]
+ public Task RequiresAssemblyFilesWithMessageAndUrl ()
+ {
+ var TestRequiresAssemblyFilesWithMessageAndUrl = @"
+class C
+{
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles (Message = ""Message from attribute"", Url = ""https://helpurl"")]
+ void M1()
+ {
+ }
+
+ void M2()
+ {
+ M1();
+ }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesWithMessageAndUrl,
+ VerifyCS.Diagnostic ().WithSpan (27, 3, 27, 7).WithArguments ("C.M2()", "Message from attribute", "https://helpurl"));
+ }
+
+ [Fact]
+ public Task NoDiagnosticIfMethodNotCalled ()
+ {
+ var TestNoDiagnosticIfMethodNotCalled = @"
+class C
+{
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles]
+ void M() { }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestNoDiagnosticIfMethodNotCalled);
+ }
+
+ [Fact]
+ public Task NoDiagnosticIsProducedIfCallerIsAnnotated ()
+ {
+ var TestNoDiagnosticIsProducedIfCallerIsAnnotated = @"
+class C
+{
+ void M1()
+ {
+ M2();
+ }
+
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles (Message = ""Warn from M2"")]
+ void M2()
+ {
+ M3();
+ }
+
+ [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles (Message = ""Warn from M3"")]
+ void M3()
+ {
+ }
+}";
+ return VerifyRequiresAssemblyFilesAnalyzer (TestNoDiagnosticIsProducedIfCallerIsAnnotated,
+ VerifyCS.Diagnostic ().WithSpan (22, 3, 22, 7).WithArguments ("C.M2()", "Warn from M2"));
+ }
+ }
+}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
index 81899e8906d0..25050d50721a 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
@@ -32,7 +32,6 @@ class C
int M2() => M1();
}";
return VerifyRequiresUnreferencedCodeAnalyzer (TestRequiresWithMessageOnlyOnMethod,
- // (8,17): warning IL2026: Calling 'System.Int32 C::M1()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. message.
VerifyCS.Diagnostic ().WithSpan (8, 17, 8, 21).WithArguments ("C.M1()", "message", ""));
}
@@ -54,7 +53,6 @@ static void RequiresWithMessageAndUrl ()
}
}";
return VerifyRequiresUnreferencedCodeAnalyzer (MessageAndUrlOnMethod,
- // (8,3): warning IL2026: Calling 'C.RequiresWithMessageAndUrl()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --RequiresWithMessageAndUrl--.
VerifyCS.Diagnostic ().WithSpan (8, 3, 8, 31).WithArguments ("C.RequiresWithMessageAndUrl()", "Message for --RequiresWithMessageAndUrl--", "https://helpurl")
);
}
@@ -78,7 +76,6 @@ static int PropertyRequires {
}
}";
return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires,
- // (8,7): warning IL2026: Calling 'C.PropertyRequires.get' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --getter PropertyRequires--.
VerifyCS.Diagnostic ().WithSpan (8, 7, 8, 23).WithArguments ("C.PropertyRequires.get", "Message for --getter PropertyRequires--", "")
);
}
@@ -102,7 +99,6 @@ static int PropertyRequires {
}
}";
return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires,
- // (8,3): warning IL2026: Calling 'C.PropertyRequires.set' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --setter PropertyRequires--.
VerifyCS.Diagnostic ().WithSpan (8, 3, 8, 19).WithArguments ("C.PropertyRequires.set", "Message for --setter PropertyRequires--", "")
);
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
index c62c2d762004..458d0b34635b 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
@@ -11,7 +11,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Xunit;
namespace ILLink.RoslynAnalyzer.Tests