diff options
Diffstat (limited to 'test')
53 files changed, 1343 insertions, 1396 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/CompilationExtensions.cs b/test/ILLink.RoslynAnalyzer.Tests/CompilationExtensions.cs index 550a7e8e4..64b3eecbb 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/CompilationExtensions.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/CompilationExtensions.cs @@ -1,14 +1,11 @@ // 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.Collections.Immutable; using System.IO; using System.Linq; -using System.Text; using System.Threading; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; using Xunit; diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/ComTests.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/ComTests.cs new file mode 100644 index 000000000..7545840f0 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/ComTests.cs @@ -0,0 +1,41 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop.InternalCalls +{ + public sealed class ComTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/InternalCalls/Com"; + + [Fact] + public Task DefaultConstructorOfParameterIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task DefaultConstructorOfReturnTypeIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfParameterAreRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfReturnTypeAreRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfThisAreRemoved () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/InternalCallsTests.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/InternalCallsTests.cs new file mode 100644 index 000000000..58e8ed443 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/InternalCallsTests.cs @@ -0,0 +1,47 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop +{ + public sealed class InternalCallsTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/InternalCalls"; + + [Fact] + public Task UnusedDefaultConstructorIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedFieldsOfTypesAreNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedFieldsOfTypesWhenHasThisAreNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task DefaultConstructorOfReturnTypeIsNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedFieldsOfTypesPassedByRefAreNotRemoved () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/ComTests.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/ComTests.cs new file mode 100644 index 000000000..a07563ec9 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/ComTests.cs @@ -0,0 +1,41 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop.PInvoke +{ + public sealed class ComTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/PInvoke/Com"; + + [Fact] + public Task DefaultConstructorOfParameterIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task DefaultConstructorOfReturnTypeIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfParameterAreRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfReturnTypeAreRemoved () + { + return RunTest (); + } + + [Fact] + public Task FieldsOfThisAreRemoved () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/IndividualTests.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/IndividualTests.cs new file mode 100644 index 000000000..04e393753 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/IndividualTests.cs @@ -0,0 +1,17 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop.PInvoke +{ + public class IndividualTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/PInvoke/Individual"; + + [Fact] + public Task CanOutputPInvokes () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/PInvokeTests.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/PInvokeTests.cs new file mode 100644 index 000000000..7ee4ae899 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/PInvokeTests.cs @@ -0,0 +1,48 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop +{ + public sealed class PInvokeTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/PInvoke"; + + + [Fact] + public Task UnusedDefaultConstructorIsRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedFieldsOfTypesPassedByRefAreNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task DefaultConstructorOfReturnTypeIsNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedFieldsOfTypesAreNotRemoved () + { + return RunTest (); + } + + [Fact] + public Task UnusedPInvoke () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/Warnings.cs b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/Warnings.cs new file mode 100644 index 000000000..a3a1a3f1d --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/Warnings.cs @@ -0,0 +1,17 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests.Interop.PInvoke +{ + public sealed class WarningsTests : LinkerTestBase + { + protected override string TestSuiteName => "Interop/PInvoke/Warnings"; + + [Fact] + public Task ComPInvokeWarning () + { + return RunTest (); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestBase.cs b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestBase.cs new file mode 100644 index 000000000..1a382693e --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestBase.cs @@ -0,0 +1,20 @@ + +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace ILLink.RoslynAnalyzer.Tests +{ + public abstract class LinkerTestBase : TestCaseUtils + { + protected abstract string TestSuiteName { get; } + + private static readonly (string, string)[] MSBuildProperties = UseMSBuildProperties ( + MSBuildPropertyOptionNames.EnableTrimAnalyzer, + MSBuildPropertyOptionNames.EnableSingleFileAnalyzer); + + protected Task RunTest ([CallerMemberName] string testName = "") + { + return RunTestFile (TestSuiteName, testName, MSBuildProperties); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs deleted file mode 100644 index 94e734250..000000000 --- a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs +++ /dev/null @@ -1,58 +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.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace ILLink.RoslynAnalyzer.Tests -{ - /// <summary> - /// Test cases stored in files - /// </summary> - public class LinkerTestCases : TestCaseUtils - { - [Theory] - [MemberData (nameof (TestCaseUtils.GetTestData), parameters: nameof (RequiresCapability))] - public void RequiresCapability (string m) - { - RunTest (nameof (RequiresCapability), m, UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer)); - } - - [Theory] - [MemberData (nameof (TestCaseUtils.GetTestData), parameters: nameof (Interop))] - public void Interop (string m) - { - RunTest (nameof (Interop), m, UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer)); - } - - [Theory] - [MemberData (nameof (TestCaseUtils.GetTestData), parameters: nameof (DataFlow))] - public void DataFlow (string m) - { - var shouldRun = (TestCase testCase) => { - var testSyntaxRoot = testCase.MemberSyntax.SyntaxTree.GetRoot (); - var testCaseClass = testSyntaxRoot.DescendantNodes ().OfType<ClassDeclarationSyntax> ().First (); - // Double-check that this is the right class. It should have a Main() method. - var testCaseMain = testCaseClass.DescendantNodes ().OfType<MethodDeclarationSyntax> ().First (); - if (testCaseMain.Identifier.ValueText != "Main") - throw new NotImplementedException (); - - switch (testCaseClass.Identifier.ValueText) { - case "MemberTypesRelationships": - case "MethodParametersDataFlow": - case "MethodReturnParameterDataFlow": - return true; - default: - return false; - } - }; - - RunTest (nameof (DataFlow), m, UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer), shouldRun); - } - } -} diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs index d9f567ba0..a23fd9872 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using ILLink.Shared; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; using Xunit; @@ -78,29 +76,6 @@ class C } [Fact] - public Task SimpleDiagnosticOnMethod () - { - var TestRequiresAssemblyFilesOnMethod = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - [RequiresAssemblyFiles] - void M1() - { - } - - void M2() - { - M1(); - } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnMethod, - // (13,3): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", "", "")); - } - - [Fact] public Task SimpleDiagnosticOnProperty () { var TestRequiresAssemblyFilesOnProperty = @" @@ -160,29 +135,6 @@ class C } [Fact] - public Task RequiresAssemblyFilesWithMessageAndUrl () - { - var TestRequiresAssemblyFilesWithMessageAndUrl = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - [RequiresAssemblyFiles (""Message from attribute"", Url = ""https://helpurl"")] - void M1() - { - } - - void M2() - { - M1(); - } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesWithMessageAndUrl, - // (13,3): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. Message from attribute. https://helpurl - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", " Message from attribute.", " https://helpurl")); - } - - [Fact] public Task RequiresAssemblyFilesWithUrlOnly () { var TestRequiresAssemblyFilesWithMessageAndUrl = @" @@ -395,53 +347,6 @@ class C } [Fact] - public Task LazyDelegateWithRequiresAssemblyFiles () - { - 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; - } -}"; - - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (6,50): warning IL3002: Using member 'C.InitC()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (6, 50, 6, 55).WithArguments ("C.InitC()", "", "")); - } - - [Fact] - public Task ActionDelegateWithRequiresAssemblyFiles () - { - const string src = @" -using System; -using System.Diagnostics.CodeAnalysis; -class C -{ - [RequiresAssemblyFiles] - public static void M1() { } - public static void M2() - { - Action a = M1; - Action b = () => M1(); - } -}"; - - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (10,20): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (10, 20, 10, 22).WithArguments ("C.M1()", "", ""), - // (11,26): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (11, 26, 11, 30).WithArguments ("C.M1()", "", "")); - } - - [Fact] public Task RequiresAssemblyFilesDiagnosticFix () { var test = @" @@ -767,467 +672,5 @@ public class C }, fixedExpected: Array.Empty<DiagnosticResult> ()); } - - [Fact] - public Task TestStaticCctorRequiresAssemblyFiles () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtor -{ - [RequiresAssemblyFiles (""Message for --TestStaticCtor--"")] - static StaticCtor () - { - } - - static void TestStaticCctorRequiresUnreferencedCode () - { - _ = new StaticCtor (); - } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src); - } - - [Fact] - public Task StaticCtorTriggeredByFieldAccess () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtorTriggeredByFieldAccess -{ - public static int field; - - [RequiresAssemblyFiles (""Message for --StaticCtorTriggeredByFieldAccess.Cctor--"")] - static StaticCtorTriggeredByFieldAccess () - { - field = 0; - } -} -class C -{ - static void TestStaticCtorMarkingIsTriggeredByFieldAccess () - { - var x = StaticCtorTriggeredByFieldAccess.field + 1; - } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src); - } - - [Fact] - public Task TestStaticCtorTriggeredByMethodCall () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtorTriggeredByMethodCall -{ - [RequiresAssemblyFiles (""Message for --StaticCtorTriggeredByMethodCall.Cctor--"")] - static StaticCtorTriggeredByMethodCall () - { - } - - [RequiresAssemblyFiles (""Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--"")] - public void TriggerStaticCtorMarking () - { - } -} - -class C -{ - static void TestStaticCtorTriggeredByMethodCall () - { - new StaticCtorTriggeredByMethodCall ().TriggerStaticCtorMarking (); - } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (21,3): warning IL3002: Using member 'StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssemblyFiles).WithSpan (21, 3, 21, 69).WithArguments ("StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking()", " Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--.", "") - ); - } - - [Fact] - public Task OverrideHasAttributeButBaseDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class DerivedClass : BaseClass -{ - [RequiresAssemblyFiles] - public override void VirtualMethod () - { - } - - private string name; - public override string VirtualPropertyWithAnnotationInAccesor - { - [RequiresAssemblyFiles] - get { return name; } - set { name = value; } - } - - [RequiresAssemblyFiles] - public override string VirtualPropertyWithAnnotationInProperty { get; set; } -} - -class BaseClass -{ - public virtual void VirtualMethod () - { - } - - public virtual string VirtualPropertyWithAnnotationInAccesor { get; set; } - - public virtual string VirtualPropertyWithAnnotationInProperty { get; set; } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (7,23): warning IL3003: Member 'DerivedClass.VirtualMethod()' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualMethod()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (7, 23, 7, 36).WithArguments ("Member 'DerivedClass.VirtualMethod()' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualMethod()' without 'RequiresAssemblyFilesAttribute'"), - // (15,3): warning IL3003: Member 'DerivedClass.VirtualPropertyWithAnnotationInAccesor.get' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualPropertyWithAnnotationInAccesor.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (15, 3, 15, 6).WithArguments ("Member 'DerivedClass.VirtualPropertyWithAnnotationInAccesor.get' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualPropertyWithAnnotationInAccesor.get' without 'RequiresAssemblyFilesAttribute'"), - // (20,25): warning IL3003: Member 'DerivedClass.VirtualPropertyWithAnnotationInProperty' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualPropertyWithAnnotationInProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (20, 25, 20, 64).WithArguments ("Member 'DerivedClass.VirtualPropertyWithAnnotationInProperty' with 'RequiresAssemblyFilesAttribute' overrides base member 'BaseClass.VirtualPropertyWithAnnotationInProperty' without 'RequiresAssemblyFilesAttribute'")); - } - - [Fact] - public Task VirtualHasAttributeButOverrideDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class DerivedClass : BaseClass -{ - public override void VirtualMethod () - { - } - - private string name; - public override string VirtualPropertyWithAnnotationInAccesor - { - get { return name; } - set { name = value; } - } - - public override string VirtualPropertyWithAnnotationInProperty { get; set; } -} - -class BaseClass -{ - [RequiresAssemblyFiles] - public virtual void VirtualMethod () - { - } - - public virtual string VirtualPropertyWithAnnotationInAccesor {[RequiresAssemblyFiles] get; set; } - - [RequiresAssemblyFiles] - public virtual string VirtualPropertyWithAnnotationInProperty { get; set; } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (6,23): warning IL3003: Base member 'BaseClass.VirtualMethod()' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualMethod()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (6, 23, 6, 36).WithArguments ("Base member 'BaseClass.VirtualMethod()' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualMethod()' without 'RequiresAssemblyFilesAttribute'"), - // (13,3): warning IL3003: Base member 'BaseClass.VirtualPropertyWithAnnotationInAccesor.get' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualPropertyWithAnnotationInAccesor.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Base member 'BaseClass.VirtualPropertyWithAnnotationInAccesor.get' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualPropertyWithAnnotationInAccesor.get' without 'RequiresAssemblyFilesAttribute'"), - // (17,25): warning IL3003: Base member 'BaseClass.VirtualPropertyWithAnnotationInProperty' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualPropertyWithAnnotationInProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (17, 25, 17, 64).WithArguments ("Base member 'BaseClass.VirtualPropertyWithAnnotationInProperty' with 'RequiresAssemblyFilesAttribute' has a derived member 'DerivedClass.VirtualPropertyWithAnnotationInProperty' without 'RequiresAssemblyFilesAttribute'")); - } - - [Fact] - public Task ImplementationHasAttributeButInterfaceDoesnt () - { - // Once the interface has the attributes indicated in the warnings we would have warnings for AnotherImplementation. - // In the meantime AnotherImplementation doesn't generate a warning - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRAF -{ - [RequiresAssemblyFiles] - public void Method () { } - - private string name; - public string StringProperty - { - [RequiresAssemblyFiles] - get { return name; } - set { name = value; } - } - - private int num; - [RequiresAssemblyFiles] - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -class ExplicitImplementation : IRAF -{ - [RequiresAssemblyFiles] - void IRAF.Method() { } - - private string name; - string IRAF.StringProperty - { - [RequiresAssemblyFiles] - get { return name; } - set { name = value; } - } - - private int num; - [RequiresAssemblyFiles] - int IRAF.NumProperty - { - get { return num; } - set { num = value; } - } -} - -interface IRAF -{ - void Method(); - string StringProperty { get; set; } - int NumProperty { get; set; } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (7,14): warning IL3003: Member 'Implementation.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (7, 14, 7, 20).WithArguments ("Member 'Implementation.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (13,3): warning IL3003: Member 'Implementation.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Member 'Implementation.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (19,13): warning IL3003: Member 'Implementation.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (19, 13, 19, 24).WithArguments ("Member 'Implementation.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'"), - // (48,12): warning IL3003: Member 'ExplicitImplementation.IRAF.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (48, 12, 48, 18).WithArguments ("Member 'ExplicitImplementation.IRAF.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (54,3): warning IL3003: Member 'ExplicitImplementation.IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (54, 3, 54, 6).WithArguments ("Member 'ExplicitImplementation.IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (60,11): warning IL3003: Member 'ExplicitImplementation.IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (60, 11, 60, 22).WithArguments ("Member 'ExplicitImplementation.IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'")); - } - - [Fact] - public Task InterfaceHasAttributeButImplementationDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -interface IRAF -{ - [RequiresAssemblyFiles] - void Method(); - string StringProperty { [RequiresAssemblyFiles] get; set; } - [RequiresAssemblyFiles] - int NumProperty { get; set; } -}"; - return VerifyRequiresAssemblyFilesAnalyzer (src, - // (6,14): warning IL3003: Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (6, 14, 6, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (11,3): warning IL3003: Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (11, 3, 11, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (16,13): warning IL3003: Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (16, 13, 16, 24).WithArguments ("Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.NumProperty' without 'RequiresAssemblyFilesAttribute'"), - // (25,14): warning IL3003: Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (25, 14, 25, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (30,3): warning IL3003: Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (30, 3, 30, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (35,13): warning IL3003: Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (35, 13, 35, 24).WithArguments ("Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.NumProperty' without 'RequiresAssemblyFilesAttribute'")); - } - - [Fact] - public async Task MissingRAFAttributeOnSource () - { - var references = @" -using System.Diagnostics.CodeAnalysis; - -public interface IRAF -{ - [RequiresAssemblyFiles] - void Method(); - string StringProperty { [RequiresAssemblyFiles] get; set; } - [RequiresAssemblyFiles] - int NumProperty { get; set; } -}"; - - var src = @" -class Implementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} -"; - var compilation = (await TestCaseCompilation.GetCompilation (references)).EmitToImageReference (); - - await VerifyRequiresAssemblyFilesAnalyzer (src, additionalReferences: new[] { compilation }, - // (4,14): warning IL3003: Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (4, 14, 4, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (9,3): warning IL3003: Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (9, 3, 9, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (14,13): warning IL3003: Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (14, 13, 14, 24).WithArguments ("Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'Implementation.NumProperty' without 'RequiresAssemblyFilesAttribute'"), - // (23,14): warning IL3003: Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (23, 14, 23, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (28,3): warning IL3003: Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (28, 3, 28, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (33,13): warning IL3003: Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (33, 13, 33, 24).WithArguments ("Interface member 'IRAF.NumProperty' with 'RequiresAssemblyFilesAttribute' has an implementation member 'AnotherImplementation.NumProperty' without 'RequiresAssemblyFilesAttribute'")); - } - - [Fact] - public async Task MissingRAFAttributeOnReference () - { - var references = @" -public interface IRAF -{ - void Method(); - string StringProperty { get; set; } - int NumProperty { get; set; } -}"; - - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRAF -{ - [RequiresAssemblyFiles] - public void Method () { } - - private string name; - public string StringProperty - { - [RequiresAssemblyFiles] - get { return name; } - set { name = value; } - } - - private int num; - [RequiresAssemblyFiles] - public int NumProperty - { - get { return num; } - set { num = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } - - private int num; - public int NumProperty - { - get { return num; } - set { num = value; } - } -} -"; - var compilation = (await TestCaseCompilation.GetCompilation (references)).EmitToImageReference (); - - await VerifyRequiresAssemblyFilesAnalyzer (src, additionalReferences: new[] { compilation }, - // (7,14): warning IL3003: Member 'Implementation.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (7, 14, 7, 20).WithArguments ("Member 'Implementation.Method()' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.Method()' without 'RequiresAssemblyFilesAttribute'"), - // (13,3): warning IL3003: Member 'Implementation.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Member 'Implementation.StringProperty.get' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresAssemblyFilesAttribute'"), - // (19,13): warning IL3003: Member 'Implementation.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresAssembyFilesAttributeMismatch).WithSpan (19, 13, 19, 24).WithArguments ("Member 'Implementation.NumProperty' with 'RequiresAssemblyFilesAttribute' implements interface member 'IRAF.NumProperty' without 'RequiresAssemblyFilesAttribute'")); - } } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs new file mode 100644 index 000000000..6dba8bc95 --- /dev/null +++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs @@ -0,0 +1,41 @@ + +using System.Threading.Tasks; +using Xunit; + +namespace ILLink.RoslynAnalyzer.Tests +{ + public sealed class RequiresCapabilityTests : LinkerTestBase + { + protected override string TestSuiteName => "RequiresCapability"; + + [Fact] + public Task RequiresCapability () + { + return RunTest (nameof (RequiresCapability)); + } + + [Fact] + public Task RequiresCapabilityFromCopiedAssembly () + { + return RunTest (nameof (RequiresCapabilityFromCopiedAssembly)); + } + + [Fact] + public Task RequiresCapabilityReflectionAnalysisEnabled () + { + return RunTest (nameof (RequiresCapabilityReflectionAnalysisEnabled)); + } + + [Fact] + public Task RequiresInCompilerGeneratedCode () + { + return RunTest (nameof (RequiresInCompilerGeneratedCode)); + } + + [Fact] + public Task RequiresOnAttributeCtor () + { + return RunTest (nameof (RequiresOnAttributeCtor)); + } + } +}
\ No newline at end of file diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs index 9cb7d8995..8a834dd0b 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using ILLink.RoslynAnalyzer; using ILLink.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing; @@ -54,22 +53,7 @@ build_property.{MSBuildPropertyOptionNames.EnableTrimAnalyzer} = true"))); return test.RunAsync (); } - [Fact] - public Task SimpleDiagnostic () - { - var TestRequiresWithMessageOnlyOnMethod = @" -using System.Diagnostics.CodeAnalysis; -class C -{ - [RequiresUnreferencedCodeAttribute(""message"")] - int M1() => 0; - int M2() => M1(); -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (TestRequiresWithMessageOnlyOnMethod, - // (8,17): warning IL2026: Using member 'C.M1()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. message. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (8, 17, 8, 21).WithArguments ("C.M1()", " message.", "")); - } [Fact] public async Task SimpleDiagnosticFix () @@ -322,541 +306,6 @@ public class C } [Fact] - public Task TestRequiresWithMessageAndUrlOnMethod () - { - var MessageAndUrlOnMethod = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - static void TestRequiresWithMessageAndUrlOnMethod () - { - RequiresWithMessageAndUrl (); - } - [RequiresUnreferencedCode (""Message for --RequiresWithMessageAndUrl--"", Url = ""https://helpurl"")] - static void RequiresWithMessageAndUrl () - { - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (MessageAndUrlOnMethod, - // (8,3): warning IL2026: Using member 'C.RequiresWithMessageAndUrl()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --RequiresWithMessageAndUrl--. https://helpurl - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (8, 3, 8, 31).WithArguments ("C.RequiresWithMessageAndUrl()", " Message for --RequiresWithMessageAndUrl--.", " https://helpurl") - ); - } - - [Fact] - public Task TestTrailingPeriodsOnWarningMessageAreNotDupplicated () - { - var source = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - [RequiresUnreferencedCode (""Warning message"")] - static void MessageWithoutTrailingPeriod () - { - } - - [RequiresUnreferencedCode (""Warning message."")] - static void MessageWithTrailingPeriod () - { - } - - static void Test () - { - MessageWithoutTrailingPeriod (); - MessageWithTrailingPeriod (); - } -}"; - - return VerifyRequiresUnreferencedCodeAnalyzer (source, - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (18, 3, 18, 34).WithArguments ("C.MessageWithoutTrailingPeriod()", " Warning message.", string.Empty), - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (19, 3, 19, 31).WithArguments ("C.MessageWithTrailingPeriod()", " Warning message.", string.Empty)); - } - - [Fact] - public Task TestRequiresOnPropertyGetter () - { - var PropertyRequires = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - static void TestRequiresOnPropertyGetter () - { - _ = PropertyRequires; - } - - static int PropertyRequires { - [RequiresUnreferencedCode (""Message for --getter PropertyRequires--"")] - get { return 42; } - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires, - // (8,7): warning IL2026: Using member 'C.PropertyRequires.get' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --getter PropertyRequires--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (8, 7, 8, 23).WithArguments ("C.PropertyRequires.get", " Message for --getter PropertyRequires--.", "") - ); - } - - [Fact] - public Task TestRequiresOnPropertySetter () - { - var PropertyRequires = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - static void TestRequiresOnPropertySetter () - { - PropertyRequires = 0; - } - - static int PropertyRequires { - [RequiresUnreferencedCode (""Message for --setter PropertyRequires--"")] - set { } - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires, - // (8,3): warning IL2026: Using member 'C.PropertyRequires.set' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --setter PropertyRequires--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (8, 3, 8, 19).WithArguments ("C.PropertyRequires.set", " Message for --setter PropertyRequires--.", "") - ); - } - - [Fact] - public Task TestStaticCctorRequiresUnreferencedCode () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtor -{ - [RequiresUnreferencedCode (""Message for --TestStaticCtor--"")] - static StaticCtor () - { - } - - static void TestStaticCctorRequiresUnreferencedCode () - { - _ = new StaticCtor (); - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src); - } - - [Fact] - public Task StaticCtorTriggeredByFieldAccess () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtorTriggeredByFieldAccess -{ - public static int field; - - [RequiresUnreferencedCode (""Message for --StaticCtorTriggeredByFieldAccess.Cctor--"")] - static StaticCtorTriggeredByFieldAccess () - { - field = 0; - } -} -class C -{ - static void TestStaticCtorMarkingIsTriggeredByFieldAccess () - { - var x = StaticCtorTriggeredByFieldAccess.field + 1; - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src); - } - - [Fact] - public Task TestStaticCtorTriggeredByMethodCall () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class StaticCtorTriggeredByMethodCall -{ - [RequiresUnreferencedCode (""Message for --StaticCtorTriggeredByMethodCall.Cctor--"")] - static StaticCtorTriggeredByMethodCall () - { - } - - [RequiresUnreferencedCode (""Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--"")] - public void TriggerStaticCtorMarking () - { - } -} - -class C -{ - static void TestStaticCtorTriggeredByMethodCall () - { - new StaticCtorTriggeredByMethodCall ().TriggerStaticCtorMarking (); - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (21,3): warning IL2026: Using member 'StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (21, 3, 21, 69).WithArguments ("StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking()", " Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--.", "") - ); - } - - [Fact] - public Task TypeIsBeforeFieldInit () - { - var TypeIsBeforeFieldInit = @" -using System.Diagnostics.CodeAnalysis; - -class C -{ - class TypeIsBeforeFieldInit - { - public static int field = AnnotatedMethod (); - - [RequiresUnreferencedCode (""Message from --TypeIsBeforeFieldInit.AnnotatedMethod--"")] - public static int AnnotatedMethod () => 42; - } - - static void TestTypeIsBeforeFieldInit () - { - var x = TypeIsBeforeFieldInit.field + 42; - } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (TypeIsBeforeFieldInit, - // (8,29): warning IL2026: Using member 'C.TypeIsBeforeFieldInit.AnnotatedMethod()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Message from --TypeIsBeforeFieldInit.AnnotatedMethod--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (8, 29, 8, 47).WithArguments ("C.TypeIsBeforeFieldInit.AnnotatedMethod()", " Message from --TypeIsBeforeFieldInit.AnnotatedMethod--.", "") - ); - } - - [Fact] - public Task LazyDelegateWithRequiresUnreferencedCode () - { - 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; - - [RequiresUnreferencedCode (""Message from --C.InitC--"")] - public static C InitC() { - C cObject = new C(); - return cObject; - } -}"; - - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (6,50): warning IL2026: Using member 'C.InitC()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Message from --C.InitC--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (6, 50, 6, 55).WithArguments ("C.InitC()", " Message from --C.InitC--.", "")); - } - - [Fact] - public Task ActionDelegateWithRequiresAssemblyFiles () - { - const string src = @" -using System; -using System.Diagnostics.CodeAnalysis; -class C -{ - [RequiresUnreferencedCode (""Message from --C.M1--"")] - public static void M1() { } - public static void M2() - { - Action a = M1; - Action b = () => M1(); - } -}"; - - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (10,20): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Message from --C.M1--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (10, 20, 10, 22).WithArguments ("C.M1()", " Message from --C.M1--.", ""), - // (11,26): warning IL2026: Using member 'C.M1()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Message from --C.M1--. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCode).WithSpan (11, 26, 11, 30).WithArguments ("C.M1()", " Message from --C.M1--.", "")); - } - - [Fact] - public Task OverrideHasAttributeButBaseDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class DerivedClass : BaseClass -{ - [RequiresUnreferencedCode(""Message"")] - public override void VirtualMethod () - { - } - - private string name; - public override string VirtualProperty - { - [RequiresUnreferencedCode(""Message"")] - get { return name; } - set { name = value; } - } -} - -class BaseClass -{ - public virtual void VirtualMethod () - { - } - - public virtual string VirtualProperty { get; set; } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (7,23): warning IL2046: Member 'DerivedClass.VirtualMethod()' with 'RequiresUnreferencedCodeAttribute' overrides base member 'BaseClass.VirtualMethod()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (7, 23, 7, 36).WithArguments ("Member 'DerivedClass.VirtualMethod()' with 'RequiresUnreferencedCodeAttribute' overrides base member 'BaseClass.VirtualMethod()' without 'RequiresUnreferencedCodeAttribute'"), - // (15,3): warning IL2046: Member 'DerivedClass.VirtualProperty.get' with 'RequiresUnreferencedCodeAttribute' overrides base member 'BaseClass.VirtualProperty.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (15, 3, 15, 6).WithArguments ("Member 'DerivedClass.VirtualProperty.get' with 'RequiresUnreferencedCodeAttribute' overrides base member 'BaseClass.VirtualProperty.get' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] - public Task VirtualHasAttributeButOverrideDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class DerivedClass : BaseClass -{ - public override void VirtualMethod () - { - } - - private string name; - public override string VirtualProperty - { - get { return name; } - set { name = value; } - } -} - -class BaseClass -{ - [RequiresUnreferencedCode(""Message"")] - public virtual void VirtualMethod () - { - } - - public virtual string VirtualProperty {[RequiresUnreferencedCode(""Message"")] get; set; } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (13,3): warning IL2046: Base member 'BaseClass.VirtualProperty.get' with 'RequiresUnreferencedCodeAttribute' has a derived member 'DerivedClass.VirtualProperty.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Base member 'BaseClass.VirtualProperty.get' with 'RequiresUnreferencedCodeAttribute' has a derived member 'DerivedClass.VirtualProperty.get' without 'RequiresUnreferencedCodeAttribute'"), - // (6,23): warning IL2046: Base member 'BaseClass.VirtualMethod()' with 'RequiresUnreferencedCodeAttribute' has a derived member 'DerivedClass.VirtualMethod()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (6, 23, 6, 36).WithArguments ("Base member 'BaseClass.VirtualMethod()' with 'RequiresUnreferencedCodeAttribute' has a derived member 'DerivedClass.VirtualMethod()' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] - public Task ImplementationHasAttributeButInterfaceDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRUC -{ - [RequiresUnreferencedCode(""Message"")] - public void RUC () { } - - private string name; - public string Property - { - [RequiresUnreferencedCode(""Message"")] - get { return name; } - set { name = value; } - } -} - -class AnotherImplementation : IRUC -{ - public void RUC () { } - - private string name; - public string Property - { - get { return name; } - set { name = value; } - } -} - -class ExplicitImplementation : IRUC -{ - [RequiresUnreferencedCode(""Message"")] - void IRUC.RUC() { } - - private string name; - string IRUC.Property - { - [RequiresUnreferencedCode(""Message"")] - get { return name; } - set { name = value; } - } -} - -interface IRUC -{ - void RUC(); - string Property { get; set; } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (7,14): warning IL2046: Member 'Implementation.RUC()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.RUC()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (7, 14, 7, 17).WithArguments ("Member 'Implementation.RUC()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.RUC()' without 'RequiresUnreferencedCodeAttribute'"), - // (13,3): warning IL2046: Member 'Implementation.Property.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.Property.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Member 'Implementation.Property.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.Property.get' without 'RequiresUnreferencedCodeAttribute'"), - // (33,12): warning IL2046: Member 'ExplicitImplementation.IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.RUC()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (33, 12, 33, 15).WithArguments ("Member 'ExplicitImplementation.IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.RUC()' without 'RequiresUnreferencedCodeAttribute'"), - // (39,3): warning IL2046: Member 'ExplicitImplementation.IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.Property.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (39, 3, 39, 6).WithArguments ("Member 'ExplicitImplementation.IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRUC.Property.get' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] - public Task InterfaceHasAttributeButImplementationDoesnt () - { - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRUC -{ - public void RUC () { } - - private string name; - public string Property - { - get { return name; } - set { name = value; } - } -} - -class AnotherImplementation : IRUC -{ - public void RUC () { } - - private string name; - public string Property - { - get { return name; } - set { name = value; } - } -} - -interface IRUC -{ - [RequiresUnreferencedCode(""Message"")] - void RUC(); - string Property {[RequiresUnreferencedCode(""Message"")] get; set; } -}"; - return VerifyRequiresUnreferencedCodeAnalyzer (src, - // (6,14): warning IL2046: Interface member 'IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.RUC()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (6, 14, 6, 17).WithArguments ("Interface member 'IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.RUC()' without 'RequiresUnreferencedCodeAttribute'"), - // (11,3): warning IL2046: Interface member 'IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.Property.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (11, 3, 11, 6).WithArguments ("Interface member 'IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.Property.get' without 'RequiresUnreferencedCodeAttribute'"), - // (18,14): warning IL2046: Interface member 'IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.RUC()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (18, 14, 18, 17).WithArguments ("Interface member 'IRUC.RUC()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.RUC()' without 'RequiresUnreferencedCodeAttribute'"), - // (23,3): warning IL2046: Interface member 'IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.Property.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (23, 3, 23, 6).WithArguments ("Interface member 'IRUC.Property.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.Property.get' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] - public async Task MissingRAFAttributeOnSource () - { - var references = @" -using System.Diagnostics.CodeAnalysis; - -public interface IRAF -{ - [RequiresUnreferencedCode (""Message"")] - void Method(); - string StringProperty { [RequiresUnreferencedCode (""Message"")] get; set; } -}"; - - var src = @" -class Implementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } -} -"; - var compilation = (await TestCaseCompilation.GetCompilation (references)).EmitToImageReference (); - - await VerifyRequiresUnreferencedCodeAnalyzer (src, additionalReferences: new[] { compilation }, - // (4,14): warning IL2046: Interface member 'IRAF.Method()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.Method()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (4, 14, 4, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.Method()' without 'RequiresUnreferencedCodeAttribute'"), - // (16,14): warning IL2046: Interface member 'IRAF.Method()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (16, 14, 16, 20).WithArguments ("Interface member 'IRAF.Method()' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.Method()' without 'RequiresUnreferencedCodeAttribute'"), - // (9,3): warning IL2046: Interface member 'IRAF.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (9, 3, 9, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'Implementation.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'"), - // (21,3): warning IL2046: Interface member 'IRAF.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (21, 3, 21, 6).WithArguments ("Interface member 'IRAF.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' has an implementation member 'AnotherImplementation.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] - public async Task MissingRAFAttributeOnReference () - { - var references = @" -public interface IRAF -{ - void Method(); - string StringProperty { get; set; } -}"; - - var src = @" -using System.Diagnostics.CodeAnalysis; - -class Implementation : IRAF -{ - [RequiresUnreferencedCode (""Message"")] - public void Method () { } - - private string name; - public string StringProperty - { - [RequiresUnreferencedCode (""Message"")] - get { return name; } - set { name = value; } - } -} - -class AnotherImplementation : IRAF -{ - public void Method () { } - - private string name; - public string StringProperty - { - get { return name; } - set { name = value; } - } -} -"; - var compilation = (await TestCaseCompilation.GetCompilation (references)).EmitToImageReference (); - - await VerifyRequiresUnreferencedCodeAnalyzer (src, additionalReferences: new[] { compilation }, - // (7,14): warning IL2046: Member 'Implementation.Method()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRAF.Method()' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (7, 14, 7, 20).WithArguments ("Member 'Implementation.Method()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRAF.Method()' without 'RequiresUnreferencedCodeAttribute'"), - // (13,3): warning IL2046: Member 'Implementation.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'. Attributes must match across all interface implementations or overrides. - VerifyCS.Diagnostic (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch).WithSpan (13, 3, 13, 6).WithArguments ("Member 'Implementation.StringProperty.get' with 'RequiresUnreferencedCodeAttribute' implements interface member 'IRAF.StringProperty.get' without 'RequiresUnreferencedCodeAttribute'")); - } - - [Fact] public Task InvocationOnDynamicType () { var source = @" diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCase.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCase.cs index 17bdbd8c6..055da0792 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCase.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCase.cs @@ -1,12 +1,9 @@ // 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.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -28,34 +25,28 @@ namespace ILLink.RoslynAnalyzer.Tests Attributes = attributes; } - public void Run (params (string, string)[] MSBuildProperties) + public void Run ((CompilationWithAnalyzers, SemanticModel) compAndModel) { var testSyntaxTree = MemberSyntax.SyntaxTree; var testDependenciesSource = GetTestDependencies (testSyntaxTree) .Select (testDependency => CSharpSyntaxTree.ParseText (File.ReadAllText (testDependency))); - var test = new TestChecker ( - MemberSyntax, - TestCaseCompilation.CreateCompilation ( - testSyntaxTree, - MSBuildProperties, - additionalSources: testDependenciesSource).Result); - + var test = new TestChecker (MemberSyntax, compAndModel); test.ValidateAttributes (Attributes); } - private static IEnumerable<string> GetTestDependencies (SyntaxTree testSyntaxTree) + public static IEnumerable<string> GetTestDependencies (SyntaxTree testSyntaxTree) { - TestCaseUtils.GetDirectoryPaths (out var rootSourceDir, out _); + LinkerTestBase.GetDirectoryPaths (out var rootSourceDir, out _); foreach (var attribute in testSyntaxTree.GetRoot ().DescendantNodes ().OfType<AttributeSyntax> ()) { if (attribute.Name.ToString () != "SetupCompileBefore") continue; var testNamespace = testSyntaxTree.GetRoot ().DescendantNodes ().OfType<NamespaceDeclarationSyntax> ().Single ().Name.ToString (); var testSuiteName = testNamespace.Substring (testNamespace.LastIndexOf ('.') + 1); - var args = TestCaseUtils.GetAttributeArguments (attribute); + var args = LinkerTestBase.GetAttributeArguments (attribute); foreach (var sourceFile in ((ImplicitArrayCreationExpressionSyntax) args["#1"]).DescendantNodes ().OfType<LiteralExpressionSyntax> ()) - yield return Path.Combine (rootSourceDir, testSuiteName, TestCaseUtils.GetStringFromExpression (sourceFile)); + yield return Path.Combine (rootSourceDir, testSuiteName, LinkerTestBase.GetStringFromExpression (sourceFile)); } } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs index 33c197b9e..f009ccfa5 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Text; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index 4778f3f7a..3835f4f1f 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -12,8 +13,8 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Text; using Xunit; namespace ILLink.RoslynAnalyzer.Tests @@ -30,7 +31,7 @@ namespace ILLink.RoslynAnalyzer.Tests .WithNuGetConfigFilePath (Path.Combine (TestCaseUtils.GetRepoRoot (), "NuGet.config")); private static ImmutableArray<MetadataReference> s_net6Refs; - public async static ValueTask<ImmutableArray<MetadataReference>> GetNet6References () + public static async ValueTask<ImmutableArray<MetadataReference>> GetNet6References () { if (s_net6Refs.IsDefault) { var refs = await Net6PreviewAssemblies.ResolveAsync (null, default); @@ -39,51 +40,33 @@ namespace ILLink.RoslynAnalyzer.Tests return s_net6Refs; } - public static IEnumerable<object[]> GetTestData (string testSuiteName) - => s_testCases[testSuiteName].Keys.Select (testName => new object[] { testName }); - - public static void RunTest (string suiteName, string testName, (string, string)[] MSBuildProperties, Func<TestCase, bool>? shouldRun = null) - { - var testCase = s_testCases[suiteName][testName]; - if (shouldRun == null || shouldRun (testCase)) - testCase.Run (MSBuildProperties); - } - - private static readonly Dictionary<string, Dictionary<string, TestCase>> s_testCases = InitializeTestCases (); - - private static Dictionary<string, Dictionary<string, TestCase>> InitializeTestCases () + public static async Task RunTestFile (string suiteName, string testName, params (string, string)[] msbuildProperties) { - var testCases = new Dictionary<string, Dictionary<string, TestCase>> (); - foreach (var file in GetTestFiles ()) { - // Some tests are in nested directories. Walk up until we get the test suite directory. - string directory = Path.GetDirectoryName (file)!; - string parentDirectory; - while (Path.GetFileName (parentDirectory = Path.GetDirectoryName (directory)!) != MonoLinkerTestsCases) - directory = parentDirectory; - string suiteName = Path.GetFileName (directory); - - if (!testCases.TryGetValue (suiteName, out var suiteTestCases)) { - suiteTestCases = new (); - testCases.Add (suiteName, suiteTestCases); - } - - foreach (var testCase in BuildTestCasesForFile (file)) { - var canditateTestName = GetMemberSyntaxFullName (testCase.MemberSyntax); - string testName = canditateTestName; - int index = 0; - while (!suiteTestCases.TryAdd (testName, testCase)) { - testName = canditateTestName + "#" + (++index).ToString (); - } - - testCase.Name = testName; - } + GetDirectoryPaths (out string rootSourceDir, out string testAssemblyPath); + Debug.Assert (Path.GetFileName (rootSourceDir) == MonoLinkerTestsCases); + var testPath = Path.Combine (rootSourceDir, suiteName, $"{testName}.cs"); + Assert.True (File.Exists (testPath)); + var tree = SyntaxFactory.ParseSyntaxTree ( + SourceText.From (File.OpenRead (testPath), Encoding.UTF8), + path: testPath); + + var testDependenciesSource = TestCase.GetTestDependencies (tree) + .Select (f => SyntaxFactory.ParseSyntaxTree (SourceText.From (File.OpenRead (f)))); + var comp = await TestCaseCompilation.CreateCompilation ( + tree, + msbuildProperties, + additionalSources: testDependenciesSource); + foreach (var testCase in BuildTestCasesForTree (tree)) { + testCase.Run (comp); } - return testCases; } - private static IEnumerable<TestCase> BuildTestCasesForFile (string testFile) + /// <summary> + /// Builds a <see cref="TestCase" /> for each member in the tree. + /// </summary> + private static IEnumerable<TestCase> BuildTestCasesForTree (SyntaxTree tree) { - var root = CSharpSyntaxTree.ParseText (File.ReadAllText (testFile)).GetRoot (); + var root = tree.GetRoot (); foreach (var node in root.DescendantNodes ()) { if (node is MemberDeclarationSyntax m) { var attrs = m.AttributeLists.SelectMany (al => al.Attributes.Where (IsWellKnown)).ToList (); @@ -185,26 +168,6 @@ namespace ILLink.RoslynAnalyzer.Tests return arguments; } - public static IEnumerable<string> GetTestFiles () - { - GetDirectoryPaths (out var rootSourceDir, out _); - foreach (var subDir in Directory.EnumerateDirectories (rootSourceDir, "*", SearchOption.AllDirectories)) { - var subDirName = Path.GetFileName (subDir); - switch (subDirName) { - case "bin": - case "obj": - case "Properties": - case "Dependencies": - case "Individual": - continue; - } - - foreach (var file in Directory.EnumerateFiles (subDir, "*.cs")) { - yield return file; - } - } - } - public static (string, string)[] UseMSBuildProperties (params string[] MSBuildProperties) { return MSBuildProperties.Select (msbp => ($"build_property.{msbp}", "true")).ToArray (); @@ -216,30 +179,5 @@ namespace ILLink.RoslynAnalyzer.Tests string ThisFile ([CallerFilePath] string path = "") => path; } - - public static string GetMemberSyntaxFullName (MemberDeclarationSyntax member) - { - StringBuilder fullName = new (); - var parent = member.Parent; - while (parent is ClassDeclarationSyntax parentClass) { - fullName.Insert (0, "."); - fullName.Insert (0, parentClass.Identifier.ToString ()); - parent = parentClass.Parent; - } - - fullName.Append (GetMemberSyntaxName (member)); - return fullName.ToString (); - } - - public static string GetMemberSyntaxName (MemberDeclarationSyntax member) => - member switch { - MethodDeclarationSyntax method => method.Identifier.ToString (), - PropertyDeclarationSyntax property => property.Identifier.ToString (), - FieldDeclarationSyntax field => field.Declaration.Variables.Single ().Identifier.ToString (), - EventDeclarationSyntax @event => @event.Identifier.ToString (), - ClassDeclarationSyntax @class => @class.Identifier.ToString (), - ConstructorDeclarationSyntax ctor => ctor.Modifiers.Any (t => t.Text == "static") ? ".cctor" : ".ctor", - _ => "UnknownMember" - }; } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs index dc170c311..51964ed0f 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs @@ -63,12 +63,12 @@ namespace ILLink.RoslynAnalyzer.Tests MemberSyntax = memberSyntax; } - bool IsExpectedDiagnostic (AttributeSyntax attribute) + static bool IsExpectedDiagnostic (AttributeSyntax attribute) { switch (attribute.Name.ToString ()) { case "ExpectedWarning": case "LogContains": - var args = TestCaseUtils.GetAttributeArguments (attribute); + var args = LinkerTestBase.GetAttributeArguments (attribute); if (args.TryGetValue ("ProducedBy", out var producedBy)) { // Skip if this warning is not expected to be produced by any of the analyzers that we are currently testing. return GetProducedBy (producedBy).HasFlag (ProducedBy.Analyzer); @@ -154,15 +154,15 @@ namespace ILLink.RoslynAnalyzer.Tests { missingDiagnosticMessage = null; matchIndex = null; - var args = TestCaseUtils.GetAttributeArguments (attribute); - string expectedWarningCode = TestCaseUtils.GetStringFromExpression (args["#0"]); + var args = LinkerTestBase.GetAttributeArguments (attribute); + string expectedWarningCode = LinkerTestBase.GetStringFromExpression (args["#0"]); if (!expectedWarningCode.StartsWith ("IL")) throw new InvalidOperationException ($"Expected warning code should start with \"IL\" prefix."); List<string> expectedMessages = args .Where (arg => arg.Key.StartsWith ("#") && arg.Key != "#0") - .Select (arg => TestCaseUtils.GetStringFromExpression (arg.Value, SemanticModel)) + .Select (arg => LinkerTestBase.GetStringFromExpression (arg.Value, SemanticModel)) .ToList (); for (int i = 0; i < diagnostics.Count; i++) { @@ -172,7 +172,7 @@ namespace ILLink.RoslynAnalyzer.Tests } } - missingDiagnosticMessage = $"Expected to find warning containing:{string.Join (" ", expectedMessages.Select (m => "'" + m + "'"))}" + + missingDiagnosticMessage = $"Warning '{expectedWarningCode}'. Expected to find warning containing:{string.Join (" ", expectedMessages.Select (m => "'" + m + "'"))}" + $", but no such message was found.{ Environment.NewLine}"; return false; @@ -193,8 +193,8 @@ namespace ILLink.RoslynAnalyzer.Tests { missingDiagnosticMessage = null; matchIndex = null; - var args = TestCaseUtils.GetAttributeArguments (attribute); - var text = TestCaseUtils.GetStringFromExpression (args["#0"]); + var args = LinkerTestBase.GetAttributeArguments (attribute); + var text = LinkerTestBase.GetStringFromExpression (args["#0"]); // If the text starts with `warning IL...` then it probably follows the pattern // 'warning <diagId>: <location>:' @@ -218,14 +218,14 @@ namespace ILLink.RoslynAnalyzer.Tests } } - missingDiagnosticMessage = $"Could not find text:\n{text}\nIn diagnostics:\n{(string.Join (Environment.NewLine, DiagnosticMessages))}"; + missingDiagnosticMessage = $"Could not find text:\n{text}\nIn diagnostics:\n{string.Join (Environment.NewLine, DiagnosticMessages)}"; return false; } private void ValidateLogDoesNotContainAttribute (AttributeSyntax attribute, List<Diagnostic> diagnosticMessages) { - var arg = Assert.Single (TestCaseUtils.GetAttributeArguments (attribute)); - var text = TestCaseUtils.GetStringFromExpression (arg.Value); + var arg = Assert.Single (LinkerTestBase.GetAttributeArguments (attribute)); + var text = LinkerTestBase.GetStringFromExpression (arg.Value); foreach (var diagnostic in DiagnosticMessages) Assert.DoesNotContain (text, diagnostic.GetMessage ()); } @@ -234,23 +234,23 @@ namespace ILLink.RoslynAnalyzer.Tests { missingDiagnosticMessage = null; matchIndex = null; - var args = TestCaseUtils.GetAttributeArguments (attribute); + var args = LinkerTestBase.GetAttributeArguments (attribute); MemberDeclarationSyntax sourceMember = attribute.Ancestors ().OfType<MemberDeclarationSyntax> ().First (); if (SemanticModel.GetDeclaredSymbol (sourceMember) is not ISymbol memberSymbol) return false; string sourceMemberName = memberSymbol!.GetDisplayName (); - string expectedReflectionMemberMethodType = TestCaseUtils.GetStringFromExpression ((TypeOfExpressionSyntax) args["#0"], SemanticModel, ISymbolExtensions.ILLinkTypeDisplayFormat); - string expectedReflectionMemberMethodName = TestCaseUtils.GetStringFromExpression (args["#1"], SemanticModel); + string expectedReflectionMemberMethodType = LinkerTestBase.GetStringFromExpression ((TypeOfExpressionSyntax) args["#0"], SemanticModel, ISymbolExtensions.ILLinkTypeDisplayFormat); + string expectedReflectionMemberMethodName = LinkerTestBase.GetStringFromExpression (args["#1"], SemanticModel); var reflectionMethodParameters = new List<string> (); if (args.TryGetValue ("#2", out var reflectionMethodParametersExpr) || args.TryGetValue ("reflectionMethodParameters", out reflectionMethodParametersExpr)) { if (reflectionMethodParametersExpr is ArrayCreationExpressionSyntax arrayReflectionMethodParametersExpr) { foreach (var rmp in arrayReflectionMethodParametersExpr.Initializer!.Expressions) { var parameterStr = rmp.Kind () == SyntaxKind.TypeOfExpression - ? TestCaseUtils.GetStringFromExpression ((TypeOfExpressionSyntax) rmp, SemanticModel, ISymbolExtensions.ILLinkMemberDisplayFormat) - : TestCaseUtils.GetStringFromExpression (rmp, SemanticModel); + ? LinkerTestBase.GetStringFromExpression ((TypeOfExpressionSyntax) rmp, SemanticModel, ISymbolExtensions.ILLinkMemberDisplayFormat) + : LinkerTestBase.GetStringFromExpression (rmp, SemanticModel); reflectionMethodParameters.Add (parameterStr); } } @@ -260,13 +260,13 @@ namespace ILLink.RoslynAnalyzer.Tests if (args.TryGetValue ("#3", out var messageExpr) || args.TryGetValue ("message", out messageExpr)) { if (messageExpr is ArrayCreationExpressionSyntax arrayMessageExpr) { foreach (var m in arrayMessageExpr.Initializer!.Expressions) - expectedStringsInMessage.Add (TestCaseUtils.GetStringFromExpression (m, SemanticModel)); + expectedStringsInMessage.Add (LinkerTestBase.GetStringFromExpression (m, SemanticModel)); } } string expectedWarningCode = string.Empty; if (args.TryGetValue ("#4", out var messageCodeExpr) || args.TryGetValue ("messageCode", out messageCodeExpr)) { - expectedWarningCode = TestCaseUtils.GetStringFromExpression (messageCodeExpr); + expectedWarningCode = LinkerTestBase.GetStringFromExpression (messageCodeExpr); Assert.True (expectedWarningCode.StartsWith ("IL"), $"The warning code specified in {messageCodeExpr.ToString ()} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'"); } diff --git a/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs b/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs index 26a273aff..3e308104f 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs @@ -2,12 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; -using ILLink.CodeFix; using ILLink.Shared; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; using Xunit; diff --git a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs index 6529da26c..473017037 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.IO; using System.Linq; using System.Reflection; using System.Text; @@ -10,7 +9,6 @@ using System.Threading; using System.Threading.Tasks; using ILLink.Shared; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; diff --git a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs index 9fc04e38f..fcef098ea 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using ILLink.Shared; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; diff --git a/test/ILLink.Tasks.Tests/CreateRuntimeRootDescriptorFileTests.cs b/test/ILLink.Tasks.Tests/CreateRuntimeRootDescriptorFileTests.cs index 19d5e6c86..db3bf83f6 100644 --- a/test/ILLink.Tasks.Tests/CreateRuntimeRootDescriptorFileTests.cs +++ b/test/ILLink.Tasks.Tests/CreateRuntimeRootDescriptorFileTests.cs @@ -3,9 +3,7 @@ using System; using System.IO; -using System.Linq; using System.Xml.Linq; -using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Xunit; @@ -47,7 +45,7 @@ namespace ILLink.Tasks.Tests File.WriteAllText ("namespace.h", "#define g_TestNS \"TestNS\"" + Environment.NewLine); - File.WriteAllLines ("cortypeinfo.h", new string[] { }); + File.WriteAllLines ("cortypeinfo.h", Array.Empty<string> ()); File.WriteAllLines ("rexcep.h", new string[] { "DEFINE_EXCEPTION(g_TestNS, TestAlwaysException, false, C)", @@ -62,7 +60,7 @@ namespace ILLink.Tasks.Tests XElement existingAssembly = new XElement ("assembly", new XAttribute ("fullname", "testassembly"), new XComment ("Existing content")); XElement existingContent = new XElement ("linker", existingAssembly); - (new XDocument (existingContent)).Save ("Test.ILLink.Descriptors.Combined.xml"); + new XDocument (existingContent).Save ("Test.ILLink.Descriptors.Combined.xml"); var task = new CreateRuntimeRootILLinkDescriptorFile () { NamespaceFilePath = new TaskItem ("namespace.h"), @@ -142,7 +140,7 @@ namespace ILLink.Tasks.Tests File.WriteAllText ("namespace.h", "#define g_TestNS \"TestNS\"" + Environment.NewLine); - File.WriteAllLines ("cortypeinfo.h", new string[] { }); + File.WriteAllLines ("cortypeinfo.h", Array.Empty<string> ()); File.WriteAllLines ("rexcep.h", new string[] { "DEFINE_EXCEPTION(g_TestNS, TestAlwaysException, false, C)", @@ -157,7 +155,7 @@ namespace ILLink.Tasks.Tests XElement existingAssembly = new XElement ("assembly", new XAttribute ("fullname", "testassembly"), new XComment ("Existing content")); XElement existingContent = new XElement ("linker", existingAssembly); - (new XDocument (existingContent)).Save ("Test.ILLink.Descriptors.Combined.xml"); + new XDocument (existingContent).Save ("Test.ILLink.Descriptors.Combined.xml"); var task = new CreateRuntimeRootILLinkDescriptorFile () { NamespaceFilePath = new TaskItem ("namespace.h"), diff --git a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs b/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs index 216dec205..e6aef3617 100644 --- a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs +++ b/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs @@ -369,7 +369,7 @@ namespace ILLink.Tasks.Tests using (var driver = task.CreateDriver ()) { var actualWarnAsError = driver.Context.WarnAsError; var actualGeneralWarnAsError = driver.Context.GeneralWarnAsError; - Assert.Equal (warnAsError.Count () + warnNotAsError.Count (), actualWarnAsError.Count); + Assert.Equal (warnAsError.Length + warnNotAsError.Length, actualWarnAsError.Count); Assert.Equal (treatWarningsAsErrors, actualGeneralWarnAsError); if (warnAsError.Length > 0) { foreach (var warningCode in warnAsError) @@ -753,7 +753,7 @@ namespace ILLink.Tasks.Tests public void TestErrorHandling () { var task = new MockTask () { - RootAssemblyNames = new ITaskItem[0] + RootAssemblyNames = Array.Empty<ITaskItem> () }; task.BuildEngine = new MockBuildEngine (); Assert.False (task.Execute ()); diff --git a/test/ILLink.Tasks.Tests/Mock.cs b/test/ILLink.Tasks.Tests/Mock.cs index dba28887b..2ea9e492c 100644 --- a/test/ILLink.Tasks.Tests/Mock.cs +++ b/test/ILLink.Tasks.Tests/Mock.cs @@ -21,8 +21,8 @@ namespace ILLink.Tasks.Tests public MockTask () { // Ensure that [Required] members are non-null - AssemblyPaths = new ITaskItem[0]; - RootAssemblyNames = new ITaskItem[0]; + AssemblyPaths = Array.Empty<ITaskItem> (); + RootAssemblyNames = Array.Empty<ITaskItem> (); ILLinkPath = Path.Combine (Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location), "illink.dll"); } diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs index fe054761b..934512ce5 100644 --- a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs +++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs @@ -14,6 +14,10 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions throw new ArgumentException ("Value cannot be null or empty.", nameof (message)); } + /// <summary> + /// Property used by the result checkers of trimmer and analyzers to determine whether + /// the tool should have produced the specified warning on the annotated member. + /// </summary> public ProducedBy ProducedBy { get; set; } = ProducedBy.TrimmerAndAnalyzer; } }
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs index 599908cfb..2cd8667ed 100644 --- a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs +++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs @@ -13,5 +13,11 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions if (string.IsNullOrEmpty (message)) throw new ArgumentException ("Value cannot be null or empty.", nameof (message)); } + + /// <summary> + /// Property used by the result checkers of trimmer and analyzers to determine whether + /// the tool should have produced the specified warning on the annotated member. + /// </summary> + public ProducedBy ProducedBy { get; set; } = ProducedBy.TrimmerAndAnalyzer; } } diff --git a/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.Descriptor.xml b/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.Descriptor.xml new file mode 100644 index 000000000..4fa3f75f9 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.Descriptor.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" ?> +<linker> + <assembly fullname="test" /> +</linker>
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.cs b/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.cs new file mode 100644 index 000000000..c61f1562a --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Mono.Linker.Tests.Cases.LinkAttributes.Dependencies +{ + public static class Used + { + public static void Use () { } + } +} diff --git a/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.LinkAttributes.xml b/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.LinkAttributes.xml new file mode 100644 index 000000000..b28401f8a --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.LinkAttributes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" ?> +<linker> + <assembly fullname="*"> + <type fullname="Mono.Linker.Tests.Cases.LinkAttributes.AttributeToRemoveAttribute"> + <attribute internal="RemoveAttributeInstances"/> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.cs b/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.cs new file mode 100644 index 000000000..1e0e34a17 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.cs @@ -0,0 +1,48 @@ +// 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 Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.LinkAttributes.Dependencies; + +namespace Mono.Linker.Tests.Cases.LinkAttributes +{ + [IgnoreDescriptors (false)] + + // The test verifies that removed attributes which are later on kept due to descriptors correctly warn. + // The setup is: + // - test assembly with the AttributeToRemoveAttribute type + // - link attributes.xml which marks the attribute for removal (applied early, in this case via command line, but could be a embedded in the test assembly) + // - the attribute is used by the test assembly + // - another assembly lib.dll is added and is referenced (after the attribute is used/marked) + // - This new assembly has a descriptor which marks the entire test assembly (note that it marks the TEST assembly) + // - This marking causes the warning, as it's an explicit request to keep the attribute which was supposed to be removed + + [SetupLinkAttributesFile ("LinkerAttributeRemovalAndPreserveAssembly.LinkAttributes.xml")] + + [SetupCompileBefore ( + "lib.dll", + new[] { "Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.cs" })] + // https://github.com/dotnet/linker/issues/2358 - adding the descriptor currently causes nullref in the linker + // resources: new object[] { new string[] { "Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.Descriptor.xml", "ILLink.Descriptors.xml" } })] + + [ExpectedNoWarnings] + + class LinkerAttributeRemovalAndPreserveAssembly + { + public static void Main () + { + TestAttributeRemoval (); + } + + [AttributeToRemoveAttribute] + [Kept] + static void TestAttributeRemoval () + { + Used.Use (); + } + } + + public class AttributeToRemoveAttribute : Attribute { } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs index ba33cdc4e..5f93cf879 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs @@ -17,6 +17,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestNameBindingFlags (); TestNameWrongBindingFlags (); TestNameUnknownBindingFlags (BindingFlags.Public); + TestNameUnknownBindingFlagsAndName (BindingFlags.Public, "DoesntMatter"); TestNullName (); TestEmptyName (); TestNonExistingName (); @@ -72,6 +73,13 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + static void TestNameUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + { + // Since the binding flags are not known linker should mark all events on the type + var eventInfo = typeof (UnknownBindingFlagsAndName).GetEvent (name, bindingFlags); + } + + [Kept] static void TestNullName () { var eventInfo = typeof (EventUsedViaReflection).GetEvent (null); @@ -221,6 +229,30 @@ namespace Mono.Linker.Tests.Cases.Reflection public event EventHandler<EventArgs> PublicEvent; } + class UnknownBindingFlagsAndName + { + [Kept] + [KeptEventAddMethod] + [KeptEventRemoveMethod] + [method: ExpectBodyModified] + internal event EventHandler<EventArgs> InternalEvent; + [Kept] + [KeptBackingField] + [KeptEventAddMethod] + [KeptEventRemoveMethod] + static event EventHandler<EventArgs> Static; + [Kept] + [KeptEventAddMethod] + [KeptEventRemoveMethod] + [method: ExpectBodyModified] + private event EventHandler<EventArgs> PrivateEvent; + [Kept] + [KeptEventAddMethod] + [KeptEventRemoveMethod] + [method: ExpectBodyModified] + public event EventHandler<EventArgs> PublicEvent; + } + class IfClass { [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs index 7d7fc22d3..94535adb1 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs @@ -15,6 +15,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestNameBindingFlags (); TestNameWrongBindingFlags (); TestNameUnknownBindingFlags (BindingFlags.Public); + TestNameUnknownBindingFlagsAndName (BindingFlags.Public, "DoesntMatter"); TestNullName (); TestEmptyName (); TestNonExistingName (); @@ -67,6 +68,13 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + static void TestNameUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + { + // Since the binding flags and name are not known linker should mark all fields on the type + var field = typeof (UnknownBindingFlagsAndName).GetField (name, bindingFlags); + } + + [Kept] static void TestNullName () { var field = typeof (FieldUsedViaReflection).GetField (null); @@ -187,6 +195,17 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + private class UnknownBindingFlagsAndName + { + [Kept] + public static int field; + [Kept] + public int nonStatic; + [Kept] + private static int privatefield; + } + + [Kept] private class IfClass { [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs index 18e70c058..bff3994a2 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs @@ -17,6 +17,7 @@ namespace Mono.Linker.Tests.Cases.Reflection GetMethod_Name_Types.TestNameAndType (); GetMethod_Name_BindingAttr.TestExplicitBindingFlags (); GetMethod_Name_BindingAttr.TestUnknownBindingFlags (BindingFlags.Public); + GetMethod_Name_BindingAttr.TestUnknownBindingFlagsAndName (BindingFlags.Public, "DoesntMatter"); GetMethod_Name_BindingAttr.TestUnknownNullBindingFlags (BindingFlags.Public); GetMethod_Name_BindingAttr_Binder_Types_Modifiers.TestNameBindingFlagsAndParameterModifier (); GetMethod_Name_BindingAttr_Binder_CallConvention_Types_Modifiers.TestNameBindingFlagsCallingConventionParameterModifier (); @@ -37,6 +38,7 @@ namespace Mono.Linker.Tests.Cases.Reflection DerivedAndBase.TestMethodInBaseType (); IgnoreCaseBindingFlags.TestIgnoreCaseBindingFlags (); FailIgnoreCaseBindingFlags.TestFailIgnoreCaseBindingFlags (); + IgnorableBindingFlags.TestIgnorableBindingFlags (); UnsupportedBindingFlags.TestUnsupportedBindingFlags (); } @@ -200,6 +202,25 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + class UnknownBindingFlagsAndName + { + [Kept] + private static int OnlyCalledViaReflection () + { + return 42; + } + } + + [Kept] + [RecognizedReflectionAccessPattern] + public static void TestUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + { + // Since the binding flags and name are not known linker should mark all methods on the type + var method = typeof (UnknownBindingFlagsAndName).GetMethod (name, bindingFlags); + method.Invoke (null, new object[] { }); + } + + [Kept] private class NullBindingFlags { [Kept] @@ -732,6 +753,28 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + class IgnorableBindingFlags + { + [Kept] + public int OnlyCalledViaReflection () + { + return 54; + } + + private bool Unmarked () + { + return true; + } + + [Kept] + public static void TestIgnorableBindingFlags () + { + var method = typeof (IgnorableBindingFlags).GetMethod ("OnlyCalledViaReflection", BindingFlags.Public | BindingFlags.InvokeMethod); + method.Invoke (null, new object[] { }); + } + } + + [Kept] class UnsupportedBindingFlags { [Kept] @@ -741,7 +784,7 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] - private bool MarkedDueToInvokeMethod () + private bool MarkedDueToChangeType () { return true; } @@ -749,7 +792,7 @@ namespace Mono.Linker.Tests.Cases.Reflection [Kept] public static void TestUnsupportedBindingFlags () { - var method = typeof (UnsupportedBindingFlags).GetMethod ("OnlyCalledViaReflection", BindingFlags.InvokeMethod); + var method = typeof (UnsupportedBindingFlags).GetMethod ("OnlyCalledViaReflection", BindingFlags.Public | BindingFlags.SuppressChangeType); method.Invoke (null, new object[] { }); } } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs index 9fdbf389a..5658a1a99 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs @@ -22,6 +22,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestDataFlowWithAnnotation (typeof (MyType)); TestIfElse (1); TestIgnoreCaseBindingFlags (); + TestIgnorableBindingFlags (); TestUnsupportedBindingFlags (); } @@ -100,9 +101,15 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + static void TestIgnorableBindingFlags () + { + var methods = typeof (InvokeMethodClass).GetMethods (BindingFlags.Public | BindingFlags.InvokeMethod); + } + + [Kept] static void TestUnsupportedBindingFlags () { - var methods = typeof (InvokeMethodClass).GetMethods (BindingFlags.InvokeMethod); + var methods = typeof (SuppressChangeTypeClass).GetMethods (BindingFlags.Public | BindingFlags.SuppressChangeType); } [Kept] @@ -287,8 +294,23 @@ namespace Mono.Linker.Tests.Cases.Reflection return 54; } + private bool Unmarked () + { + return true; + } + } + + [Kept] + private class SuppressChangeTypeClass + { + [Kept] + public int OnlyCalledViaReflection () + { + return 54; + } + [Kept] - private bool MarkedDueToInvokeMethod () + private bool MarkedDueToSuppressChangeType () { return true; } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs index cda87ee85..2700a8793 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs @@ -16,6 +16,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestPrivateByName (); TestByBindingFlags (); TestByUnknownBindingFlags (BindingFlags.Public); + TestByUnknownBindingFlagsAndName (BindingFlags.Public, "DoesntMatter"); TestNonExistingName (); TestNullType (); TestIgnoreCaseBindingFlags (); @@ -81,6 +82,16 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + [RecognizedReflectionAccessPattern ( + typeof (Type), nameof (Type.GetNestedType), new Type[] { typeof (string), typeof (BindingFlags) }, + typeof (UnknownBindingFlagsAndName.PublicNestedType), null, (Type[]) null)] + static void TestByUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + { + // Since the binding flags and name are not known linker should mark all nested types on the type + _ = typeof (UnknownBindingFlagsAndName).GetNestedType (name, bindingFlags); + } + + [Kept] static void TestNonExistingName () { _ = typeof (NestedTypeUsedViaReflection).GetNestedType ("NonExisting"); @@ -125,6 +136,16 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + private class UnknownBindingFlagsAndName + { + [Kept] + public static class PublicNestedType { } + + [Kept] + private static class PrivateNestedType { } + } + + [Kept] private class IgnoreCaseClass { [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Reflection/PropertiesUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/PropertiesUsedViaReflection.cs index a7b7dbea8..4f8346b7c 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/PropertiesUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/PropertiesUsedViaReflection.cs @@ -23,6 +23,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestDataFlowWithAnnotation (typeof (MyType)); TestIfElse (1); TestIgnoreCaseBindingFlags (); + TestIgnorableBindingFlags (); TestUnsupportedBindingFlags (); } @@ -107,9 +108,16 @@ namespace Mono.Linker.Tests.Cases.Reflection [Kept] [RecognizedReflectionAccessPattern] + static void TestIgnorableBindingFlags () + { + var properties = typeof (ExactBindingBindingFlagsClass).GetProperties (BindingFlags.Public | BindingFlags.ExactBinding); + } + + [Kept] + [RecognizedReflectionAccessPattern] static void TestUnsupportedBindingFlags () { - var properties = typeof (ExactBindingBindingFlagsClass).GetProperties (BindingFlags.ExactBinding); + var properties = typeof (ChangeTypeBindingFlagsClass).GetProperties (BindingFlags.Public | BindingFlags.SuppressChangeType); } [Kept] @@ -256,8 +264,22 @@ namespace Mono.Linker.Tests.Cases.Reflection set { _field = value; } } + private static int Unmarked { + get { return _field; } + } + } + + [Kept] + class ChangeTypeBindingFlagsClass + { + [Kept] + public static int SetterOnly { + [Kept] + set { _field = value; } + } + [Kept] - private static int MarkedDueToExactBinding { + private static int KeptDueToChangeType { [Kept] get { return _field; } } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs index 3971f9108..4004e894b 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs @@ -17,6 +17,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestGetterOnly (); TestBindingFlags (); TestUnknownBindingFlags (BindingFlags.Public); + TestUnknownBindingFlagsAndName (BindingFlags.Public, "IrrelevantName"); TestNullName (); TestEmptyName (); TestNonExistingName (); @@ -27,6 +28,7 @@ namespace Mono.Linker.Tests.Cases.Reflection TestPropertyInBaseType (); TestIgnoreCaseBindingFlags (); TestFailIgnoreCaseBindingFlags (); + TestIgnorableBindingFlags (); TestUnsupportedBindingFlags (); } @@ -90,6 +92,17 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + [RecognizedReflectionAccessPattern ( + typeof (Type), nameof (Type.GetProperty), new Type[] { typeof (string), typeof (BindingFlags) }, + typeof (UnknownBindingFlagsAndName), nameof (UnknownBindingFlagsAndName.SomeProperty), (Type[]) null)] + static void TestUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + { + // Since the binding flags and name are not known linker should mark all properties on the type + var property = typeof (UnknownBindingFlagsAndName).GetProperty (name, bindingFlags); + property.GetValue (null, new object[] { }); + } + + [Kept] static void TestNullName () { var property = typeof (PropertyUsedViaReflection).GetProperty (null); @@ -194,9 +207,15 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + static void TestIgnorableBindingFlags () + { + var property = typeof (ExactBindingBindingFlagsClass).GetProperty ("SetterOnly", BindingFlags.Public | BindingFlags.ExactBinding); + } + + [Kept] static void TestUnsupportedBindingFlags () { - var property = typeof (ExactBindingBindingFlagsClass).GetProperty ("SetterOnly", BindingFlags.ExactBinding); + var property = typeof (ChangeTypeBindingFlagsClass).GetProperty ("SetterOnly", BindingFlags.Public | BindingFlags.SuppressChangeType); } [Kept] @@ -314,6 +333,18 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + class UnknownBindingFlagsAndName + { + [Kept] + internal static int SomeProperty { + [Kept] + private get { return _field; } + [Kept] + set { _field = value; } + } + } + + [Kept] class IgnoreCaseBindingFlagsClass { [Kept] @@ -346,8 +377,22 @@ namespace Mono.Linker.Tests.Cases.Reflection set { _field = value; } } + public static int Unmarked { + get { return _field; } + } + } + + [Kept] + class ChangeTypeBindingFlagsClass + { + [Kept] + public static int SetterOnly { + [Kept] + set { _field = value; } + } + [Kept] - public static int MarkedDueToExactBinding { + public static int Marked { [Kept] get { return _field; } } diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/ReferenceInterfaces.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/ReferenceInterfaces.cs new file mode 100644 index 000000000..e30fd271c --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/ReferenceInterfaces.cs @@ -0,0 +1,44 @@ +// 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.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies +{ + public class ReferenceInterfaces + { + public interface IBaseWithRequiresInReference + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + public void Method (); + + public string PropertyAnnotationInAccesor { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get; + set; + } + + [RequiresAssemblyFiles ("Message")] + public string PropertyAnnotationInProperty { get; set; } + } + + public interface IBaseWithoutRequiresInReference + { + public void Method (); + + public string PropertyAnnotationInAccesor { + get; + set; + } + + public string PropertyAnnotationInProperty { get; set; } + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/RequiresInCopyAssembly.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/RequiresInCopyAssembly.cs index 74cdff268..c121ff4ef 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/RequiresInCopyAssembly.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/RequiresInCopyAssembly.cs @@ -15,24 +15,29 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies } [RequiresUnreferencedCode ("Message for --Method--")] + [RequiresAssemblyFiles ("Message for --Method--")] public void Method () { } [RequiresUnreferencedCode ("Message for --UncalledMethod--")] + [RequiresAssemblyFiles ("Message for --UncalledMethod--")] public void UncalledMethod () { } [RequiresUnreferencedCode ("Message for --MethodCalledThroughReflection--")] + [RequiresAssemblyFiles ("Message for --MethodCalledThroughReflection--")] static void MethodCalledThroughReflection () { } public int UnusedProperty { [RequiresUnreferencedCode ("Message for --getter UnusedProperty--")] + [RequiresAssemblyFiles ("Message for --getter UnusedProperty--")] get { return 42; } + [RequiresAssemblyFiles ("Message for --setter UnusedProperty--")] [RequiresUnreferencedCode ("Message for --setter UnusedProperty--")] set { } } @@ -40,16 +45,19 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies class UnusedBaseType { [RequiresUnreferencedCode ("Message for --UnusedBaseTypeCctor--")] + [RequiresAssemblyFiles ("Message for --UnusedBaseTypeCctor--")] static UnusedBaseType () { } [RequiresUnreferencedCode ("Message for --UnusedVirtualMethod1--")] + [RequiresAssemblyFiles ("Message for --UnusedVirtualMethod1--")] public virtual void UnusedVirtualMethod1 () { } [RequiresUnreferencedCode ("Message for --UnusedVirtualMethod2--")] + [RequiresAssemblyFiles ("Message for --UnusedVirtualMethod2--")] public virtual void UnusedVirtualMethod2 () { } @@ -58,6 +66,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies class UnusedDerivedType : UnusedBaseType { [RequiresUnreferencedCode ("Message for --UnusedVirtualMethod1--")] + [RequiresAssemblyFiles ("Message for --UnusedVirtualMethod1--")] public override void UnusedVirtualMethod1 () { } @@ -71,12 +80,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies interface IUnusedInterface { [RequiresUnreferencedCode ("Message for --IUnusedInterface.UnusedMethod--")] + [RequiresAssemblyFiles ("Message for --IUnusedInterface.UnusedMethod--")] public void UnusedMethod (); } class UnusedImplementationClass : IUnusedInterface { [RequiresUnreferencedCode ("Message for --UnusedImplementationClass.UnusedMethod--")] + [RequiresAssemblyFiles ("Message for --UnusedImplementationClass.UnusedMethod--")] public void UnusedMethod () { } @@ -85,12 +96,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability.Dependencies public interface IBaseInterface { [RequiresUnreferencedCode ("Message for --IBaseInterface.MethodInBaseInterface--")] + [RequiresAssemblyFiles ("Message for --IBaseInterface.MethodInBaseInterface--")] void MethodInBaseInterface (); } public interface IDerivedInterface : IBaseInterface { [RequiresUnreferencedCode ("Message for --IDerivedInterface.MethodInDerivedInterface--")] + [RequiresAssemblyFiles ("Message for --IDerivedInterface.MethodInDerivedInterface--")] void MethodInDerivedInterface (); } } diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs index f7155e5fe..40814d2e6 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs @@ -19,6 +19,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [SetupLinkerAction ("copy", "lib")] [SetupCompileBefore ("lib.dll", new[] { "Dependencies/RequiresInCopyAssembly.cs" })] [KeptAllTypesAndMembersInAssembly ("lib.dll")] + [SetupLinkerAction ("copy", "lib2")] + [SetupCompileBefore ("lib2.dll", new[] { "Dependencies/ReferenceInterfaces.cs" })] + [KeptAllTypesAndMembersInAssembly ("lib2.dll")] [SetupLinkAttributesFile ("RequiresCapability.attributes.xml")] [SetupLinkerDescriptorFile ("RequiresCapability.descriptor.xml")] [SkipKeptItemsValidation] @@ -82,32 +85,38 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability AccessThroughNewConstraint.TestNewConstraintOnTypeParameter (); AccessThroughNewConstraint.TestNewConstraintOnTypeParameterOfStaticType (); AccessThroughLdToken.Test (); + AttributeMismatch.Test (); RequiresOnClass.Test (); } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageOnly--.")] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", ProducedBy = ProducedBy.Analyzer)] static void TestRequiresWithMessageOnlyOnMethod () { RequiresWithMessageOnly (); } [RequiresUnreferencedCode ("Message for --RequiresWithMessageOnly--")] + [RequiresAssemblyFiles ("Message for --RequiresWithMessageOnly--")] static void RequiresWithMessageOnly () { } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl")] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = ProducedBy.Analyzer)] static void TestRequiresWithMessageAndUrlOnMethod () { RequiresWithMessageAndUrl (); } [RequiresUnreferencedCode ("Message for --RequiresWithMessageAndUrl--", Url = "https://helpurl")] + [RequiresAssemblyFiles ("Message for --RequiresWithMessageAndUrl--", Url = "https://helpurl")] static void RequiresWithMessageAndUrl () { } [ExpectedWarning ("IL2026", "Message for --ConstructorRequires--.")] + [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", ProducedBy = ProducedBy.Analyzer)] static void TestRequiresOnConstructor () { new ConstructorRequires (); @@ -116,6 +125,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class ConstructorRequires { [RequiresUnreferencedCode ("Message for --ConstructorRequires--")] + [RequiresAssemblyFiles ("Message for --ConstructorRequires--")] public ConstructorRequires () { } @@ -123,6 +133,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedWarning ("IL2026", "Message for --getter PropertyRequires--.")] [ExpectedWarning ("IL2026", "Message for --setter PropertyRequires--.")] + [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer)] static void TestRequiresOnPropertyGetterAndSetter () { _ = PropertyRequires; @@ -131,9 +143,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability static int PropertyRequires { [RequiresUnreferencedCode ("Message for --getter PropertyRequires--")] + [RequiresAssemblyFiles ("Message for --getter PropertyRequires--")] get { return 42; } [RequiresUnreferencedCode ("Message for --setter PropertyRequires--")] + [RequiresAssemblyFiles ("Message for --setter PropertyRequires--")] set { } } @@ -144,6 +158,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability static Type GetUnknownType () => null; [RequiresUnreferencedCode ("Message for --MethodWithRequires--")] + [RequiresAssemblyFiles ("Message for --MethodWithRequires--")] static void MethodWithRequires () { } @@ -152,6 +167,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability static Type _requiresPublicConstructors; [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestMethodWithRequires () { // Normally this would warn, but with the attribute on this method it should be auto-suppressed @@ -159,24 +175,28 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestParameter () { _unknownType.RequiresPublicMethods (); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestReturnValue () { GetUnknownType ().RequiresPublicEvents (); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestField () { _requiresPublicConstructors = _unknownType; } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestMethodWithRequires (); @@ -196,36 +216,42 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class GenericTypeRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> { } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestGenericMethod () { GenericMethodRequiresPublicMethods<TUnknown> (); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestGenericMethodMismatch () { GenericMethodRequiresPublicMethods<TPublicProperties> (); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestGenericType () { new GenericTypeRequiresPublicFields<TUnknown> (); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestMakeGenericTypeWithStaticTypes () { typeof (GenericTypeRequiresPublicFields<>).MakeGenericType (typeof (TUnknown)); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestMakeGenericTypeWithDynamicTypes () { typeof (GenericTypeRequiresPublicFields<>).MakeGenericType (_unknownType); } [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static void TestMakeGenericMethod () { typeof (SuppressGenericParameters<TUnknown, TPublicProperties>) @@ -234,6 +260,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestGenericMethod (); @@ -292,6 +319,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class BaseType { [RequiresUnreferencedCode ("Message for --BaseType.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --BaseType.VirtualMethodRequires--")] public virtual void VirtualMethodRequires () { } @@ -300,12 +328,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class TypeWhichOverridesMethod : BaseType { [RequiresUnreferencedCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] public override void VirtualMethodRequires () { } } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestBaseTypeVirtualMethodRequires () { var tmp = new BaseType (); @@ -314,6 +344,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [LogDoesNotContain ("TypeWhichOverridesMethod.VirtualMethodRequires")] [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestTypeWhichOverridesMethodVirtualMethodRequires () { var tmp = new TypeWhichOverridesMethod (); @@ -322,6 +353,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [LogDoesNotContain ("TypeWhichOverridesMethod.VirtualMethodRequires")] [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestTypeWhichOverridesMethodVirtualMethodRequiresOnBase () { BaseType tmp = new TypeWhichOverridesMethod (); @@ -330,19 +362,25 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class PropertyBaseType { - public virtual int VirtualPropertyRequires { [RequiresUnreferencedCode ("Message for --PropertyBaseType.VirtualPropertyRequires--")] get; } + public virtual int VirtualPropertyRequires { + [RequiresUnreferencedCode ("Message for --PropertyBaseType.VirtualPropertyRequires--")] + [RequiresAssemblyFiles ("Message for --PropertyBaseType.VirtualPropertyRequires--")] + get; + } } class TypeWhichOverridesProperty : PropertyBaseType { public override int VirtualPropertyRequires { [RequiresUnreferencedCode ("Message for --TypeWhichOverridesProperty.VirtualPropertyRequires--")] + [RequiresAssemblyFiles ("Message for --TypeWhichOverridesProperty.VirtualPropertyRequires--")] get { return 1; } } } [LogDoesNotContain ("TypeWhichOverridesProperty.VirtualPropertyRequires")] [ExpectedWarning ("IL2026", "--PropertyBaseType.VirtualPropertyRequires--")] + [ExpectedWarning ("IL3002", "--PropertyBaseType.VirtualPropertyRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestTypeWhichOverridesVirtualPropertyRequires () { var tmp = new TypeWhichOverridesProperty (); @@ -382,6 +420,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability struct StaticCCtorForFieldAccess { + // TODO: Analyzer still allows RUC/RAF on static constructor with no warning + // https://github.com/dotnet/linker/issues/2347 [ExpectedWarning ("IL2116", "StaticCCtorForFieldAccess..cctor()", ProducedBy = ProducedBy.Trimmer)] [RequiresUnreferencedCode ("Message for --StaticCCtorForFieldAccess.cctor--")] static StaticCCtorForFieldAccess () { } @@ -397,9 +437,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class TypeIsBeforeFieldInit { [ExpectedWarning ("IL2026", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = ProducedBy.Analyzer)] public static int field = AnnotatedMethod (); [RequiresUnreferencedCode ("Message from --TypeIsBeforeFieldInit.AnnotatedMethod--")] + [RequiresAssemblyFiles ("Message from --TypeIsBeforeFieldInit.AnnotatedMethod--")] public static int AnnotatedMethod () => 42; } @@ -416,19 +458,24 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class StaticCtorTriggeredByMethodCall { + // TODO: Analyzer still allows RUC/RAF on static constructor with no warning + // https://github.com/dotnet/linker/issues/2347 [ExpectedWarning ("IL2116", "StaticCtorTriggeredByMethodCall..cctor()", ProducedBy = ProducedBy.Trimmer)] [RequiresUnreferencedCode ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] + [RequiresAssemblyFiles ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] static StaticCtorTriggeredByMethodCall () { } [RequiresUnreferencedCode ("Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--")] + [RequiresAssemblyFiles ("Message for --StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--")] public void TriggerStaticCtorMarking () { } } [ExpectedWarning ("IL2026", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--")] + [ExpectedWarning ("IL3002", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", ProducedBy = ProducedBy.Analyzer)] static void TestStaticCtorTriggeredByMethodCall () { new StaticCtorTriggeredByMethodCall ().TriggerStaticCtorMarking (); @@ -449,6 +496,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [LogDoesNotContain ("ImplementationClass.MethodWithRequires")] [ExpectedWarning ("IL2026", "--IRequires.MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--IRequires.MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestInterfaceMethodWithRequires () { IRequires inst = new ImplementationClass (); @@ -461,12 +509,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability interface IRequires { [RequiresUnreferencedCode ("Message for --IRequires.MethodWithRequires--")] + [RequiresAssemblyFiles ("Message for --IRequires.MethodWithRequires--")] public void MethodWithRequires (); } class ImplementationClass : IRequires { [RequiresUnreferencedCode ("Message for --ImplementationClass.RequiresMethod--")] + [RequiresAssemblyFiles ("Message for --ImplementationClass.RequiresMethod--")] public void MethodWithRequires () { } @@ -475,12 +525,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability abstract class CovariantReturnBase { [RequiresUnreferencedCode ("Message for --CovariantReturnBase.GetRequires--")] + [RequiresAssemblyFiles ("Message for --CovariantReturnBase.GetRequires--")] public abstract BaseReturnType GetRequires (); } class CovariantReturnDerived : CovariantReturnBase { [RequiresUnreferencedCode ("Message for --CovariantReturnDerived.GetRequires--")] + [RequiresAssemblyFiles ("Message for --CovariantReturnDerived.GetRequires--")] public override DerivedReturnType GetRequires () { return null; @@ -489,6 +541,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [LogDoesNotContain ("--CovariantReturnBase.GetRequires--")] [ExpectedWarning ("IL2026", "--CovariantReturnDerived.GetRequires--")] + [ExpectedWarning ("IL3002", "--CovariantReturnDerived.GetRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestCovariantReturnCallOnDerived () { var tmp = new CovariantReturnDerived (); @@ -496,6 +549,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--Method--")] + [ExpectedWarning ("IL3002", "--Method--", ProducedBy = ProducedBy.Analyzer)] static void TestRequiresInMethodFromCopiedAssembly () { var tmp = new RequiresInCopyAssembly (); @@ -516,11 +570,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Message for --RequiresInDynamicDependency--")] + [RequiresAssemblyFiles ("Message for --RequiresInDynamicDependency--")] static void RequiresInDynamicDependency () { } [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--")] + [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", ProducedBy = ProducedBy.Analyzer)] [DynamicDependency ("RequiresInDynamicDependency")] static void TestRequiresInDynamicDependency () { @@ -528,22 +584,27 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Linker adds a trailing period to this message")] + [RequiresAssemblyFiles ("Linker adds a trailing period to this message")] static void WarningMessageWithoutEndingPeriod () { } [ExpectedWarning ("IL2026", "Linker adds a trailing period to this message.")] + [ExpectedWarning ("IL3002", "Linker adds a trailing period to this message.", ProducedBy = ProducedBy.Analyzer)] static void TestThatTrailingPeriodIsAddedToMessage () { WarningMessageWithoutEndingPeriod (); } [RequiresUnreferencedCode ("Linker does not add a period to this message.")] + [RequiresAssemblyFiles ("Linker does not add a period to this message.")] static void WarningMessageEndsWithPeriod () { } + [LogDoesNotContain ("Linker does not add a period to this message..")] [ExpectedWarning ("IL2026", "Linker does not add a period to this message.")] + [ExpectedWarning ("IL3002", "Linker does not add a period to this message.", ProducedBy = ProducedBy.Analyzer)] static void TestThatTrailingPeriodIsNotDuplicatedInWarningMessage () { WarningMessageEndsWithPeriod (); @@ -570,6 +631,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class AttributeWhichRequiresAttribute : Attribute { [RequiresUnreferencedCode ("Message for --AttributeWhichRequiresAttribute.ctor--")] + [RequiresAssemblyFiles ("Message for --AttributeWhichRequiresAttribute.ctor--")] public AttributeWhichRequiresAttribute () { } @@ -585,17 +647,20 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability get => false; [RequiresUnreferencedCode ("--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] + [RequiresAssemblyFiles ("--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] set { } } } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] class GenericTypeWithAttributedParameter<[AttributeWhichRequires] T> { public static void TestMethod () { } } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] static void GenericMethodWithAttributedParameter<[AttributeWhichRequires] T> () { } static void TestRequiresOnAttributeOnGenericParameter () @@ -605,7 +670,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = ProducedBy.Analyzer)] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] class TypeWithAttributeWhichRequires @@ -613,19 +680,25 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = ProducedBy.Analyzer)] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static void MethodWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = ProducedBy.Analyzer)] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static int _fieldWithAttributeWhichRequires; [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = ProducedBy.Analyzer)] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static bool PropertyWithAttributeWhichRequires { get; set; } @@ -633,9 +706,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] [RequiresUnreferencedCode ("--MethodWhichRequiresWithAttributeWhichRequires--")] + [RequiresAssemblyFiles ("--MethodWhichRequiresWithAttributeWhichRequires--")] static void MethodWhichRequiresWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--MethodWhichRequiresWithAttributeWhichRequires--")] + [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestMethodWhichRequiresWithAttributeWhichRequires () { MethodWhichRequiresWithAttributeWhichRequires (); @@ -662,10 +737,12 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class GenericWithStaticMethod<T> { [RequiresUnreferencedCode ("Message for --GenericTypeWithStaticMethodWhichRequires--")] + [RequiresAssemblyFiles ("Message for --GenericTypeWithStaticMethodWhichRequires--")] public static void GenericTypeWithStaticMethodWhichRequires () { } } [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--")] + [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer)] public static void GenericTypeWithStaticMethodViaLdftn () { var _ = new Action (GenericWithStaticMethod<TestType>.GenericTypeWithStaticMethodWhichRequires); @@ -682,12 +759,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability abstract class Base { [RequiresUnreferencedCode ("Message for --CovariantReturnViaLdftn.Base.GetRequires--")] + [RequiresAssemblyFiles ("Message for --CovariantReturnViaLdftn.Base.GetRequires--")] public abstract BaseReturnType GetRequires (); } class Derived : Base { [RequiresUnreferencedCode ("Message for --CovariantReturnViaLdftn.Derived.GetRequires--")] + [RequiresAssemblyFiles ("Message for --CovariantReturnViaLdftn.Derived.GetRequires--")] public override DerivedReturnType GetRequires () { return null; @@ -695,6 +774,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--CovariantReturnViaLdftn.Derived.GetRequires--")] + [ExpectedWarning ("IL3002", "--CovariantReturnViaLdftn.Derived.GetRequires--", ProducedBy = ProducedBy.Analyzer)] public static void Test () { var tmp = new Derived (); @@ -748,18 +828,22 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability static event EventHandler EventToTestRemove { add { } [RequiresUnreferencedCode ("Message for --EventToTestRemove.remove--")] + [RequiresAssemblyFiles ("Message for --EventToTestRemove.remove--")] remove { } } [ExpectedWarning ("IL2026", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Trimmer)] static event EventHandler EventToTestAdd { [RequiresUnreferencedCode ("Message for --EventToTestAdd.add--")] + [RequiresAssemblyFiles ("Message for --EventToTestAdd.add--")] add { } remove { } } [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--")] + [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2026", "--EventToTestAdd.add--")] + [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Analyzer)] public static void Test () { EventToTestRemove -= (sender, e) => { }; @@ -772,12 +856,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class NewConstraintTestType { [RequiresUnreferencedCode ("Message for --NewConstraintTestType.ctor--")] + [RequiresAssemblyFiles ("Message for --NewConstraintTestType.ctor--")] public NewConstraintTestType () { } } static void GenericMethod<T> () where T : new() { } [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = ProducedBy.Analyzer)] public static void Test () { GenericMethod<NewConstraintTestType> (); @@ -793,12 +879,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = ProducedBy.Analyzer)] public static void TestNewConstraintOnTypeParameter () { _ = new NewConstaintOnTypeParameter<NewConstraintTestType> (); } [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = ProducedBy.Analyzer)] public static void TestNewConstraintOnTypeParameterOfStaticType () { NewConstraintOnTypeParameterOfStaticType<NewConstraintTestType>.DoNothing (); @@ -809,18 +897,283 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability { static bool PropertyWithLdToken { [RequiresUnreferencedCode ("Message for --PropertyWithLdToken.get--")] + [RequiresAssemblyFiles ("Message for --PropertyWithLdToken.get--")] get { return false; } } [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--")] + [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = ProducedBy.Analyzer)] public static void Test () { Expression<Func<bool>> getter = () => PropertyWithLdToken; } } + class AttributeMismatch + { + static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + + class BaseClassWithRequires + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + public virtual void VirtualMethod () + { + } + + public virtual string VirtualPropertyAnnotationInAccesor { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get; + set; + } + + [RequiresAssemblyFiles ("Message")] + public virtual string VirtualPropertyAnnotationInProperty { get; set; } + } + + class BaseClassWithoutRequires + { + public virtual void VirtualMethod () + { + } + + public virtual string VirtualPropertyAnnotationInAccesor { get; set; } + + public virtual string VirtualPropertyAnnotationInProperty { get; set; } + } + + class DerivedClassWithRequires : BaseClassWithoutRequires + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()")] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", ProducedBy = ProducedBy.Analyzer)] + public override void VirtualMethod () + { + } + + private string name; + public override string VirtualPropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get { return name; } + set { name = value; } + } + + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + public override string VirtualPropertyAnnotationInProperty { get; set; } + } + + class DerivedClassWithoutRequires : BaseClassWithRequires + { + [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()")] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = ProducedBy.Analyzer)] + public override void VirtualMethod () + { + } + + private string name; + public override string VirtualPropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + get { return name; } + set { name = value; } + } + + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + public override string VirtualPropertyAnnotationInProperty { get; set; } + } + + public interface IBaseWithRequires + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + void Method (); + + string PropertyAnnotationInAccesor { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get; + set; + } + + [RequiresAssemblyFiles ("Message")] + string PropertyAnnotationInProperty { get; set; } + } + + public interface IBaseWithoutRequires + { + void Method (); + + string PropertyAnnotationInAccesor { get; set; } + + string PropertyAnnotationInProperty { get; set; } + } + + class ImplementationClassWithRequires : IBaseWithoutRequires + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()")] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = ProducedBy.Analyzer)] + public void Method () + { + } + + private string name; + public string PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get { return name; } + set { name = value; } + } + + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + public string PropertyAnnotationInProperty { get; set; } + } + + class ExplicitImplementationClassWithRequires : IBaseWithoutRequires + { + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = ProducedBy.Analyzer)] + void IBaseWithoutRequires.Method () + { + } + + private string name; + string IBaseWithoutRequires.PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get { return name; } + set { name = value; } + } + + [RequiresAssemblyFiles ("Message")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + string IBaseWithoutRequires.PropertyAnnotationInProperty { get; set; } + } + + class ImplementationClassWithoutRequires : IBaseWithRequires + { + [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()")] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", ProducedBy = ProducedBy.Analyzer)] + public void Method () + { + } + + private string name; + public string PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + get { return name; } + set { name = value; } + } + + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + public string PropertyAnnotationInProperty { get; set; } + } + + class ExplicitImplementationClassWithoutRequires : IBaseWithRequires + { + [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithRequires.Method()")] + [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithRequires.Method()", ProducedBy = ProducedBy.Analyzer)] + void IBaseWithRequires.Method () + { + } + + private string name; + string IBaseWithRequires.PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + get { return name; } + set { name = value; } + } + + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresCapability.AttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + string IBaseWithRequires.PropertyAnnotationInProperty { get; set; } + } + + class ImplementationClassWithoutRequiresInSource : ReferenceInterfaces.IBaseWithRequiresInReference + { + [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()")] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", ProducedBy = ProducedBy.Analyzer)] + public void Method () + { + } + + private string name; + public string PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + get { return name; } + set { name = value; } + } + + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty", "IBaseWithRequiresInReference.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + public string PropertyAnnotationInProperty { get; set; } + } + + class ImplementationClassWithRequiresInSource : ReferenceInterfaces.IBaseWithoutRequiresInReference + { + [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()")] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", ProducedBy = ProducedBy.Analyzer)] + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + public void Method () + { + } + + private string name; + public string PropertyAnnotationInAccesor { + [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Analyzer)] + [RequiresUnreferencedCode ("Message")] + [RequiresAssemblyFiles ("Message")] + get { return name; } + set { name = value; } + } + + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = ProducedBy.Analyzer)] + [RequiresAssemblyFiles ("Message")] + public string PropertyAnnotationInProperty { get; set; } + } + + [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "IBaseWithRequires.Method()", ProducedBy = ProducedBy.Trimmer)] + public static void Test () + { + RequirePublicMethods (typeof (BaseClassWithRequires)); + RequirePublicMethods (typeof (BaseClassWithoutRequires)); + RequirePublicMethods (typeof (DerivedClassWithRequires)); + RequirePublicMethods (typeof (DerivedClassWithoutRequires)); + RequirePublicMethods (typeof (IBaseWithRequires)); + RequirePublicMethods (typeof (IBaseWithoutRequires)); + RequirePublicMethods (typeof (ImplementationClassWithRequires)); + RequirePublicMethods (typeof (ImplementationClassWithoutRequires)); + RequirePublicMethods (typeof (ExplicitImplementationClassWithRequires)); + RequirePublicMethods (typeof (ExplicitImplementationClassWithoutRequires)); + RequirePublicMethods (typeof (ImplementationClassWithoutRequiresInSource)); + RequirePublicMethods (typeof (ImplementationClassWithRequiresInSource)); + } + } + class RequiresOnClass { [RequiresUnreferencedCode ("Message for --ClassWithRequires--")] @@ -1572,7 +1925,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability public static int field; // `field` cannot be used as named attribute argument because is static, and if accessed via - // a property the property will be the one generating the warning, but then the warning will + // a property the property will be the one generating the warning, but then the warning will // be suppresed by the Requires on the declaring type public int PropertyOnAttribute { get { return field; } diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapabilityFromCopiedAssembly.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapabilityFromCopiedAssembly.cs index b30833564..6036d7044 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapabilityFromCopiedAssembly.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapabilityFromCopiedAssembly.cs @@ -11,6 +11,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [SetupCompileBefore ("lib.dll", new[] { "Dependencies/RequiresInCopyAssembly.cs" })] [KeptAllTypesAndMembersInAssembly ("lib.dll")] [LogDoesNotContain ("IL2026")] + [LogDoesNotContain ("IL3002")] [LogDoesNotContain ("IL2027")] public class RequiresCapabilityFromCopiedAssembly { diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs index 26777a1a8..0adbae0d6 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs @@ -44,6 +44,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static IEnumerable<int> TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -51,6 +52,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static IEnumerable<int> TestCallAfterYieldReturn () { yield return 0; @@ -68,6 +70,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static IEnumerable<int> TestLdftn () { yield return 0; @@ -75,6 +78,18 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability var action = new Action (MethodWithRequires); } + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static IEnumerable<int> TestLazyDelegate () + { + yield return 0; + yield return 1; + _ = _default.Value; + } + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] static IEnumerable<int> TestDynamicallyAccessedMethod () { @@ -89,6 +104,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallAfterYieldReturn (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); } } @@ -96,6 +112,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class SuppressInIteratorBody { [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestCall () { MethodWithRequires (); @@ -105,6 +122,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestReflectionAccess () { yield return 0; @@ -115,6 +133,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestLdftn () { yield return 0; @@ -122,7 +141,20 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability var action = new Action (MethodWithRequires); } + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static IEnumerable<int> TestLazyDelegate () + { + yield return 0; + yield return 1; + _ = _default.Value; + } + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -131,6 +163,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestMethodParameterWithRequirements (Type unknownType = null) { unknownType.RequiresNonPublicMethods (); @@ -138,6 +171,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestGenericMethodParameterRequirement<TUnknown> () { MethodWithGenericWhichRequiresMethods<TUnknown> (); @@ -145,6 +179,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestGenericTypeParameterRequirement<TUnknown> () { new TypeWithGenericWhichRequiresNonPublicFields<TUnknown> (); @@ -152,11 +187,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestCall (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); TestMethodParameterWithRequirements (); TestGenericMethodParameterRequirement<TestType> (); @@ -167,6 +204,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInAsyncBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async void TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -174,6 +212,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async void TestCallAfterYieldReturn () { await MethodAsync (); @@ -191,12 +230,23 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async void TestLdftn () { await MethodAsync (); var action = new Action (MethodWithRequires); } + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static async void TestLazyDelegate () + { + await MethodAsync (); + _ = _default.Value; + } + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] static async void TestDynamicallyAccessedMethod () { @@ -210,6 +260,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallAfterYieldReturn (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); } } @@ -217,6 +268,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class SuppressInAsyncBody { [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestCall () { MethodWithRequires (); @@ -226,6 +278,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestReflectionAccess () { await MethodAsync (); @@ -236,13 +289,26 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestLdftn () { await MethodAsync (); var action = new Action (MethodWithRequires); } + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static async void TestLazyDelegate () + { + await MethodAsync (); + _ = _default.Value; + } + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -250,6 +316,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestMethodParameterWithRequirements (Type unknownType = null) { unknownType.RequiresNonPublicMethods (); @@ -257,6 +324,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestGenericMethodParameterRequirement<TUnknown> () { MethodWithGenericWhichRequiresMethods<TUnknown> (); @@ -264,6 +332,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestGenericTypeParameterRequirement<TUnknown> () { new TypeWithGenericWhichRequiresNonPublicFields<TUnknown> (); @@ -271,11 +340,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestCall (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); TestMethodParameterWithRequirements (); TestGenericMethodParameterRequirement<TestType> (); @@ -286,6 +357,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInAsyncIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async IAsyncEnumerable<int> TestCallBeforeYieldReturn () { await MethodAsync (); @@ -294,6 +366,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async IAsyncEnumerable<int> TestCallAfterYieldReturn () { yield return 0; @@ -314,6 +387,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async IAsyncEnumerable<int> TestLdftn () { await MethodAsync (); @@ -321,6 +395,17 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability var action = new Action (MethodWithRequires); } + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static async IAsyncEnumerable<int> TestLazyDelegate () + { + await MethodAsync (); + yield return 0; + _ = _default.Value; + } + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] static async IAsyncEnumerable<int> TestDynamicallyAccessedMethod () { @@ -335,6 +420,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallAfterYieldReturn (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); } } @@ -342,6 +428,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class SuppressInAsyncIteratorBody { [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestCall () { MethodWithRequires (); @@ -352,6 +439,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestReflectionAccess () { await MethodAsync (); @@ -364,6 +452,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestLdftn () { await MethodAsync (); @@ -371,7 +460,20 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability yield return 0; } + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static async IAsyncEnumerable<int> TestLazyDelegate () + { + await MethodAsync (); + yield return 0; + _ = _default.Value; + } + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -380,6 +482,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestMethodParameterWithRequirements (Type unknownType = null) { unknownType.RequiresNonPublicMethods (); @@ -388,6 +491,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestGenericMethodParameterRequirement<TUnknown> () { yield return 0; @@ -396,6 +500,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async IAsyncEnumerable<int> TestGenericTypeParameterRequirement<TUnknown> () { new TypeWithGenericWhichRequiresNonPublicFields<TUnknown> (); @@ -404,11 +509,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestCall (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); TestMethodParameterWithRequirements (); TestGenericMethodParameterRequirement<TestType> (); @@ -419,6 +526,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInLocalFunction { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestCall () { LocalFunction (); @@ -427,6 +535,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestCallWithClosure (int p = 0) { LocalFunction (); @@ -449,6 +558,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestLdftn () { LocalFunction (); @@ -459,6 +569,20 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } } + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + LocalFunction (); + + void LocalFunction () + { + _ = _default.Value; + } + } + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] static void TestDynamicallyAccessedMethod () { @@ -473,6 +597,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallWithClosure (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); } } @@ -483,20 +608,24 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability // so its suppression effect also doesn't propagate [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCall () { LocalFunction (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () => MethodWithRequires (); } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCallWithClosure (int p = 0) { LocalFunction (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () { p++; @@ -505,38 +634,59 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestReflectionAccess () { LocalFunction (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () => typeof (RequiresInCompilerGeneratedCode) .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) .Invoke (null, new object[] { }); } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestLdftn () { LocalFunction (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () { var action = new Action (MethodWithRequires); } } + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + LocalFunction (); + + void LocalFunction () + { + _ = _default.Value; + } + } + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestDynamicallyAccessedMethod () { LocalFunction (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestMethodParameterWithRequirements (Type unknownType = null) { LocalFunction (); @@ -546,6 +696,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericMethodParameterRequirement<TUnknown> () { LocalFunction (); @@ -555,6 +706,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericTypeParameterRequirement<TUnknown> () { LocalFunction (); @@ -564,6 +716,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericLocalFunction<TUnknown> () { LocalFunction<TUnknown> (); @@ -575,6 +728,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericLocalFunctionInner<TUnknown> () { LocalFunction<TUnknown> (); @@ -611,22 +765,26 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCallMethodWithRequiresInLtftnLocalFunction () { var _ = new Action (LocalFunction); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () => MethodWithRequires (); } class DynamicallyAccessedLocalFunction { [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction () { typeof (DynamicallyAccessedLocalFunction).RequiresNonPublicMethods (); [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] void LocalFunction () => MethodWithRequires (); } } @@ -640,6 +798,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability LocalFunction (); // This will produce a warning since the location function has Requires on it [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] void LocalFunction (Type unknownType = null) { MethodWithRequires (); @@ -648,11 +807,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestSuppressionOnOuterAndLocalFunction () { LocalFunction (); [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] void LocalFunction (Type unknownType = null) { MethodWithRequires (); @@ -661,12 +822,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestCall (); TestCallWithClosure (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestMethodParameterWithRequirements (); TestDynamicallyAccessedMethod (); TestGenericMethodParameterRequirement<TestType> (); @@ -685,12 +848,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInLambda { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestCall () { Action _ = () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestCallWithClosure (int p = 0) { Action _ = () => { @@ -710,6 +875,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static void TestLdftn () { Action _ = () => { @@ -717,6 +883,17 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability }; } + [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + Action _ = () => { + var action = _default.Value; + }; + } + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] static void TestDynamicallyAccessedMethod () { @@ -731,6 +908,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallWithClosure (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); } } @@ -744,7 +922,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability // - Would be useful for testing - have to use the CompilerGeneratedCode = true trick instead [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCall () { Action _ = () => MethodWithRequires (); @@ -752,6 +932,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedWarning ("IL2067", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCallWithReflectionAnalysisWarning () { // This should not produce warning because the Requires @@ -759,7 +940,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestCallWithClosure (int p = 0) { Action _ = () => { @@ -771,6 +954,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability // Analyzer doesn't recognize reflection access - so doesn't warn in this case [ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestReflectionAccess () { Action _ = () => { @@ -781,7 +965,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestLdftn () { Action _ = () => { @@ -789,9 +975,21 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability }; } + [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy<string> _default = new Lazy<string> (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + Action _ = () => { + var action = _default.Value; + }; + } + // Analyzer doesn't apply DAM - so won't see this warnings [ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestDynamicallyAccessedMethod () { Action _ = () => { @@ -804,6 +1002,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedWarning ("IL2077", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] [ExpectedWarning ("IL2067", ProducedBy = ProducedBy.Analyzer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestMethodParameterWithRequirements (Type unknownType = null) { Action _ = () => unknownType.RequiresNonPublicMethods (); @@ -811,6 +1010,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedWarning ("IL2091", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericMethodParameterRequirement<TUnknown> () { Action _ = () => { @@ -821,6 +1021,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability // The warning is currently not detected by roslyn analyzer since it doesn't analyze DAM yet [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static void TestGenericTypeParameterRequirement<TUnknown> () { Action _ = () => { @@ -829,6 +1030,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestCall (); @@ -836,6 +1038,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability TestCallWithClosure (); TestReflectionAccess (); TestLdftn (); + TestLazyDelegate (); TestDynamicallyAccessedMethod (); TestMethodParameterWithRequirements (); TestGenericMethodParameterRequirement<TestType> (); @@ -846,6 +1049,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class WarnInComplex { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] static async void TestIteratorLocalFunctionInAsync () { await MethodAsync (); @@ -877,6 +1081,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class SuppressInComplex { [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestIteratorLocalFunctionInAsync () { await MethodAsync (); @@ -884,6 +1089,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability await MethodAsync (); [RequiresUnreferencedCode ("Suppress in local function")] + [RequiresAssemblyFiles ("Suppress in local function")] IEnumerable<int> LocalFunction () { yield return 0; @@ -893,6 +1099,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static async void TestIteratorLocalFunctionInAsyncWithoutInner () { await MethodAsync (); @@ -900,6 +1107,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability await MethodAsync (); [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] IEnumerable<int> LocalFunction () { yield return 0; @@ -909,6 +1117,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] static IEnumerable<int> TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator () { MethodWithGenericWhichRequiresMethods<TypeWithMethodWithRequires> (); @@ -916,6 +1125,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] public static void Test () { TestIteratorLocalFunctionInAsync (); @@ -927,6 +1137,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class StateMachinesOnlyReferencedViaReflection { [RequiresUnreferencedCode ("Requires to suppress")] + [RequiresAssemblyFiles ("Requires to suppress")] static IEnumerable<int> TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress () { yield return 0; @@ -934,6 +1145,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("Requires to suppress")] + [RequiresAssemblyFiles ("Requires to suppress")] static async void TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress () { await MethodAsync (); @@ -941,6 +1153,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] static IEnumerable<int> TestIteratorOnlyReferencedViaReflectionWhichShouldWarn () { yield return 0; @@ -948,6 +1161,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () { await MethodAsync (); @@ -969,12 +1183,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability public class AsyncBodyCallingMethodWithRequires { [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static Task<object> MethodWithRequiresAsync (Type type) { return Task.FromResult (new object ()); } [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] static async Task<object> AsyncMethodCallingRequires (Type type) { using (var diposable = await GetDisposableAsync ()) { @@ -983,6 +1199,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer)] public static void Test () { AsyncMethodCallingRequires (typeof (object)); @@ -992,12 +1209,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability public class GenericAsyncBodyCallingMethodWithRequires { [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] static ValueTask<TValue> MethodWithRequiresAsync<TValue> () { return ValueTask.FromResult (default (TValue)); } [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] static async Task<T> AsyncMethodCallingRequires<T> () { using (var disposable = await GetDisposableAsync ()) { @@ -1006,6 +1225,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer)] public static void Test () { AsyncMethodCallingRequires<object> (); @@ -1017,12 +1237,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class RequiresOnCtor { [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] public RequiresOnCtor () { } } [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] static IAsyncEnumerable<TValue> AsyncEnumMethodCallingRequires< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TValue> () { @@ -1038,6 +1260,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer)] public static void Test () { AsyncEnumMethodCallingRequires<object> (); @@ -1055,6 +1278,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability } [RequiresUnreferencedCode ("--MethodWithRequires--")] + [RequiresAssemblyFiles ("--MethodWithRequires--")] static void MethodWithRequires () { } @@ -1062,11 +1286,19 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class TypeWithMethodWithRequires { [RequiresUnreferencedCode ("--TypeWithMethodWithRequires.MethodWithRequires--")] + [RequiresAssemblyFiles ("--TypeWithMethodWithRequires.MethodWithRequires--")] static void MethodWithRequires () { } } + [RequiresUnreferencedCode ("Message from --MethodWithRequiresAndReturns--")] + [RequiresAssemblyFiles ("Message from --MethodWithRequiresAndReturns--")] + public static string MethodWithRequiresAndReturns () + { + return "string"; + } + static void MethodWithGenericWhichRequiresMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] T> () { } diff --git a/test/Mono.Linker.Tests/Extensions/NiceIO.cs b/test/Mono.Linker.Tests/Extensions/NiceIO.cs index 8cbf9c5a5..5fbe8982c 100644 --- a/test/Mono.Linker.Tests/Extensions/NiceIO.cs +++ b/test/Mono.Linker.Tests/Extensions/NiceIO.cs @@ -51,7 +51,7 @@ namespace Mono.Linker.Tests.Extensions if (path == "/") { _isRelative = false; - _elements = new string[] { }; + _elements = Array.Empty<string> (); } else { var split = path.Split ('/', '\\'); @@ -94,7 +94,7 @@ namespace Mono.Linker.Tests.Extensions return stack.Count > 0 && stack[stack.Count - 1] != ".."; } - private string ParseDriveLetter (string path, out string driveLetter) + private static string ParseDriveLetter (string path, out string driveLetter) { if (path.Length >= 2 && path[1] == ':') { driveLetter = path[0].ToString (); @@ -433,7 +433,7 @@ namespace Mono.Linker.Tests.Extensions ThrowIfRelative (); ThrowIfRoot (); EnsureParentDirectoryExists (); - File.WriteAllBytes (ToString (), new byte[0]); + File.WriteAllBytes (ToString (), Array.Empty<byte> ()); return this; } diff --git a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index a6fb77cad..ca7754f8e 100644 --- a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -19,7 +19,7 @@ namespace Mono.Linker.Tests.TestCases [TestFixture] public class IndividualTests { - private NPath TestsDirectory => TestDatabase.TestCasesRootDirectory.Parent.Combine ("Mono.Linker.Tests"); + private static NPath TestsDirectory => TestDatabase.TestCasesRootDirectory.Parent.Combine ("Mono.Linker.Tests"); [Test] public void CanSkipUnresolved () @@ -217,14 +217,14 @@ namespace Mono.Linker.Tests.TestCases Assert.That (secondOutputMvid, Is.EqualTo (firstOutputMvid)); } - protected Guid GetMvid (NPath assemblyPath) + protected static Guid GetMvid (NPath assemblyPath) { using (var assembly = AssemblyDefinition.ReadAssembly (assemblyPath)) { return assembly.MainModule.Mvid; } } - private TestCase CreateIndividualCase (Type testCaseType) + private static TestCase CreateIndividualCase (Type testCaseType) { return TestDatabase.CreateCollector ().CreateIndividualCase (testCaseType); } diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs index 89dd43a08..01f57a3aa 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs @@ -25,7 +25,7 @@ namespace Mono.Linker.Tests.TestCasesRunner { Driver.ProcessResponseFile (args, out var queue); using (var driver = new TestDriver (queue, customizations)) { - driver.Run (logger); + driver.Run (logger, throwOnFatalLinkerException: true); } } } diff --git a/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs b/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs index f4d4b25df..3c9a222be 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs @@ -5,7 +5,6 @@ using System.Linq; using Mono.Cecil; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Extensions; -using NUnit.Framework; namespace Mono.Linker.Tests.TestCasesRunner { diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index 447c7c5a8..8f18a2b7e 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; using System.Text.RegularExpressions; using Mono.Cecil; using Mono.Cecil.Cil; @@ -395,7 +393,7 @@ namespace Mono.Linker.Tests.TestCasesRunner Assert.Fail ($"Invalid test assertion. No member named `{memberName}` exists on the original type `{originalType}`"); } - void VerifyCopyAssemblyIsKeptUnmodified (NPath outputDirectory, string assemblyName) + static void VerifyCopyAssemblyIsKeptUnmodified (NPath outputDirectory, string assemblyName) { string inputAssemblyPath = Path.Combine (Directory.GetParent (outputDirectory).ToString (), "input", assemblyName); string outputAssemblyPath = Path.Combine (outputDirectory, assemblyName); @@ -602,7 +600,7 @@ namespace Mono.Linker.Tests.TestCasesRunner { var assembly = ResolveLinkedAssembly (inAssemblyAttribute.ConstructorArguments[0].Value.ToString ()); var expectedReferenceNames = ((CustomAttributeArgument[]) inAssemblyAttribute.ConstructorArguments[1].Value).Select (attr => (string) attr.Value).ToList (); - for (int i = 0; i < expectedReferenceNames.Count (); i++) + for (int i = 0; i < expectedReferenceNames.Count; i++) if (expectedReferenceNames[i].EndsWith (".dll")) expectedReferenceNames[i] = expectedReferenceNames[i].Substring (0, expectedReferenceNames[i].LastIndexOf (".")); @@ -651,12 +649,13 @@ namespace Mono.Linker.Tests.TestCasesRunner } } - bool IsProducedByLinker (CustomAttribute attr) + static bool IsProducedByLinker (CustomAttribute attr) { var producedBy = attr.GetPropertyValue ("ProducedBy"); return producedBy is null ? true : ((ProducedBy) producedBy).HasFlag (ProducedBy.Trimmer); } - IEnumerable<ICustomAttributeProvider> GetAttributeProviders (AssemblyDefinition assembly) + + static IEnumerable<ICustomAttributeProvider> GetAttributeProviders (AssemblyDefinition assembly) { foreach (var testType in assembly.AllDefinedTypes ()) { foreach (var provider in testType.AllMembers ()) @@ -767,8 +766,7 @@ namespace Mono.Linker.Tests.TestCasesRunner return false; } } else if (isCompilerGeneratedCode == true) { - MethodDefinition methodDefinition = mc.Origin?.Provider as MethodDefinition; - if (methodDefinition != null) { + if (mc.Origin?.Provider is MethodDefinition methodDefinition) { if (attrProvider is not IMemberDefinition expectedMember) return false; @@ -777,6 +775,9 @@ namespace Mono.Linker.Tests.TestCasesRunner if (actualName.StartsWith (expectedMember.DeclaringType.FullName) && actualName.Contains ("<" + expectedMember.Name + ">")) return true; + if (actualName.StartsWith (expectedMember.DeclaringType.FullName) && + actualName.Contains (".cctor") && (expectedMember is FieldDefinition || expectedMember is PropertyDefinition)) + return true; if (methodDefinition.Name == ".ctor" && methodDefinition.DeclaringType.FullName == expectedMember.FullName) return true; @@ -943,7 +944,7 @@ namespace Mono.Linker.Tests.TestCasesRunner $"{expectedSourceMember}: Usage of {expectedReflectionMember} unrecognized " + $"{(expectedMessageParts == null ? string.Empty : "and message contains " + string.Join (" ", expectedMessageParts.Select (p => "'" + p + "'")))}"; - Assert.AreEqual (matchedMessages.Count (), matchedPatterns.Count (), + Assert.AreEqual (matchedMessages.Count, matchedPatterns.Count, $"Inconsistency between logged messages and recorded patterns.{Environment.NewLine}{expectedUnrecognizedPatternMessage}{Environment.NewLine}" + $"Matched messages: {Environment.NewLine}{string.Join (Environment.NewLine, matchedMessages.Select (mc => "\t" + mc.Text))}{Environment.NewLine}" + $"Matched unrecognized patterns: {Environment.NewLine}{string.Join (Environment.NewLine, matchedPatterns.Select (p => "\t" + RecognizedReflectionAccessPatternToString (p)))}{Environment.NewLine}"); @@ -1342,7 +1343,7 @@ namespace Mono.Linker.Tests.TestCasesRunner return attr.AttributeType.Resolve ()?.DerivesFrom (nameof (BaseInAssemblyAttribute)) ?? false; } - bool HasAttribute (ICustomAttributeProvider caProvider, string attributeName) + static bool HasAttribute (ICustomAttributeProvider caProvider, string attributeName) { if (caProvider is AssemblyDefinition assembly && assembly.EntryPoint != null) return assembly.EntryPoint.DeclaringType.CustomAttributes diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs index 5d6c8c35a..2607e356e 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs @@ -36,7 +36,7 @@ namespace Mono.Linker.Tests.TestCasesRunner public NPath CompileTestIn (NPath outputDirectory, string outputName, IEnumerable<string> sourceFiles, string[] commonReferences, string[] mainAssemblyReferences, IEnumerable<string> defines, NPath[] resources, string[] additionalArguments) { var originalCommonReferences = commonReferences.Select (r => r.ToNPath ()).ToArray (); - var originalDefines = defines?.ToArray () ?? new string[0]; + var originalDefines = defines?.ToArray () ?? Array.Empty<string> (); Prepare (outputDirectory); @@ -89,8 +89,8 @@ namespace Mono.Linker.Tests.TestCasesRunner protected virtual CompilerOptions CreateOptionsForSupportingAssembly (SetupCompileInfo setupCompileInfo, NPath outputDirectory, NPath[] sourceFiles, NPath[] references, string[] defines, NPath[] resources) { - var allDefines = defines.Concat (setupCompileInfo.Defines ?? new string[0]).ToArray (); - var allReferences = references.Concat (setupCompileInfo.References?.Select (p => MakeSupportingAssemblyReferencePathAbsolute (outputDirectory, p)) ?? new NPath[0]).ToArray (); + var allDefines = defines.Concat (setupCompileInfo.Defines ?? Array.Empty<string> ()).ToArray (); + var allReferences = references.Concat (setupCompileInfo.References?.Select (p => MakeSupportingAssemblyReferencePathAbsolute (outputDirectory, p)) ?? Array.Empty<NPath> ()).ToArray (); string[] additionalArguments = string.IsNullOrEmpty (setupCompileInfo.AdditionalArguments) ? null : new[] { setupCompileInfo.AdditionalArguments }; return new CompilerOptions { OutputPath = outputDirectory.Combine (setupCompileInfo.OutputName), diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs index 404ecbf0f..fdcde52f7 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs @@ -69,7 +69,7 @@ namespace Mono.Linker.Tests.TestCasesRunner if (pos != -1) { string custom_assembly_path = values[0].Substring (pos + 1); if (!Path.IsPathRooted (custom_assembly_path)) - values[0] = values[0].Substring (0, pos + 1) + Path.Combine (inputPath, custom_assembly_path); + values[0] = string.Concat (values[0].AsSpan (0, pos + 1), Path.Combine (inputPath, custom_assembly_path)); } break; case "-a": diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestReflectionPatternRecorder.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestReflectionPatternRecorder.cs index d4b70f1f7..7143952ed 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/TestReflectionPatternRecorder.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/TestReflectionPatternRecorder.cs @@ -6,7 +6,7 @@ namespace Mono.Linker.Tests.TestCasesRunner { public class TestReflectionPatternRecorder : IReflectionPatternRecorder { - public IReflectionPatternRecorder PreviousRecorder = null; + public IReflectionPatternRecorder PreviousRecorder; public struct ReflectionAccessPattern { diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs index f6ce178d0..e9ead9713 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs @@ -145,7 +145,7 @@ namespace Mono.Linker.Tests.TestCasesRunner return customizations; } - private T GetResultOfTaskThatMakesNUnitAssertions<T> (Task<T> task) + private static T GetResultOfTaskThatMakesNUnitAssertions<T> (Task<T> task) { try { return task.Result; diff --git a/test/Mono.Linker.Tests/Tests/CecilVersionCheck.cs b/test/Mono.Linker.Tests/Tests/CecilVersionCheck.cs index 78fbbbb81..ca7e43d84 100644 --- a/test/Mono.Linker.Tests/Tests/CecilVersionCheck.cs +++ b/test/Mono.Linker.Tests/Tests/CecilVersionCheck.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Reflection; using NUnit.Framework; diff --git a/test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs b/test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs index 4ea98ba18..19864eb37 100644 --- a/test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs +++ b/test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Mono.Cecil; -using Mono.Linker; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.TestCasesRunner; using NUnit.Framework; @@ -103,32 +102,32 @@ namespace Mono.Linker.Tests [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[])")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[])")] - public void M (int[] a) + public static void M (int[] a) { } [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32,System.Int32,System.Int32)~System.Int32")] - public int M (int a, int b, int c) + public static int M (int a, int b, int c) { return 0; } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MRef(System.Int32@)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MRef(System.Int32@)")] - public void MRef (ref int a) + public static void MRef (ref int a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MOut(System.Int32@)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MOut(System.Int32@)")] - public void MOut (out int a) + public static void MOut (out int a) { a = 5; } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MIn(System.Int32@)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MIn(System.Int32@)")] - public void MIn (in int a) + public static void MIn (in int a) { } @@ -137,7 +136,7 @@ namespace Mono.Linker.Tests [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MRefReturn")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MRefReturn")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MRefReturn~System.Int32@")] - public ref int MRefReturn () + public static ref int MRefReturn () { return ref i; } @@ -145,63 +144,63 @@ namespace Mono.Linker.Tests [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M")] [ExpectResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M")] // binds to both. [ExpectResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M()")] // binds to both. - public void M () + public static void M () { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M()")] [ExpectResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M")] [ExpectResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M()")] - public void M (__arglist) + public static void M (__arglist) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[][])")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[][])")] - public void M (int[][] a) + public static void M (int[][] a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[][0:,0:,0:])")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[][0:,0:,0:])")] - public void M (int[,,][] a) + public static void M (int[,,][] a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[0:,0:])")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32[0:,0:])")] - public void M (int[,] a) + public static void M (int[,] a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Object)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Object)")] - public void M (dynamic d) + public static void M (dynamic d) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32*)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32*)")] - public unsafe void M (int* a) + public static unsafe void M (int* a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M``1(Mono.Linker.Tests.DocumentationSignatureParserTests.S{Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,``0}}**[0:,0:,0:][][][0:,0:]@)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M``1(Mono.Linker.Tests.DocumentationSignatureParserTests.S{Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,``0}}**[0:,0:,0:][][][0:,0:]@)")] - public unsafe void M<T> (ref S<G<A, T>>**[,][][][,,] a) + public static unsafe void M<T> (ref S<G<A, T>>**[,][][][,,] a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Collections.Generic.List{System.Int32[]})")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Collections.Generic.List{System.Int32[]})")] - public void M (List<int[]> a) + public static void M (List<int[]> a) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32,)")] //[ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.M(System.Int32,)")] // there's no way to reference this, since the parsing logic doesn't like it. - public void M (int abo, __arglist) + public static void M (int abo, __arglist) { } @@ -296,7 +295,7 @@ namespace Mono.Linker.Tests { [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.B.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A{Mono.Linker.Tests.DocumentationSignatureParserTests.B},System.Collections.Generic.List{Mono.Linker.Tests.DocumentationSignatureParserTests.A}})")] [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.B.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A{Mono.Linker.Tests.DocumentationSignatureParserTests.B},System.Collections.Generic.List{Mono.Linker.Tests.DocumentationSignatureParserTests.A}})")] - public void Method (G<A<B>, List<A>> l) + public static void Method (G<A<B>, List<A>> l) { } } @@ -336,44 +335,44 @@ namespace Mono.Linker.Tests [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method")] - public void Method () + public static void Method () { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(System.Int32)")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(System.Int32)")] - public void Method (int i) + public static void Method (int i) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.IntMethod")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.IntMethod")] - public int IntMethod () => 0; + public static int IntMethod () => 0; [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A})")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A})")] - public void Method (G<A, A> g) + public static void Method (G<A, A> g) { } [ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A}.NG{Mono.Linker.Tests.DocumentationSignatureParserTests.A})")] [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.G{Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A}.NG{Mono.Linker.Tests.DocumentationSignatureParserTests.A})")] - public void Method (G<A, A>.NG<A> g) + public static void Method (G<A, A>.NG<A> g) { } public class Invalid { [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoReturnType~")] - public int NoReturnType () => 0; + public static int NoReturnType () => 0; [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoParameters(,)")] - public void NoParameters (int a, int b) + public static void NoParameters (int a, int b) { } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoClosingParen(")] - public void NoClosingParen () { } + public static void NoClosingParen () { } [ExpectUnresolvedDocumentationSignature ("T:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Whitespace ")] [ExpectUnresolvedDocumentationSignature (" T:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Whitespace")] @@ -384,12 +383,12 @@ namespace Mono.Linker.Tests public class Whitespace { [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Whitespace.Method(System.Int32, System.Int32)")] - public void Method (int a, int b) + public static void Method (int a, int b) { } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Whitespace.Method(Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Generic{System.Int32, System.Int32})")] - public void Method (Generic<int, int> g) + public static void Method (Generic<int, int> g) { } } @@ -422,18 +421,18 @@ namespace Mono.Linker.Tests } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.MethodWithGenericInstantiation(Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Generic`1)")] - public void MethodWithGenericInstantiation (Generic<A> g) + public static void MethodWithGenericInstantiation (Generic<A> g) { } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Method(System.Int32[:,:])")] [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Method(System.Int32[0:,)")] - public void Method (int[,] a) + public static void Method (int[,] a) { } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NonGenericMethod(``0)")] - public void NonGenericMethod (int i) + public static void NonGenericMethod (int i) { } @@ -445,7 +444,7 @@ namespace Mono.Linker.Tests } [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.MethodMissingArgumentTypeName(System.)")] - public void MethodMissingArgumentTypeName (int i) + public static void MethodMissingArgumentTypeName (int i) { } @@ -453,7 +452,7 @@ namespace Mono.Linker.Tests public class NoType { [ExpectUnresolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid..Method")] - public void Method () + public static void Method () { } } @@ -466,12 +465,12 @@ namespace Mono.Linker.Tests } [ExpectUnresolvedDocumentationSignature ("T:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoParameterType()")] - public void NoParameterType (int i) + public static void NoParameterType (int i) { } [ExpectUnresolvedDocumentationSignature ("T:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoParameterType(Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Generic{})")] - public void NoGenericParameterType (Generic<A> g) + public static void NoGenericParameterType (Generic<A> g) { } @@ -503,12 +502,12 @@ namespace Mono.Linker.Tests } [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoClosingParenWithParameters(System.Int32")] - public void NoClosingParenWithParameters (int a) + public static void NoClosingParenWithParameters (int a) { } [ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.NoClosingBrace(Mono.Linker.Tests.DocumentationSignatureParserTests.Invalid.Generic{Mono.Linker.Tests.DocumentationSignatureParserTests.A)")] - public void NoClosingBrace (Generic<A> g) + public static void NoClosingBrace (Generic<A> g) { } diff --git a/test/Mono.Linker.Tests/Tests/GetDisplayNameTests.cs b/test/Mono.Linker.Tests/Tests/GetDisplayNameTests.cs index 715adbaed..1d28d6f1a 100644 --- a/test/Mono.Linker.Tests/Tests/GetDisplayNameTests.cs +++ b/test/Mono.Linker.Tests/Tests/GetDisplayNameTests.cs @@ -60,53 +60,53 @@ namespace Mono.Linker.Tests } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.SingleDimensionalArrayTypeParameter(Int32[])")] - public void SingleDimensionalArrayTypeParameter (int[] p) + public static void SingleDimensionalArrayTypeParameter (int[] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.MultiDimensionalArrayTypeParameter(Int32[,])")] - public void MultiDimensionalArrayTypeParameter (int[,] p) + public static void MultiDimensionalArrayTypeParameter (int[,] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.JaggedArrayTypeParameter(Int32[][,])")] - public void JaggedArrayTypeParameter (int[][,] p) + public static void JaggedArrayTypeParameter (int[][,] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.JaggedArrayTypeParameter(Int32[,][])")] - public void JaggedArrayTypeParameter (int[,][] p) + public static void JaggedArrayTypeParameter (int[,][] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.JaggedArrayTypeParameter(Int32[,][,,][,,,])")] - public void JaggedArrayTypeParameter (int[,][,,][,,,] p) + public static void JaggedArrayTypeParameter (int[,][,,][,,,] p) { } // PointerType [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.CommonPointerPointerTypeParameter(Int32*)")] - public unsafe void CommonPointerPointerTypeParameter (int* p) + public static unsafe void CommonPointerPointerTypeParameter (int* p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.PointerToPointerPointerTypeParameter(Int32**)")] - public unsafe void PointerToPointerPointerTypeParameter (int** p) + public static unsafe void PointerToPointerPointerTypeParameter (int** p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.PointerToArrayPointerTypeParameter(Int32*[,,,])")] - public unsafe void PointerToArrayPointerTypeParameter (int*[,,,] p) + public static unsafe void PointerToArrayPointerTypeParameter (int*[,,,] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.PointerToArrayPointerTypeParameter(Int32*[,][,,])")] - public unsafe void PointerToArrayPointerTypeParameter (int*[,][,,] p) + public static unsafe void PointerToArrayPointerTypeParameter (int*[,][,,] p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.A.PointerTypeToUnknownTypeParameter(Void*)")] - public unsafe void PointerTypeToUnknownTypeParameter (void* p) + public static unsafe void PointerTypeToUnknownTypeParameter (void* p) { } } @@ -175,7 +175,7 @@ namespace Mono.Linker.Tests } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithNestedGenericTypeArgumentsNoArgumentsOnLeaf(GetDisplayNameTests.GenericClassOneParameter<Int32>.B)")] - public void MethodWithNestedGenericTypeArgumentsNoArgumentsOnLeaf (GenericClassOneParameter<int>.B p) { } + public static void MethodWithNestedGenericTypeArgumentsNoArgumentsOnLeaf (GenericClassOneParameter<int>.B p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.GenericClassMultipleParameters<T,S>")] public class GenericClassMultipleParameters<T, S> @@ -187,24 +187,24 @@ namespace Mono.Linker.Tests } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArgument(IList<GetDisplayNameTests.GenericClassOneParameter<Byte*[]>>)")] - public void MethodWithGenericTypeArgument (IList<GenericClassOneParameter<byte*[]>> p) + public static void MethodWithGenericTypeArgument (IList<GenericClassOneParameter<byte*[]>> p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArguments(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>)")] - public void MethodWithGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]> p) + public static void MethodWithGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]> p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithNestedGenericTypeArguments" + "(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>.NestedGenericClassMultipleParameters<Char*[],Int32[,][]>)")] - public void MethodWithNestedGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]>.NestedGenericClassMultipleParameters<char*[], int[,][]> p) + public static void MethodWithNestedGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]>.NestedGenericClassMultipleParameters<char*[], int[,][]> p) { } [DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithPartiallyInstantiatedNestedGenericTypeArguments<MethodT,MethodV>" + "(GetDisplayNameTests.GenericClassMultipleParameters<MethodT,String>.NestedGenericClassMultipleParameters<Int32,MethodV>)")] - public void MethodWithPartiallyInstantiatedNestedGenericTypeArguments<MethodT, MethodV> ( + public static void MethodWithPartiallyInstantiatedNestedGenericTypeArguments<MethodT, MethodV> ( GenericClassMultipleParameters<MethodT, string>.NestedGenericClassMultipleParameters<int, MethodV> p) { } @@ -227,7 +227,7 @@ public class GetDisplayNameTestsGlobalScope public class TypeInGlobalScope { [DisplayName ("GetDisplayNameTestsGlobalScope.TypeInGlobalScope.Method()")] - public void Method () + public static void Method () { } } diff --git a/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs b/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs index e97960359..df06c3ff0 100644 --- a/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs +++ b/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs @@ -106,7 +106,7 @@ b""", new string[] { @"a b" }); } - private void TestParseResponseFileLines (string v1, string[] v2) + private static void TestParseResponseFileLines (string v1, string[] v2) { var result = new Queue<string> (); using (var reader = new StringReader (v1)) |