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:
authorJackson Schuster <jschuster@microsoft.com>2021-12-10 00:23:39 +0300
committerJackson Schuster <jschuster@microsoft.com>2021-12-10 01:44:46 +0300
commit012f3c0773c498c8601eb9af806aba1267b40342 (patch)
tree46965de7068594e8a0042b1d2a3805918d6b1d28
parent02d5a8c2fa2ead9bab2d14f00749010a37316802 (diff)
Use the ISymbol extensions for Requires analyzers
-rw-r--r--src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs24
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs428
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs3
3 files changed, 25 insertions, 430 deletions
diff --git a/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs
index efe00031b..e08359149 100644
--- a/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs
+++ b/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs
@@ -6,14 +6,35 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ILLink.RoslynAnalyzer
{
public static class RequiresISymbolExtensions
{
// TODO: Consider sharing with linker IsMethodInRequiresUnreferencedCodeScope method
+ /// <summary>
+ /// True if the source of a call is considered to be annotated with the Requires... attribute
+ /// </summary>
public static bool IsInRequiresScope (this ISymbol member, string requiresAttribute)
{
+ return member.IsInRequiresScope (requiresAttribute, true);
+ }
+
+ /// <summary>
+ /// True if member of a call is considered to be annotated with the Requires... attribute.
+ /// Doesn't check the associated symbol for overrides and virtual methods because the analyzer should warn on mismatched between the property AND the accessors
+ /// </summary>
+ /// <param name="containingSymbol">
+ /// Symbol that is either an overriding member or an overriden/virtual member
+ /// </param>
+ public static bool IsOverrideInRequiresScope(this ISymbol member, string requiresAttribute)
+ {
+ return member.IsInRequiresScope(requiresAttribute, false);
+ }
+
+ private static bool IsInRequiresScope (this ISymbol member, string requiresAttribute, bool checkAssociatedSymbol)
+ {
if (member is ISymbol containingSymbol) {
if (containingSymbol.HasAttribute (requiresAttribute)
|| (containingSymbol is not ITypeSymbol &&
@@ -21,7 +42,8 @@ namespace ILLink.RoslynAnalyzer
return true;
}
}
- if (member is IMethodSymbol { AssociatedSymbol: { } associated } && associated.HasAttribute (requiresAttribute))
+ // Only check associated symbol if not override or virtual method
+ if (checkAssociatedSymbol && member is IMethodSymbol { AssociatedSymbol: { } associated } && associated.HasAttribute (requiresAttribute))
return true;
return false;
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
deleted file mode 100644
index d2f8bf64d..000000000
--- a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
+++ /dev/null
@@ -1,428 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using ILLink.RoslynAnalyzer;
-using ILLink.Shared;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Testing;
-using Microsoft.CodeAnalysis.Text;
-using Xunit;
-using VerifyCS = ILLink.RoslynAnalyzer.Tests.CSharpCodeFixVerifier<
- ILLink.RoslynAnalyzer.RequiresUnreferencedCodeAnalyzer,
- ILLink.CodeFix.RequiresUnreferencedCodeCodeFixProvider>;
-
-namespace ILLink.RoslynAnalyzer.Tests
-{
- public class RequiresUnreferencedCodeAnalyzerTests
- {
- static readonly DiagnosticDescriptor dynamicInvocationDiagnosticDescriptor = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresUnreferencedCode, new DiagnosticString ("DynamicTypeInvocation"));
-
- static Task VerifyRequiresUnreferencedCodeAnalyzer (string source, params DiagnosticResult[] expected) =>
- VerifyRequiresUnreferencedCodeAnalyzer (source, null, expected);
-
- static async Task VerifyRequiresUnreferencedCodeAnalyzer (string source, IEnumerable<MetadataReference>? additionalReferences, params DiagnosticResult[] expected) =>
- await VerifyCS.VerifyAnalyzerAsync (source,
- TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer),
- additionalReferences ?? Array.Empty<MetadataReference> (),
- expected);
-
- static Task VerifyRequiresUnreferencedCodeCodeFix (
- string source,
- string fixedSource,
- DiagnosticResult[] baselineExpected,
- DiagnosticResult[] fixedExpected,
- int? numberOfIterations = null)
- {
- var test = new VerifyCS.Test {
- TestCode = source,
- FixedCode = fixedSource,
- ReferenceAssemblies = TestCaseUtils.Net6PreviewAssemblies
- };
- test.ExpectedDiagnostics.AddRange (baselineExpected);
- test.TestState.AnalyzerConfigFiles.Add (
- ("/.editorconfig", SourceText.From (@$"
-is_global = true
-build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
- if (numberOfIterations != null) {
- test.NumberOfIncrementalIterations = numberOfIterations;
- test.NumberOfFixAllIterations = numberOfIterations;
- }
- test.FixedState.ExpectedDiagnostics.AddRange (fixedExpected);
- return test.RunAsync ();
- }
-
-
-
- [Fact]
- public async Task SimpleDiagnosticFix ()
- {
- var test = @"
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- int M2() => M1();
-}
-class D
-{
- public int M3(C c) => c.M1();
-
- public class E
- {
- public int M4(C c) => c.M1();
- }
-}
-public class E
-{
- public class F
- {
- public int M5(C c) => c.M1();
- }
-}
-";
-
- var fixtest = @"
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- [RequiresUnreferencedCode(""Calls C.M1()"")]
- int M2() => M1();
-}
-class D
-{
- [RequiresUnreferencedCode(""Calls C.M1()"")]
- public int M3(C c) => c.M1();
-
- public class E
- {
- [RequiresUnreferencedCode(""Calls C.M1()"")]
- public int M4(C c) => c.M1();
- }
-}
-public class E
-{
- public class F
- {
- [RequiresUnreferencedCode()]
- public int M5(C c) => c.M1();
- }
-}
-";
-
- await VerifyRequiresUnreferencedCodeCodeFix (test, fixtest, new[] {
- // /0/Test0.cs(9,17): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (9, 17, 9, 21).WithArguments ("C.M1()", " message.", ""),
- // /0/Test0.cs(13,27): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(13, 27, 13, 33).WithArguments("C.M1()", " message.", ""),
- // /0/Test0.cs(17,31): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (17, 31, 17, 37).WithArguments ("C.M1()", " message.", ""),
- // /0/Test0.cs(24,31): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (24, 31, 24, 37).WithArguments ("C.M1()", " message.", "")
- }, new[] {
- // /0/Test0.cs(27,10): error CS7036: There is no argument given that corresponds to the required formal parameter 'message' of 'RequiresUnreferencedCodeAttribute.RequiresUnreferencedCodeAttribute(string)'
- DiagnosticResult.CompilerError("CS7036").WithSpan(27, 10, 27, 36).WithArguments("message", "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.RequiresUnreferencedCodeAttribute(string)"),
- }
- );
- }
-
- [Fact]
- public Task FixInLambda ()
- {
- var src = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- Action M2()
- {
- return () => M1();
- }
-}";
- var fix = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- Action M2()
- {
- return () => M1();
- }
-}";
- // No fix available inside a lambda, requries manual code change since attribute cannot
- // be applied
- return VerifyRequiresUnreferencedCodeCodeFix (
- src,
- fix,
- baselineExpected: new[] {
- // /0/Test0.cs(12,22): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(12, 22, 12, 26).WithArguments("C.M1()", " message.", "")
- },
- fixedExpected: Array.Empty<DiagnosticResult> ());
- }
-
- [Fact]
- public Task FixInLocalFunc ()
- {
- var src = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- Action M2()
- {
- void Wrapper () => M1();
- return Wrapper;
- }
-}";
- var fix = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- [RequiresUnreferencedCode(""Calls Wrapper()"")]
- Action M2()
- {
- [global::System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute(""Calls C.M1()"")] void Wrapper () => M1();
- return Wrapper;
- }
-}";
- // Roslyn currently doesn't simplify the attribute name properly, see https://github.com/dotnet/roslyn/issues/52039
- return VerifyRequiresUnreferencedCodeCodeFix (
- src,
- fix,
- baselineExpected: new[] {
- // /0/Test0.cs(12,28): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(12, 28, 12, 32).WithArguments("C.M1()", " message.", "")
- },
- fixedExpected: Array.Empty<DiagnosticResult> (),
- // The default iterations for the codefix is the number of diagnostics (1 in this case)
- // but since the codefixer introduces a new diagnostic in the first iteration, it needs
- // to run twice, so we need to set the number of iterations to 2.
- numberOfIterations: 2);
- }
-
- [Fact]
- public Task FixInCtor ()
- {
- var src = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public static int M1() => 0;
-
- public C() => M1();
-}";
- var fix = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public static int M1() => 0;
-
- [RequiresUnreferencedCode()]
- public C() => M1();
-}";
- // Roslyn currently doesn't simplify the attribute name properly, see https://github.com/dotnet/roslyn/issues/52039
- return VerifyRequiresUnreferencedCodeCodeFix (
- src,
- fix,
- baselineExpected: new[] {
- // /0/Test0.cs(10,19): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(10, 19, 10, 23).WithArguments("C.M1()", " message.", "")
- },
- fixedExpected: new[] {
- // /0/Test0.cs(10,6): error CS7036: There is no argument given that corresponds to the required formal parameter 'message' of 'RequiresUnreferencedCodeAttribute.RequiresUnreferencedCodeAttribute(string)'
- DiagnosticResult.CompilerError("CS7036").WithSpan(10, 6, 10, 32).WithArguments("message", "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.RequiresUnreferencedCodeAttribute(string)"),
- });
- }
-
- [Fact]
- public Task FixInPropertyDecl ()
- {
- var src = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- int M2 => M1();
-}";
- var fix = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-public class C
-{
- [RequiresUnreferencedCodeAttribute(""message"")]
- public int M1() => 0;
-
- int M2 => M1();
-}";
- // Can't apply RUC on properties at the moment
- return VerifyRequiresUnreferencedCodeCodeFix (
- src,
- fix,
- baselineExpected: new[] {
- // /0/Test0.cs(10,15): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(10, 15, 10, 19).WithArguments("C.M1()", " message.", "")
- },
- fixedExpected: new[] {
- // /0/Test0.cs(10,15): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
- VerifyCS.Diagnostic(DiagnosticId.RequiresUnreferencedCode).WithSpan(10, 15, 10, 19).WithArguments("C.M1()", " message.", "")
- });
- }
-
- [Fact]
- public Task InvocationOnDynamicType ()
- {
- var source = @"
-using System;
-class C
-{
- static void M0 ()
- {
- dynamic dynamicField = ""Some string"";
- Console.WriteLine (dynamicField);
- }
-
- static void M1 ()
- {
- MethodWithDynamicArgDoNothing (0);
- MethodWithDynamicArgDoNothing (""Some string"");
- MethodWithDynamicArg(-1);
- }
-
- static void MethodWithDynamicArgDoNothing (dynamic arg)
- {
- }
-
- static void MethodWithDynamicArg (dynamic arg)
- {
- arg.MethodWithDynamicArg (arg);
- }
-}";
-
- return VerifyRequiresUnreferencedCodeAnalyzer (source,
- // (8,3): warning IL2026: Invoking members on dynamic types is not trimming safe. Types or members might have been removed by the trimmer.
- VerifyCS.Diagnostic (dynamicInvocationDiagnosticDescriptor).WithSpan (8, 3, 8, 35),
- // (24,3): warning IL2026: Invoking members on dynamic types is not trimming safe. Types or members might have been removed by the trimmer.
- VerifyCS.Diagnostic (dynamicInvocationDiagnosticDescriptor).WithSpan (24, 3, 24, 33));
- }
-
- [Fact]
- public Task InvocationOnDynamicTypeInMethodWithRUCDoesNotWarnTwoTimes ()
- {
- var source = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-class C
-{
- [RequiresUnreferencedCode (""We should only see the warning related to this annotation, and none about the dynamic type."")]
- static void M0 ()
- {
- dynamic dynamicField = ""Some string"";
- Console.WriteLine (dynamicField);
- }
-}";
-
- return VerifyRequiresUnreferencedCodeAnalyzer (source);
- }
-
- [Fact]
- public Task TestMakeGenericMethodUsage ()
- {
- var source = @"
-using System.Diagnostics.CodeAnalysis;
-using System.Reflection;
-
-class C
-{
- static void M1 (MethodInfo methodInfo)
- {
- methodInfo.MakeGenericMethod (typeof (C));
- }
-
- [RequiresUnreferencedCode (""Message from RUC"")]
- static void M2 (MethodInfo methodInfo)
- {
- methodInfo.MakeGenericMethod (typeof (C));
- }
-}";
-
- return VerifyRequiresUnreferencedCodeAnalyzer (source);
- }
-
- [Fact]
- public Task TestMakeGenericTypeUsage ()
- {
- var source = @"
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-class C
-{
- static void M1 (Type t)
- {
- typeof (Nullable<>).MakeGenericType (typeof (C));
- }
-
- [RequiresUnreferencedCode (""Message from RUC"")]
- static void M2 (Type t)
- {
- typeof (Nullable<>).MakeGenericType (typeof (C));
- }
-}";
-
- return VerifyRequiresUnreferencedCodeAnalyzer (source);
- }
-
- [Fact]
- public Task VerifyThatAnalysisOfFieldsDoesNotNullRef ()
- {
- var source = @"
-using System.Diagnostics.CodeAnalysis;
-
-[DynamicallyAccessedMembers (field)]
-class C
-{
- public const DynamicallyAccessedMemberTypes field = DynamicallyAccessedMemberTypes.PublicMethods;
-}";
-
- return VerifyRequiresUnreferencedCodeAnalyzer (source);
- }
- }
-}
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs
index 6d0d97dd3..0904bb4e4 100644
--- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs
@@ -1186,7 +1186,6 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
public string PropertyAnnotationInProperty { get; set; }
[ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = ProducedBy.Analyzer)]
-
public string PropertyAnnotationInPropertyAndAccessor {
[RequiresAssemblyFiles("Message")]
[RequiresUnreferencedCode("Message")]
@@ -1539,6 +1538,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
class DerivedWithRequiresOnType : BaseWithoutRequiresOnType
{
// Bug https://github.com/dotnet/linker/issues/2379
+ //[ExpectedWarning ("IL2046", ProducedBy = ProducedBy.Analyzer)]
public override void Method () { }
}
@@ -1575,6 +1575,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
}
// Bug https://github.com/dotnet/linker/issues/2379
+ //[ExpectedWarning ("IL2046", ProducedBy = ProducedBy.Analyzer)]
public int Method (int a)
{
return a;