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:
authorTlakaelel Axayakatl Ceja <tlakaelel.ceja@microsoft.com>2021-05-06 00:25:24 +0300
committerGitHub <noreply@github.com>2021-05-06 00:25:24 +0300
commit031093e11a60c54f06348208fdf91b67f49b5f1c (patch)
treea61be95088a673bd2cd4eaca99b4a7f68d7961ee /test/ILLink.RoslynAnalyzer.Tests
parent4afa1051f5e44560368aacb21429e956ce39cc1a (diff)
Add UnconditionalSuppressMessage codefixer (#2002)
Add CodeFix for UnconditionalSuppressMessage Add test for UnconditionalSuppressMessage Change FindContainingMember to FindAttributableParent and add a list of AttributableParentTargets to values that are possible Add a base class to remove code duplication Use net5.0 reference assemblies and define requiresAssemblyFiles manually (reverts #1922)
Diffstat (limited to 'test/ILLink.RoslynAnalyzer.Tests')
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs18
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs18
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs394
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs6
4 files changed, 418 insertions, 18 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs
index 4826cf20f..7c3babedc 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs
@@ -11,6 +11,24 @@ namespace ILLink.RoslynAnalyzer.Tests
{
static Task VerifyRequiresAssemblyFilesAnalyzer (string source, params DiagnosticResult[] expected)
{
+ var attributeDefinition = @"
+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; }
+ }
+}";
+ source = source + attributeDefinition;
return VerifyCS.VerifyAnalyzerAsync (source,
TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableSingleFileAnalyzer),
expected);
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
index 543b2a1b3..1712e6e2c 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
@@ -29,22 +29,10 @@ namespace ILLink.RoslynAnalyzer.Tests
DiagnosticResult[] fixedExpected,
int? numberOfIterations = null)
{
- const string rucDef = @"
-#nullable enable
-namespace System.Diagnostics.CodeAnalysis
-{
- [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
- public sealed class RequiresUnreferencedCodeAttribute : Attribute
- {
- public RequiresUnreferencedCodeAttribute(string message) { Message = message; }
- public string Message { get; }
- public string? Url { get; set; }
- }
-}
-";
var test = new VerifyCS.Test {
- TestCode = source + rucDef,
- FixedCode = fixedSource + rucDef,
+ TestCode = source,
+ FixedCode = fixedSource,
+ ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
};
test.ExpectedDiagnostics.AddRange (baselineExpected);
test.TestState.AnalyzerConfigFiles.Add (
diff --git a/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs b/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs
new file mode 100644
index 000000000..0653274ac
--- /dev/null
+++ b/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs
@@ -0,0 +1,394 @@
+// 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.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using ILLink.CodeFix;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Testing;
+using Microsoft.CodeAnalysis.Text;
+using Xunit;
+using VerifyCSUSMwithRAF = ILLink.RoslynAnalyzer.Tests.CSharpCodeFixVerifier<
+ ILLink.RoslynAnalyzer.RequiresAssemblyFilesAnalyzer,
+ ILLink.CodeFix.UnconditionalSuppressMessageCodeFixProvider>;
+using VerifyCSUSMwithRUC = ILLink.RoslynAnalyzer.Tests.CSharpCodeFixVerifier<
+ ILLink.RoslynAnalyzer.RequiresUnreferencedCodeAnalyzer,
+ ILLink.CodeFix.UnconditionalSuppressMessageCodeFixProvider>;
+
+
+namespace ILLink.RoslynAnalyzer.Tests
+{
+ public class UnconditionalSuppressMessageCodeFixTests
+ {
+ static Task VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ string source,
+ string fixedSource,
+ DiagnosticResult[] baselineExpected,
+ DiagnosticResult[] fixedExpected)
+ {
+ var test = new VerifyCSUSMwithRUC.Test {
+ TestCode = source,
+ FixedCode = fixedSource,
+ ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
+ };
+ test.ExpectedDiagnostics.AddRange (baselineExpected);
+ test.TestState.AnalyzerConfigFiles.Add (
+ ("/.editorconfig", SourceText.From (@$"
+is_global = true
+build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true")));
+ test.FixedState.ExpectedDiagnostics.AddRange (fixedExpected);
+ return test.RunAsync ();
+ }
+
+ static Task VerifyUnconditionalSuppressMessageCodeFixWithRAF (
+ string source,
+ string fixedSource,
+ DiagnosticResult[] baselineExpected,
+ DiagnosticResult[] fixedExpected)
+ {
+ var attributeDefinition = @"
+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; }
+ }
+}";
+ var test = new VerifyCSUSMwithRAF.Test {
+ TestCode = source + attributeDefinition,
+ FixedCode = fixedSource + attributeDefinition,
+ ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
+ };
+ test.ExpectedDiagnostics.AddRange (baselineExpected);
+ test.TestState.AnalyzerConfigFiles.Add (
+ ("/.editorconfig", SourceText.From (@$"
+is_global = true
+build_property.{MSBuildPropertyOptionNames.EnableSingleFileAnalyzer} = true")));
+ test.FixedState.ExpectedDiagnostics.AddRange (fixedExpected);
+ return test.RunAsync ();
+ }
+
+ [Fact]
+ public Task SuppressRequiresUnreferencedCodeFixer ()
+ {
+ var test = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [RequiresUnreferencedCode(""message"")]
+ public int M1() => 0;
+ int M2() => M1();
+}";
+ var fixtest = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [RequiresUnreferencedCode(""message"")]
+ public int M1() => 0;
+ [UnconditionalSuppressMessage(""Trimming"", ""IL2026:Methods annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code"", Justification = ""<Pending>"")]
+ int M2() => M1();
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ test,
+ fixtest,
+ baselineExpected: new[] {
+ // /0/Test0.cs(7,17): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRUC.Diagnostic ().WithSpan (7, 17, 7, 21).WithArguments ("C.M1()", "message", ""),
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public Task SuppressRequiresAssemblyFilesFixer ()
+ {
+ var test = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [RequiresAssemblyFiles(Message = ""message"")]
+ public int M1() => 0;
+ int M2() => M1();
+}";
+ var fixtest = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [RequiresAssemblyFiles(Message = ""message"")]
+ public int M1() => 0;
+ [UnconditionalSuppressMessage(""SingleFile"", ""IL3002:Avoid calling members marked with 'RequiresAssemblyFilesAttribute' when publishing as a single-file"", Justification = ""<Pending>"")]
+ int M2() => M1();
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRAF (
+ test,
+ fixtest,
+ baselineExpected: new[] {
+ // /0/Test0.cs(7,17): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRAF.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (7, 17, 7, 21).WithArguments ("C.M1()", " message.", "")
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public Task FixInSingleFileSpecialCases ()
+ {
+ var test = @"
+using System.Reflection;
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ public static Assembly assembly = Assembly.LoadFrom(""/some/path/not/in/bundle"");
+ public string M1() => assembly.Location;
+ public void M2() {
+ _ = assembly.GetFiles();
+ }
+}
+";
+ var fixtest = @"
+using System.Reflection;
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ public static Assembly assembly = Assembly.LoadFrom(""/some/path/not/in/bundle"");
+
+ [UnconditionalSuppressMessage(""SingleFile"", ""IL3000:Avoid accessing Assembly file path when publishing as a single file"", Justification = ""<Pending>"")]
+ public string M1() => assembly.Location;
+
+ [UnconditionalSuppressMessage(""SingleFile"", ""IL3001:Avoid accessing Assembly file path when publishing as a single file"", Justification = ""<Pending>"")]
+ public void M2() {
+ _ = assembly.GetFiles();
+ }
+}
+";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRAF (
+ test,
+ fixtest,
+ baselineExpected: new[] {
+ // /0/Test0.cs(7,27): warning IL3000: 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCSUSMwithRAF.Diagnostic(RequiresAssemblyFilesAnalyzer.IL3000).WithSpan (7, 27, 7, 44).WithArguments ("System.Reflection.Assembly.Location", "", ""),
+ // /0/Test0.cs(9,13): warning IL3001: 'System.Reflection.Assembly.GetFiles()' will throw for assemblies embedded in a single-file app
+ VerifyCSUSMwithRAF.Diagnostic(RequiresAssemblyFilesAnalyzer.IL3001).WithSpan (9, 13, 9, 32).WithArguments("System.Reflection.Assembly.GetFiles()", "", ""),
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [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;
+
+ [UnconditionalSuppressMessage(""Trimming"", ""IL2026:Methods annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code"", Justification = ""<Pending>"")]
+ int M2 => M1();
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ src,
+ fix,
+ baselineExpected: new[] {
+ // /0/Test0.cs(10,15): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRUC.Diagnostic ().WithSpan(10, 15, 10, 19).WithArguments("C.M1()", "message", "")
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public Task FixInField ()
+ {
+ const string src = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+class C
+{
+ public static Lazy<C> _default = new Lazy<C>(InitC);
+ public static C Default => _default.Value;
+
+ [RequiresAssemblyFiles]
+ public static C InitC() {
+ C cObject = new C();
+ return cObject;
+ }
+}";
+ var fixtest = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+class C
+{
+ [UnconditionalSuppressMessage(""SingleFile"", ""IL3002:Avoid calling members marked with 'RequiresAssemblyFilesAttribute' when publishing as a single-file"", Justification = ""<Pending>"")]
+ public static Lazy<C> _default = new Lazy<C>(InitC);
+ public static C Default => _default.Value;
+
+ [RequiresAssemblyFiles]
+ public static C InitC() {
+ C cObject = new C();
+ return cObject;
+ }
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRAF (
+ src,
+ fixtest,
+ baselineExpected: new[] {
+ // /0/Test0.cs(6,50): warning IL3002: Using member 'C.InitC()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app.
+ VerifyCSUSMwithRAF.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (6, 50, 6, 55).WithArguments ("C.InitC()", "", ""),
+ },
+ 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;
+
+ Action M2()
+ {
+ [global::System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute(""Trimming"", ""IL2026:Methods annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code"", Justification = ""<Pending>"")] void Wrapper () => M1();
+ return Wrapper;
+ }
+}";
+ // Roslyn currently doesn't simplify the attribute name properly, see https://github.com/dotnet/roslyn/issues/52039
+ return VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ src,
+ fix,
+ baselineExpected: new[] {
+ // /0/Test0.cs(12,28): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRUC.Diagnostic ().WithSpan(12, 28, 12, 32).WithArguments("C.M1()", "message", "")
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public Task FixInCtor ()
+ {
+ var src = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+public class C
+{
+ [RequiresUnreferencedCodeAttribute(""message"")]
+ public int M1() => 0;
+
+ public C () => M1();
+}";
+ var fix = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+public class C
+{
+ [RequiresUnreferencedCodeAttribute(""message"")]
+ public int M1() => 0;
+
+ [UnconditionalSuppressMessage(""Trimming"", ""IL2026:Methods annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code"", Justification = ""<Pending>"")]
+ public C () => M1();
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ src,
+ fix,
+ baselineExpected: new[] {
+ // /0/Test0.cs(10,15): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRUC.Diagnostic ().WithSpan(10, 20, 10, 24).WithArguments("C.M1()", "message", "")
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+
+ [Fact]
+ public Task FixInEvent ()
+ {
+ var src = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+public class C
+{
+ [RequiresUnreferencedCodeAttribute(""message"")]
+ public int M1() => 0;
+
+ public event EventHandler E1
+ {
+ add
+ {
+ var a = M1();
+ }
+ remove { }
+ }
+}";
+ var fix = @"
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+public class C
+{
+ [RequiresUnreferencedCodeAttribute(""message"")]
+ public int M1() => 0;
+
+ [UnconditionalSuppressMessage(""Trimming"", ""IL2026:Methods annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code"", Justification = ""<Pending>"")]
+ public event EventHandler E1
+ {
+ add
+ {
+ var a = M1();
+ }
+ remove { }
+ }
+}";
+ return VerifyUnconditionalSuppressMessageCodeFixWithRUC (
+ src,
+ fix,
+ baselineExpected: new[] {
+ // /0/Test0.cs(14,21): warning IL2026: Using method 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. message.
+ VerifyCSUSMwithRUC.Diagnostic ().WithSpan(14, 21, 14, 25).WithArguments("C.M1()", "message", "")
+ },
+ fixedExpected: Array.Empty<DiagnosticResult> ());
+ }
+ }
+}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
index 5eae9acf3..56dae0a44 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
@@ -42,12 +42,12 @@ namespace ILLink.RoslynAnalyzer.Tests
SyntaxTree src,
(string, string)[]? globalAnalyzerOptions = null)
{
+ var mdRef = MetadataReference.CreateFromFile (typeof (Mono.Linker.Tests.Cases.Expectations.Metadata.BaseMetadataAttribute).Assembly.Location);
+
var comp = CSharpCompilation.Create (
assemblyName: Guid.NewGuid ().ToString ("N"),
syntaxTrees: new SyntaxTree[] { src },
- references: await Task.Run (() => new List<MetadataReference> {
- MetadataReference.CreateFromFile (typeof (int).Assembly.Location)
- }),
+ references: (await ReferenceAssemblies.Net.Net50.ResolveAsync (null, default)).Add (mdRef),
new CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary));
var analyzerOptions = new AnalyzerOptions (