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

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Boemer <sbomer@gmail.com>2021-11-16 20:21:59 +0300
committerSven Boemer <sbomer@gmail.com>2021-11-16 20:39:54 +0300
commita556862ea401d080a2b9dab1615f3e8cc8892026 (patch)
tree467a67802e4519e8250c9eb650ee7e19b25c28cb
parent2aed9937115a6bd5a81e37658431272ce4be3317 (diff)
parent53c5d48842fe53e05272d163c7f49e54ddcb4b37 (diff)
Merge remote-tracking branch 'origin/main' into updateFromMain
-rw-r--r--.config/dotnet-tools.json12
-rw-r--r--.editorconfig5
-rw-r--r--.github/CODEOWNERS1
-rw-r--r--.gitignore4
-rw-r--r--docs/design/compiler-generated-code-handling.md628
-rw-r--r--eng/Version.Details.xml12
-rw-r--r--eng/Versions.props4
-rw-r--r--eng/common/msbuild.ps11
-rw-r--r--eng/common/post-build/symbols-validation.ps116
-rw-r--r--eng/common/templates/job/execute-sdl.yml6
-rw-r--r--eng/common/templates/job/onelocbuild.yml5
-rw-r--r--eng/common/templates/job/source-build.yml15
-rw-r--r--eng/common/templates/job/source-index-stage1.yml10
-rw-r--r--eng/common/templates/jobs/jobs.yml4
-rw-r--r--global.json6
-rw-r--r--lint.cmd3
-rwxr-xr-xlint.sh3
-rw-r--r--src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs46
-rw-r--r--src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs6
-rw-r--r--src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs56
-rw-r--r--src/ILLink.Shared/DiagnosticId.cs2
-rw-r--r--src/ILLink.Shared/DiagnosticString.cs3
-rw-r--r--src/ILLink.Shared/SharedStrings.resx6
-rw-r--r--src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs49
-rw-r--r--src/linker/Linker.Steps/BaseSubStep.cs1
-rw-r--r--src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs1
-rw-r--r--src/linker/Linker.Steps/DiscoverSerializationHandler.cs4
-rw-r--r--src/linker/Linker.Steps/MarkStep.cs4
-rw-r--r--src/linker/Linker.Steps/MarkSubStepsDispatcher.cs1
-rw-r--r--src/linker/Linker.Steps/OutputStep.cs1
-rw-r--r--src/linker/Linker.Steps/SubStepsDispatcher.cs1
-rw-r--r--src/linker/Linker/AttributeInfo.cs1
-rw-r--r--src/linker/Linker/Driver.cs4
-rw-r--r--src/linker/Linker/EmbeddedXmlInfo.cs2
-rw-r--r--src/linker/Linker/MemberReferenceExtensions.cs3
-rw-r--r--src/linker/Linker/MethodDefinitionExtensions.cs3
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/CompilationExtensions.cs3
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/ComTests.cs41
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/InternalCalls/InternalCallsTests.cs47
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/ComTests.cs41
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/IndividualTests.cs17
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/PInvokeTests.cs48
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Interop/PInvoke/Warnings.cs17
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/LinkerTestBase.cs20
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs58
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs557
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs41
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs551
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/TestCase.cs21
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs1
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs112
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs36
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/UnconditionalSuppressMessageCodeFixTests.cs4
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs2
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs1
-rw-r--r--test/ILLink.Tasks.Tests/CreateRuntimeRootDescriptorFileTests.cs10
-rw-r--r--test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs4
-rw-r--r--test/ILLink.Tasks.Tests/Mock.cs4
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs4
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.Descriptor.xml4
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkAttributes/Dependencies/LinkerAttributeRemovalAndPreserveAssembly_Lib.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.LinkAttributes.xml8
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemovalAndPreserveAssembly.cs48
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs47
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/PropertiesUsedViaReflection.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs49
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/ReferenceInterfaces.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/Dependencies/RequiresInCopyAssembly.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapability.cs357
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresCapabilityFromCopiedAssembly.cs1
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs232
-rw-r--r--test/Mono.Linker.Tests/Extensions/NiceIO.cs6
-rw-r--r--test/Mono.Linker.Tests/TestCases/IndividualTests.cs6
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs2
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs1
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs21
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs6
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs2
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestReflectionPatternRecorder.cs2
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs2
-rw-r--r--test/Mono.Linker.Tests/Tests/CecilVersionCheck.cs1
-rw-r--r--test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs73
-rw-r--r--test/Mono.Linker.Tests/Tests/GetDisplayNameTests.cs32
-rw-r--r--test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs2
89 files changed, 2131 insertions, 1537 deletions
diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
deleted file mode 100644
index 5709726d3..000000000
--- a/.config/dotnet-tools.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "version": 1,
- "isRoot": true,
- "tools": {
- "dotnet-format": {
- "version": "5.0.211103",
- "commands": [
- "dotnet-format"
- ]
- }
- }
-}
diff --git a/.editorconfig b/.editorconfig
index ef8a70bec..79b5a9322 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -135,6 +135,11 @@ dotnet_diagnostic.CA2201.severity = none
# Analyzer crashes with https://github.com/dotnet/roslyn-analyzers/issues/5450
dotnet_diagnostic.CA2252.severity = none
+[src/linker/ref/**/*.cs]
+
+# CA1822: Mark members as static
+dotnet_diagnostic.CA1822.severity = none
+
[external**]
dotnet_analyzer_diagnostic.severity = none
generated_code = true
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 234b0fced..80251a28e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -7,5 +7,6 @@
/src/analyzer/ @radekdoulik
/src/ILLink.Tasks/ @sbomer
+/src/ILLink.RoslynAnalyzer/ @sbomer
/src/linker/ @marek-safar @mrvoorhe
/test/ @marek-safar @mrvoorhe
diff --git a/.gitignore b/.gitignore
index 414ad0275..d7f81b2c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
*.user
*.userprefs
.vs/
+.vscode/
.idea/
packages/
@@ -36,4 +37,7 @@ bin/
artifacts
*.binlog
+# Emacs backup files
+*~
+
test/Mono.Linker.Tests/TestResults.xml
diff --git a/docs/design/compiler-generated-code-handling.md b/docs/design/compiler-generated-code-handling.md
new file mode 100644
index 000000000..4ed908db0
--- /dev/null
+++ b/docs/design/compiler-generated-code-handling.md
@@ -0,0 +1,628 @@
+# Handling of compiler generated code
+
+Modern compilers provide language features which require lot of fancy code generation by the compiler. Not just pure IL generation, but producing new types, methods and fields. An example is `async`/`await` in C# which turns the body of the method into a separate class which implements a state machine.
+
+Lot of the trimming logic relies on attributes authored by the developer. These provide hints to the trimmer especially around areas which are otherwise problematic, like reflection. For example see [reflection-flow](reflection-flow.md) for an example of such attribute.
+
+## Problem
+
+User authored attributes are not propagated to the compiler generated code. For example (using C# async feature):
+
+```csharp
+[RequiresUnreferencedCode ("--MethodRequiresUnreferencedCode--")]
+static void MethodRequiresUnreferencedCode () { }
+
+[UnconditionalSuppressMessage ("IL2026", "")]
+static async void TestBeforeAwait ()
+{
+ MethodRequiresUnreferencedCode ();
+ await AsyncMethod ();
+}
+```
+
+This code should not produce any warning, because the `IL2026` is suppressed via an attribute. But currently this will produce the `IL2026` warning from a different method:
+
+```console
+ILLink: Trim analysis warning IL2026: SuppressWarningsInAsyncCode.<TestBeforeAwait>d__1.MoveNext(): Using method 'MethodRequiresUnreferencedCode()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
+```
+
+Note that the warning comes from a compiler generated method `MoveNext` on class `<TestBeforeAwait>d__1`. The `UnconditionalSuppressMessage` attribute is not propagated and so from a trimmer perspective this is completely unrelated code and thus the warning is not suppressed.
+
+### Method body attributes
+
+The trimmer currently recognizes two attributes which effectively apply to entire method body:
+
+#### `RequiresUnreferencedCodeAttribute`
+
+The `RequiresUnreferencedCodeAttribute` marks the method as incompatible with trimming and at the same time it suppressed trim analysis warnings from the entire method's body. So for example (using C# iterator feature):
+
+```csharp
+[RequiresUnreferencedCode ("Incompatible with trimming")]
+static IEnumerable<int> TestBeforeIterator ()
+{
+ MethodRequiresUnreferencedCode ();
+ yield return 1;
+}
+```
+
+Should not produce a warning.
+
+#### `UnconditionalSuppressMessageAttribute`
+
+The `UnconditionalSuppressMessageAttribute` can target lot of scopes, but the smallest one is a method. It can't target specific statements within a method. It is supposed to suppress a specific warning from the method's body, for example:
+
+```csharp
+[UnconditionalSuppressMessage("IL2026", "")]
+static async void TestAfterAwait ()
+{
+ await AsyncMethod ();
+ MethodRequiresUnreferencedCode ();
+}
+```
+
+Should not produce a warning.
+
+### Data flow analysis
+
+The trimmer performs data flow analysis within a single method's body, mostly around track the flow of `System.Type` and related instances to be able to detect recursion usage.
+
+#### `DynamicallyAccessedMembersAttribute`
+
+The `DynamicallyAccessedMembersAttribute` annotates values (local variables, method parameters, ...) of type `System.Type` to hint the trimmer that the type will have its methods accessed dynamically (through reflection). Such annotation doesn't propagate currently. For example:
+
+```csharp
+static IEnumerable<int> TestParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+{
+ type.GetMethod ("BeforeIteratorMethod");
+ yield return 1;
+ type.GetMethod ("AfterIteratorMethod");
+}
+```
+
+Should not produce any warnings, because the `type` variable is properly annotated.
+
+#### Intrinsic data flow
+
+The trimmer also intrinsically recognizes certain patterns and perform data flow analysis around them. This allows full analysis of certain reflection usage even without annotations. For example, intrinsic handling of the `typeof` keyword:
+
+```csharp
+static IEnumerable<int> TestLocalVariable ()
+{
+ Type type = typeof (TestType);
+ type.GetMethod ("BeforeIteratorMethod");
+ yield return 1;
+ type.GetMethod ("AfterIteratorMethod");
+}
+```
+
+### Compiler dependent behavior
+
+Since the problems are all caused by compiler generated code, the behaviors depend on the specific compiler in use. The main focus of this document is the Roslyn C# compiler right now. Mainly since it's by far the most used compiler for .NET code. That said, we would like to design the solution in such a way that other compilers using similar patterns could also benefit from it.
+
+It is expected that other compilers (for example the F# compiler) might have other patterns which are also problematic for trimmers. These should be eventually added to the document as well, but may require new solutions not discussed in here yet.
+
+## A - Roslyn closure rewrite expected behavior
+
+In order to create a lambda method with captured variables, the Roslyn compiler will generate a closure class which stores the captured values and the lambda method is then generated as a method on that class. Currently compiler doesn't propagate attributes to the generated methods.
+
+### A1 - `RequiresUnreferencedCode` with lambda
+
+```csharp
+[RequiresUnreferencedCode ("--TestLambdaWithCapture--")]
+static void TestLambdaWithCapture (int p)
+{
+ Action a = () => MethodRequiresUnreferencedCode (p);
+}
+```
+
+Trimmer should suppress trim analysis warnings due to `RequiresUnreferencedCode` even inside the lambda. In C# 10 it will be possible to add an attribute onto the lambda directly. The attribute should be propagated only if it's not already there.
+**Open question Q1a**: Should method body attributes propagate to lambdas? Maybe we should rely on C# 10 and explicit attributes only.
+
+### A2 - `UnconditionalSuppressMessage` with lambda
+
+```csharp
+[UnconditionalSuppressMessage ("IL2026", "")]
+static void TestLambdaWithCapture (int p)
+{
+ Action a = () => MethodRequiresUnreferencedCode (p);
+}
+```
+
+Trimmer should suppress `IL2026` due to the suppression attribute. In C# 10 it will be possible to add an attribute onto the lambda directly. The attribute should be propagated only if it's not already there.
+**Open question Q1a**: Should method body attributes propagate to lambdas? Maybe we should rely on C# 10 and explicit attributes only.
+
+### A3 - Data flow annotations with lambda
+
+```csharp
+static void TestParameterInLambda ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+{
+ Action a = () => {
+ type.GetMethod ("InLambdaMethod");
+ };
+}
+```
+
+Trimmer should be able to flow the annotation from the parameter into the closure for the lambda and thus avoid warning in this case.
+
+### A4 - Intrinsic data flow with lambda
+
+```csharp
+static void TestLocalVariableInLambda ()
+{
+ Type type = typeof (TestType);
+ Action a = () => {
+ type.GetMethod ("InLambdaMethod");
+ };
+}
+```
+
+Internal data flow tracking should propagate into lambdas.
+
+### A5 - Generic parameter data flow with lambda
+
+```csharp
+static void TestGenericParameterInLambda<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ()
+{
+ Action a = () => {
+ typeof (T).GetMethod ("InLocalMethod");
+ };
+}
+```
+
+Annotations should flow with the generic parameter into lambdas.
+
+### A6 - `RequiresUnreferencedCode` with local function
+
+```csharp
+[RequiresUnreferencedCode ("--TestLocalFunctionWithNoCapture--")]
+static void TestLocalFunctionWithNoCapture ()
+{
+ LocalFunction ();
+
+ void LocalFunction()
+ {
+ MethodRequiresUnreferencedCode ();
+ }
+}
+```
+
+The trimmer could propagate the `RequiresUnreferencedCode` to the local function. Unless the function already has that attribute present.
+**Question Q1b**: Should method body attributes propagate to local functions? It's possible to add the attribute manually to the local function, so maybe we should simply rely on that.
+
+### A7 - `UnconditionalSuppressMessage` with local function
+
+```csharp
+[UnconditionalSuppressMessage ("IL2026", "")]
+static void TestLocalFunctionWithNoCapture ()
+{
+ LocalFunction ();
+
+ void LocalFunction ()
+ {
+ MethodRequiresUnreferencedCode ();
+ }
+}
+```
+
+Similarly to the A5 case, the trimmer could propagate the warning suppression to the local function. Unless the function already has suppressions.
+**Question Q1b**: Should method body attributes propagate to local functions? It's possible to add the attribute manually to the local function, so maybe we should simply rely on that.
+
+### A8 - Data flow annotations with local function
+
+```csharp
+static void TestParameterInLocalFunction ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+{
+ LocalFunction ();
+
+ void LocalFunction ()
+ {
+ type.GetMethod ("InLocalMethod");
+ }
+}
+```
+
+Identical to A3, annotations should propagate into local functions.
+
+### A9 - Intrinsic data flow with local function
+
+```csharp
+static void TestLocalVariableInLocalFunction ()
+{
+ Type type = typeof (TestType);
+ LocalFunction ();
+
+ void LocalFunction ()
+ {
+ type.GetMethod ("InLocalMethod");
+ }
+}
+```
+
+Identical to A4 - Internal data flow tracking should propagate into local functions.
+
+### A10 - Generic parameter data flow with local functions
+
+```csharp
+static void TestGenericParameterInLocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ()
+{
+ LocalFunction ();
+
+ void LocalFunction ()
+ {
+ typeof (T).GetMethod ("InLocalMethod");
+ }
+}
+```
+
+Generic parameter annotations should flow into local methods.
+
+## B Roslyn iterator rewrites expected behavior
+
+Specifically the C# compiler will rewrite entire method bodies. Iterators which return enumeration and use `yield return` will rewrite entire method body and move it into a separate class. This has similar problems as closures since it effectively behaves a lot like closure, but has additional challenges due to different syntax.
+
+### B1 - `RequiresUnreferencedCode` with iterator body
+
+```csharp
+[RequiresUnreferencedCode ("--TestAfterIterator--")]
+static IEnumerable<int> TestAfterIterator ()
+{
+ yield return 1;
+ MethodRequiresUnreferencedCode ();
+}
+```
+
+The attribute should apply to the entire method body and thus suppress trim analysis warnings. Even if the body is spread by the compiler into different methods.
+
+### B2 - `UnconditionalSuppressMessage` with iterator body
+
+```csharp
+[UnconditionalSuppressMessage ("IL2026", "")]
+static IEnumerable<int> TestBeforeIterator ()
+{
+ MethodRequiresUnreferencedCode ();
+ yield return 1;
+}
+```
+
+The attribute should apply to the entire method body and thus suppress trim analysis warnings. Even if the body is spread by the compiler into different methods.
+
+### B3 - Data flow annotations in iterator body
+
+```csharp
+static IEnumerable<int> TestParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+{
+ type.GetMethod ("BeforeIteratorMethod");
+ yield return 1;
+ type.GetMethod ("AfterIteratorMethod");
+}
+```
+
+The data flow annotation from method parameter should flow through the entire body.
+
+### B4 - Intrinsic data flow in iterator body
+
+```csharp
+static IEnumerable<int> TestLocalVariable ()
+{
+ Type type = typeof (TestType);
+ type.GetMethod ("BeforeIteratorMethod");
+ yield return 1;
+ type.GetMethod ("AfterIteratorMethod");
+}
+```
+
+The intrinsic annotations should flow through the entire body.
+
+### B5 - Generic parameter data flow in iterator body
+
+```csharp
+static IEnumerable<int> TestGenericParameter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ()
+{
+ typeof (T).GetMethod ("BeforeIteratorMethod");
+ yield return 1;
+ typeof (T).GetMethod ("AfterIteratorMethod");
+}
+```
+
+Generic parameter annotations should flow through the entire body.
+
+## C Roslyn async rewrites expected behavior
+
+Similarly to iterators, C# compiler also rewrites method bodies which use `async`/`await`. This has similar problems as closures since it effectively behaves a lot like closure, but has additional challenges due to different syntax.
+
+### C1 - `RequiresUnreferencedCode` with async body
+
+```csharp
+[RequiresUnreferencedCode ("--TestAfterAwait--")]
+static async void TestAfterAwait ()
+{
+ await AsyncMethod ();
+ MethodRequiresUnreferencedCode ();
+}
+```
+
+The attribute should apply to the entire method body and thus suppress trim analysis warnings. Even if the body is spread by the compiler into different methods. Very similar to B1.
+
+### C2 - `UnconditionalSuppressMessage` with iterator body
+
+```csharp
+[UnconditionalSuppressMessage("IL2026", "")]
+static async void TestBeforeAwait()
+{
+ MethodRequiresUnreferencedCode ();
+ await AsyncMethod ();
+}
+```
+
+The attribute should apply to the entire method body and thus suppress trim analysis warnings. Even if the body is spread by the compiler into different methods. Very similar to B2.
+
+### C3 = Data flow annotations in async body
+
+```csharp
+static async void TestParameter ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+{
+ type.GetMethod ("BeforeAsyncMethod");
+ await AsyncMethod ();
+ type.GetMethod ("AfterAsyncMethod");
+}
+```
+
+The data flow annotation from method parameter should flow through the entire body. Very similar to B3.
+
+### C4 - Intrinsic data flow in async body
+
+```csharp
+static async void TestLocalVariable ()
+{
+ Type type = typeof (TestClass);
+ type.GetMethod ("BeforeAsyncMethod");
+ await AsyncMethod ();
+ type.GetMethod ("AfterAsyncMethod");
+}
+```
+
+The intrinsic annotations should flow through the entire body. Very similar to B4.
+
+### C5 - Generic parameter data flow in async body
+
+```csharp
+static async void TestGenericParameter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ()
+{
+ typeof (T).GetMethod ("BeforeIteratorMethod");
+ await AsyncMethod ();
+ typeof (T).GetMethod ("AfterIteratorMethod");
+}
+```
+
+Generic parameter annotations should flow through the entire body. Very similar to B5.
+
+## D Roslyn closure class and method naming behavior
+
+When the Roslyn compiler generates a closure and moves the code in the method into a method on the closure trimming tools should have enough information to provide correct information about the source of a warning (if there's any).
+
+### D1 - Lambda methods
+
+```csharp
+static void TestInLambda ()
+{
+ Action a = () => MethodRequiresUnreferencedCode (); // Warning should point to this line
+}
+```
+
+Given symbols this should produce a warning pointing to the source file, but should not include the method name which looks like `<>c.<TestInLambda>b__1_0()`. This should produce a warning which looks like:
+
+```console
+Source.cs(3,22): Trim analysis warning IL2026: Using method 'MethodRequiresUnreferencedCode()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
+```
+
+Similarly for all other warnings originating from trim analysis.
+
+**Open question Q2a:** Should we try to display a better name for lambdas if there are no symbols available for the assembly?
+
+### D2 - Local functions
+
+```csharp
+static void TestInLocalFunction ()
+{
+ LocalFunction ();
+
+ void LocalFunction()
+ {
+ MethodRequiresUnreferencedCode (); // Warning should point to this line
+ }
+}
+```
+
+Just like with lambdas, if there are symbols the warning should point to the source location and not include the compiler generated method name which in this case looks something like `Type.<TestInLocalFunction>g__LocalFunction|2_0()`. The produced warning should look like this:
+
+```console
+Source.cs(7,9): Using method 'MethodRequiresUnreferencedCode()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
+```
+
+**Open question Q2b:** Should we try to display a better name for local functions if there are no symbols available for the assembly?
+
+### D3 - Iterators
+
+```csharp
+static IEnumerable<int> TestIterator ()
+{
+ MethodRequiresUnreferencedCode (); // Warning should point to this line
+ yield return 1;
+}
+```
+
+In this case as well, the trimmer should report the warning pointing to the source and avoid including the compiler generated name which looks like `<TestIterator>d__3.MoveNext()`. The warning should look like this:
+
+```console
+Source.cs(3,5): Using method 'MethodRequiresUnreferencedCode()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
+```
+
+**Open question Q2c:** Should we try to display a better name for iterator methods if there are no symbols available for the assembly?
+
+### D4 - Async
+
+```csharp
+static async void TestAsync ()
+{
+ MethodRequiresUnreferencedCode ();
+ await AsyncMethod ();
+}
+```
+
+Just like in the above cases the warning should point to source and not include the compiler generated name, which looks like `<TestAsync>d__4.MoveNext()`. The warning should look like:
+
+```console
+Source.cs(3,5): Using method 'MethodRequiresUnreferencedCode()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
+```
+
+**Open question Q2d:** Should we try to display a better name for async methods if there are no symbols available for the assembly?
+
+## E Reporting user visible names from data flow analysis
+
+Data flow analysis in the trimmer reports warnings which point to sources of data values, for example method parameters, fields and so on. With closure classes generated by the compiler the warning might be in a spot where the immediate value is read from a field on the closure class, but that field is compiler generated. Ideally the warning would point to the actual source of the value for that field which is visible in user code.
+
+### E1 - Lambda methods
+
+```csharp
+static void TestWarningInLambda (Type typeParameter)
+{
+ Action a = () => typeParameter.GetMethod ("InLambdaMethod");
+}
+```
+
+The above should produce warning blaming `typeParameter` as the source of the unannotated value.
+
+### E2 - Local functions
+
+```csharp
+static void TestWarningInLocalFunction<TInput> ()
+{
+ Action a = () => typeof(TInput).GetMethod ("InLambdaMethod");
+}
+```
+
+In this case the warning should blame `TInput` as the unannotated value.
+
+### E3 - Iterators
+
+```csharp
+static IEnumerable<int> TestWarning(Type typeParameter)
+{
+ typeParameter.GetMethod ("InIteratorMethod");
+ yield return 1;
+}
+```
+
+This should produce warning blaming `typeParameter`.
+
+### E4 - Async
+
+```csharp
+static async void TestWarning<TInput>()
+{
+ typeof (TInput).GetMethod ("InAsyncMethod");
+ await AsyncMethod ();
+}
+```
+
+And this one should blame `TInput`.
+
+## Recommended solution
+
+The solution needs to solve two problems:
+
+* How to propagate warning suppression and `RequiresUnreferencedCode` suppression from
+the user method to all of the compiler generated methods/types which are called by that method.
+This is called "suppression propagation" below.
+* How to implement data flow analysis across the user method's body and all of the compiler generated
+methods, types and fields. This is called "data flow analysis" below.
+
+In both cases the first thing the trimmer needs to figure out is for a given user method
+what are all of the compiler generated items which were used to implement that method
+in the IL. This can include:
+
+* New types - for example closure types
+* New methods - for example methods on the closure types, or methods on the parent type for local functions
+* New fields - fields on the closure types
+* New generic parameters - closure types and methods may be generic if the user method is generic
+
+To correctly handle warning suppression, the trimmer needs to apply the same warning suppressions
+on warnings generated due to all of the compiler generated items as if those were coming
+directly from the user method's body.
+
+To correctly handle data flow analysis, the trimmer needs to be able to track values across all of the
+compiler generated items as if they implement a single unit. This almost inevitable leads to
+cross method data flow analysis. Since that is a very expensive thing to do, being able to confine
+it to only the compiler generated code for a given user method is almost necessary. On top of that
+the trimmer needs to be able to track values as they traverse local variables, method parameters
+and fields on the closure types.
+
+### Long term solution
+
+Detecting which compiler generated items are used by any given user method is currently relatively tricky.
+There's no definitive marker in the IL which would let the trimmer confidently determine this information.
+Good long term solution will need the compilers to produce some kind of marker in the IL so that
+static analysis tools can reliably detect all of the compiler generated items.
+
+This ask can be described as:
+For a given user method, ability to determine all of the items (methods, fields, types, IL code) which were
+used by the compiler to generate the functionality of the method into an IL assembly.
+
+This should be things which are directly generated from the user's code. It should NOT include compiler
+helpers and other infrastructure which may be needed but is not directly attributable to a user code.
+
+This should be enough to implement solutions for both suppression propagation and data flow analysis.
+
+### Possible short term solution
+
+#### Heuristic based solution
+
+Without compiler provided markers, there's no existing way to 100% reliably implement the required
+functionality in the trimmer. That said, it should be possible to implement a reasonably good
+approximation. This approximation will necessarily make assumptions about the compilers used
+to produce the analyzed code. So for the purposes of a short term solution, Roslyn CSharp compiler
+should be treated as first priority (since it's by far the most common compiler to produce analyzed IL).
+Second in row should be the FSharp compiler.
+
+It is also much simpler to implement suppression propagation, so that should be done first.
+
+The general idea how to detect compiler generated code for a given user method:
+
+* Ability to detect compiler generated code. Can be done by detecting identifiers which are invalid
+in a given language. For CSharp, the compiler uses `<` and `>` characters in the identifiers
+of a compiler generated items. In FSharp this role is served by the `@` character.
+* Any compiler generated item (as detected per above) referenced from a user method
+will be considered to belong to that user method.
+
+Pros:
+
+* Can handle all cases for warning suppressions - async, iterator, lambdas and local functions
+* Can work on not just Roslyn generated IL
+
+Cons:
+
+* Heuristic - it may get it wrong in which case the trimmer may report less warnings than it should
+* Complex implementation mainly due to issues with reflection accessed code. For example if the closure class
+is marked only due to reflection access (for example `DynamicallyAccessedMemberType.All`) and the actual
+user method is not marked at all then there's no good way to determine the user method to figure out suppression
+context. Again can lead to reporting less warnings.
+
+#### Deterministic partial solution based on attributes
+
+For state machines the Roslyn compiler currently generates `IteratorStateMachineAttribute`, `AsyncStateMachineAttribute` and `AsyncIteratorStateMachineAttribute` attributes onto the "user method" and the attribute points to the generated state machine type.
+
+This can be used to completely deterministically figure out the mapping between state machine code and user methods.
+
+Pros:
+
+* Deterministic and reliable - as long as Roslyn generates these attributes (which is considered internal behavior)
+* Relatively simple implementation in the trimmer for suppressions
+
+Cons:
+
+* Partial solution - only works on async and iterator methods, doesn't work on lambdas and local functions
+
+The recommended solution is to use the deterministic approach via attributes. This solution doesn't have the reflection access problem (which is very problematic).
+The fact that it doesn't solve lambdas and local functions has a reasonable workaround. Both can be annotated
+manually by the developer by adding attributes to them. This introduces a discrepancy between analyzer
+and trimmer (as analyzer would not have this problem), but it's acceptable behavior for .NET 6. \ No newline at end of file
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 035206c8f..2edca87dc 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -3,18 +3,18 @@
<ProductDependencies>
</ProductDependencies>
<ToolsetDependencies>
- <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.21524.1">
+ <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.21559.3">
<Uri>https://github.com/dotnet/arcade</Uri>
- <Sha>0cdef445272ad6a7374dfed71496c5affef90305</Sha>
+ <Sha>fecf65bedcee9036b8ba9d8d7feef5413f294914</Sha>
<SourceBuild RepoName="arcade" ManagedOnly="true" />
</Dependency>
- <Dependency Name="Microsoft.DotNet.ApiCompat" Version="7.0.0-beta.21524.1">
+ <Dependency Name="Microsoft.DotNet.ApiCompat" Version="7.0.0-beta.21559.3">
<Uri>https://github.com/dotnet/arcade</Uri>
- <Sha>0cdef445272ad6a7374dfed71496c5affef90305</Sha>
+ <Sha>fecf65bedcee9036b8ba9d8d7feef5413f294914</Sha>
</Dependency>
- <Dependency Name="Microsoft.NET.Sdk.IL" Version="7.0.0-alpha.1.21524.4">
+ <Dependency Name="Microsoft.NET.Sdk.IL" Version="7.0.0-alpha.1.21562.1">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>9e795c014b0be513c84f96427c544bae486bb101</Sha>
+ <Sha>35704e44e5d1b158f21512b1c1081a0e025bde3f</Sha>
<!--
This would introduce a cyclic dependency, so it's explictly not enabled for now
<SourceBuild RepoName="runtime" />
diff --git a/eng/Versions.props b/eng/Versions.props
index 59cc427dd..16ba658f6 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -11,14 +11,14 @@
<PropertyGroup>
<UsingToolMicrosoftNetCompilers>true</UsingToolMicrosoftNetCompilers>
<!-- ilasm -->
- <MicrosoftNETSdkILPackageVersion>7.0.0-alpha.1.21524.4</MicrosoftNETSdkILPackageVersion>
+ <MicrosoftNETSdkILPackageVersion>7.0.0-alpha.1.21562.1</MicrosoftNETSdkILPackageVersion>
<!-- see https://github.com/dotnet/runtime/issues/1338 -->
<MicrosoftNETCoreILAsmVersion>$(MicrosoftNETSdkILPackageVersion)</MicrosoftNETCoreILAsmVersion>
<!-- SRM version should match the SDK version at https://github.com/dotnet/sdk/blob/master/eng/Versions.props -->
<SystemReflectionMetadataVersion>5.0.0</SystemReflectionMetadataVersion>
<MicrosoftBuildFrameworkVersion>17.0.0-preview-21267-01</MicrosoftBuildFrameworkVersion>
<MicrosoftBuildUtilitiesCoreVersion>17.0.0-preview-21267-01</MicrosoftBuildUtilitiesCoreVersion>
- <MicrosoftDotNetApiCompatVersion>7.0.0-beta.21524.1</MicrosoftDotNetApiCompatVersion>
+ <MicrosoftDotNetApiCompatVersion>7.0.0-beta.21559.3</MicrosoftDotNetApiCompatVersion>
<MicrosoftDotNetCodeAnalysisVersion>6.0.0-beta.21271.1</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftCodeAnalysisCSharpCodeStyleVersion>3.10.0-2.final</MicrosoftCodeAnalysisCSharpCodeStyleVersion>
<MicrosoftCodeAnalysisVersion>3.10.0-2.final</MicrosoftCodeAnalysisVersion>
diff --git a/eng/common/msbuild.ps1 b/eng/common/msbuild.ps1
index eea19cd84..f041e5ddd 100644
--- a/eng/common/msbuild.ps1
+++ b/eng/common/msbuild.ps1
@@ -6,6 +6,7 @@ Param(
[switch] $ci,
[switch] $prepareMachine,
[switch] $excludePrereleaseVS,
+ [string] $msbuildEngine = $null,
[Parameter(ValueFromRemainingArguments=$true)][String[]]$extraArgs
)
diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1
index a4a92efbe..cd2181baf 100644
--- a/eng/common/post-build/symbols-validation.ps1
+++ b/eng/common/post-build/symbols-validation.ps1
@@ -134,17 +134,17 @@ $CountMissingSymbols = {
# Save the output and get diagnostic output
$output = & $dotnetSymbolExe --symbols --modules $WindowsPdbVerificationParam $TargetServerParam $FullPath -o $SymbolsPath --diagnostics | Out-String
- if (Test-Path $PdbPath) {
- return 'PDB'
+ if ((Test-Path $PdbPath) -and (Test-path $SymbolPath)) {
+ return 'Module and PDB for Module'
}
- elseif (Test-Path $NGenPdb) {
- return 'NGen PDB'
+ elseif ((Test-Path $NGenPdb) -and (Test-Path $PdbPath) -and (Test-Path $SymbolPath)) {
+ return 'Dll, PDB and NGen PDB'
}
- elseif (Test-Path $SODbg) {
- return 'DBG for SO'
+ elseif ((Test-Path $SODbg) -and (Test-Path $SymbolPath)) {
+ return 'So and DBG for SO'
}
- elseif (Test-Path $DylibDwarf) {
- return 'Dwarf for Dylib'
+ elseif ((Test-Path $DylibDwarf) -and (Test-Path $SymbolPath)) {
+ return 'Dylib and Dwarf for Dylib'
}
elseif (Test-Path $SymbolPath) {
return 'Module'
diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml
index 69eb67849..3aafc82e4 100644
--- a/eng/common/templates/job/execute-sdl.yml
+++ b/eng/common/templates/job/execute-sdl.yml
@@ -60,11 +60,7 @@ jobs:
- name: GuardianPackagesConfigFile
value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config
pool:
- # To extract archives (.tar.gz, .zip), we need access to "tar", added in Windows 10/2019.
- ${{ if eq(parameters.extractArchiveArtifacts, 'false') }}:
- name: Hosted VS2017
- ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}:
- vmImage: windows-2019
+ vmImage: windows-2019
steps:
- checkout: self
clean: true
diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml
index e8bc77d2e..c4fc18b3e 100644
--- a/eng/common/templates/job/onelocbuild.yml
+++ b/eng/common/templates/job/onelocbuild.yml
@@ -4,7 +4,7 @@ parameters:
# Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool
pool:
- vmImage: vs2017-win2016
+ vmImage: 'windows-2019'
CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex
GithubPat: $(BotAccount-dotnet-bot-repo-PAT)
@@ -12,6 +12,7 @@ parameters:
SourcesDirectory: $(Build.SourcesDirectory)
CreatePr: true
AutoCompletePr: false
+ ReusePr: true
UseLfLineEndings: true
UseCheckedInLocProjectJson: false
LanguageSet: VS_Main_Languages
@@ -64,6 +65,8 @@ jobs:
${{ if eq(parameters.CreatePr, true) }}:
isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }}
isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }}
+ ${{ if eq(parameters.RepoType, 'gitHub') }}:
+ isShouldReusePrSelected: ${{ parameters.ReusePr }}
packageSourceAuth: patAuth
patVariable: ${{ parameters.CeapexPat }}
${{ if eq(parameters.RepoType, 'gitHub') }}:
diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml
index 5023d36dc..5cd5325d7 100644
--- a/eng/common/templates/job/source-build.yml
+++ b/eng/common/templates/job/source-build.yml
@@ -31,11 +31,6 @@ parameters:
# container and pool.
platform: {}
- # The default VM host AzDO pool. This should be capable of running Docker containers: almost all
- # source-build builds run in Docker, including the default managed platform.
- defaultContainerHostPool:
- vmImage: ubuntu-20.04
-
jobs:
- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }}
displayName: Source-Build (${{ parameters.platform.name }})
@@ -47,7 +42,15 @@ jobs:
container: ${{ parameters.platform.container }}
${{ if eq(parameters.platform.pool, '') }}:
- pool: ${{ parameters.defaultContainerHostPool }}
+ # The default VM host AzDO pool. This should be capable of running Docker containers: almost all
+ # source-build builds run in Docker, including the default managed platform.
+ pool:
+ ${{ if eq(variables['System.TeamProject'], 'public') }}:
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ name: NetCore1ESPool-Internal
+ demands: ImageOverride -equals Build.Ubuntu.1804.Amd64
${{ if ne(parameters.platform.pool, '') }}:
pool: ${{ parameters.platform.pool }}
diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml
index 1cc0c29e4..4af724eb1 100644
--- a/eng/common/templates/job/source-index-stage1.yml
+++ b/eng/common/templates/job/source-index-stage1.yml
@@ -5,8 +5,6 @@ parameters:
sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci"
preSteps: []
binlogPath: artifacts/log/Debug/Build.binlog
- pool:
- vmImage: vs2017-win2016
condition: ''
dependsOn: ''
@@ -24,7 +22,13 @@ jobs:
- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- group: source-dot-net stage1 variables
- pool: ${{ parameters.pool }}
+ pool:
+ ${{ if eq(variables['System.TeamProject'], 'public') }}:
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals Build.Server.Amd64.VS2019.Open
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ name: NetCore1ESPool-Internal
+ demands: ImageOverride -equals Build.Server.Amd64.VS2019
steps:
- ${{ each preStep in parameters.preSteps }}:
- ${{ preStep }}
diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml
index a1f8fce96..8dd1fdbd1 100644
--- a/eng/common/templates/jobs/jobs.yml
+++ b/eng/common/templates/jobs/jobs.yml
@@ -83,7 +83,7 @@ jobs:
- ${{ if eq(parameters.enableSourceBuild, true) }}:
- Source_Build_Complete
pool:
- vmImage: vs2017-win2016
+ vmImage: 'windows-2019'
runAsPublic: ${{ parameters.runAsPublic }}
publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }}
enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }}
@@ -96,4 +96,4 @@ jobs:
dependsOn:
- Asset_Registry_Publish
pool:
- vmImage: vs2017-win2016
+ vmImage: 'windows-2019'
diff --git a/global.json b/global.json
index 8f2190165..80620c636 100644
--- a/global.json
+++ b/global.json
@@ -1,10 +1,10 @@
{
"tools": {
- "dotnet": "6.0.100-rc.1.21430.12"
+ "dotnet": "6.0.100"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21524.1",
+ "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21559.3",
"Microsoft.FIX-85B6-MERGE-9C38-CONFLICT": "1.0.0",
- "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.21524.4"
+ "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.21562.1"
}
}
diff --git a/lint.cmd b/lint.cmd
index 7e17179ce..f4c4466a9 100644
--- a/lint.cmd
+++ b/lint.cmd
@@ -1,3 +1,2 @@
@echo off
-powershell -ExecutionPolicy ByPass -NoProfile -command "Set-Location %~dp0; & """%~dp0eng\dotnet.ps1""" ""tool restore"""
-powershell -ExecutionPolicy ByPass -NoProfile -command "Set-Location %~dp0; & """%~dp0eng\dotnet.ps1""" ""tool run dotnet-format -- illink.sln --fix-whitespace --exclude src/analyzer src/tuner external %*"""
+powershell -ExecutionPolicy ByPass -NoProfile -command "Set-Location %~dp0; & """%~dp0eng\dotnet.ps1""" ""format illink.sln --exclude src/analyzer src/tuner external %*"""
diff --git a/lint.sh b/lint.sh
index 0e3815471..570584c04 100755
--- a/lint.sh
+++ b/lint.sh
@@ -13,5 +13,4 @@ while [[ -h $source ]]; do
done
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
-"$scriptroot/eng/dotnet.sh" tool restore
-"$scriptroot/eng/dotnet.sh" tool run dotnet-format -- illink.sln --fix-whitespace --exclude src/analyzer src/tuner external $@
+"$scriptroot/eng/dotnet.sh" format illink.sln --exclude src/analyzer src/tuner external $@
diff --git a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs
index 75e3fbe57..6ceae6d4a 100644
--- a/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs
+++ b/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs
@@ -8,6 +8,7 @@ using System.Linq;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
@@ -144,6 +145,51 @@ namespace ILLink.RoslynAnalyzer
CheckCalledMember (operationContext, methodSymbol, incompatibleMembers);
}, OperationKind.DelegateCreation);
+ context.RegisterSyntaxNodeAction (syntaxNodeAnalysisContext => {
+ var model = syntaxNodeAnalysisContext.SemanticModel;
+ if (syntaxNodeAnalysisContext.ContainingSymbol is not ISymbol containingSymbol || containingSymbol.HasAttribute (RequiresAttributeName))
+ return;
+
+ GenericNameSyntax genericNameSyntaxNode = (GenericNameSyntax) syntaxNodeAnalysisContext.Node;
+ var typeParams = ImmutableArray<ITypeParameterSymbol>.Empty;
+ var typeArgs = ImmutableArray<ITypeSymbol>.Empty;
+ switch (model.GetSymbolInfo (genericNameSyntaxNode).Symbol) {
+ case INamedTypeSymbol typeSymbol:
+ typeParams = typeSymbol.TypeParameters;
+ typeArgs = typeSymbol.TypeArguments;
+ break;
+
+ case IMethodSymbol methodSymbol:
+ typeParams = methodSymbol.TypeParameters;
+ typeArgs = methodSymbol.TypeArguments;
+ break;
+
+ default:
+ return;
+ }
+
+ for (int i = 0; i < typeParams.Length; i++) {
+ var typeParam = typeParams[i];
+ var typeArg = typeArgs[i];
+ if (!typeParam.HasConstructorConstraint)
+ continue;
+
+ var typeArgCtors = ((INamedTypeSymbol) typeArg).InstanceConstructors;
+ foreach (var instanceCtor in typeArgCtors) {
+ if (instanceCtor.Arity > 0)
+ continue;
+
+ if (instanceCtor.TryGetAttribute (RequiresAttributeName, out var requiresUnreferencedCodeAttribute)) {
+ syntaxNodeAnalysisContext.ReportDiagnostic (Diagnostic.Create (RequiresDiagnosticRule,
+ syntaxNodeAnalysisContext.Node.GetLocation (),
+ containingSymbol.GetDisplayName (),
+ (string) requiresUnreferencedCodeAttribute.ConstructorArguments[0].Value!,
+ GetUrlFromAttribute (requiresUnreferencedCodeAttribute)));
+ }
+ }
+ }
+ }, SyntaxKind.GenericName);
+
// Register any extra operation actions supported by the analyzer.
foreach (var extraOperationAction in ExtraOperationActions)
context.RegisterOperationAction (extraOperationAction.Action, extraOperationAction.OperationKind);
diff --git a/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
index 146eef064..f2e14ff60 100644
--- a/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
@@ -24,9 +24,9 @@ namespace ILLink.RoslynAnalyzer
static readonly DiagnosticDescriptor s_requiresAssemblyFilesRule = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssemblyFiles,
helpLinkUri: "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3002");
- static readonly DiagnosticDescriptor s_requiresAssembyFilesAttributeMismatch = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssembyFilesAttributeMismatch);
+ static readonly DiagnosticDescriptor s_requiresAssemblyFilesAttributeMismatch = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssemblyFilesAttributeMismatch);
- public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_locationRule, s_getFilesRule, s_requiresAssemblyFilesRule, s_requiresAssembyFilesAttributeMismatch);
+ public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_locationRule, s_getFilesRule, s_requiresAssemblyFilesRule, s_requiresAssemblyFilesAttributeMismatch);
private protected override string RequiresAttributeName => RequiresAssemblyFilesAttribute;
@@ -36,7 +36,7 @@ namespace ILLink.RoslynAnalyzer
private protected override DiagnosticDescriptor RequiresDiagnosticRule => s_requiresAssemblyFilesRule;
- private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresAssembyFilesAttributeMismatch;
+ private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresAssemblyFilesAttributeMismatch;
protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation compilation)
{
diff --git a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
index ba060ccf0..7e4f7e5a2 100644
--- a/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
@@ -3,11 +3,8 @@
using System;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace ILLink.RoslynAnalyzer
@@ -35,56 +32,6 @@ namespace ILLink.RoslynAnalyzer
operationContext.Operation.Syntax.GetLocation ()));
};
- [SuppressMessage ("MicrosoftCodeAnalysisPerformance", "RS1008",
- Justification = "Storing per-compilation data inside a diagnostic analyzer might cause stale compilations to remain alive." +
- "This action is registered through a compilation start action, so that instances that register this syntax" +
- " node action will not outlive a compilation's lifetime, avoiding the possibility of the locals stored in" +
- " this function to cause for any stale compilations to remain in memory.")]
- static readonly Action<SyntaxNodeAnalysisContext> s_constructorConstraint = syntaxNodeAnalysisContext => {
- var model = syntaxNodeAnalysisContext.SemanticModel;
- if (syntaxNodeAnalysisContext.ContainingSymbol is not ISymbol containingSymbol || containingSymbol.HasAttribute (RequiresUnreferencedCodeAttribute))
- return;
-
- GenericNameSyntax genericNameSyntaxNode = (GenericNameSyntax) syntaxNodeAnalysisContext.Node;
- var typeParams = ImmutableArray<ITypeParameterSymbol>.Empty;
- var typeArgs = ImmutableArray<ITypeSymbol>.Empty;
- switch (model.GetSymbolInfo (genericNameSyntaxNode).Symbol) {
- case INamedTypeSymbol typeSymbol:
- typeParams = typeSymbol.TypeParameters;
- typeArgs = typeSymbol.TypeArguments;
- break;
-
- case IMethodSymbol methodSymbol:
- typeParams = methodSymbol.TypeParameters;
- typeArgs = methodSymbol.TypeArguments;
- break;
-
- default:
- return;
- }
-
- for (int i = 0; i < typeParams.Length; i++) {
- var typeParam = typeParams[i];
- var typeArg = typeArgs[i];
- if (!typeParam.HasConstructorConstraint)
- continue;
-
- var typeArgCtors = ((INamedTypeSymbol) typeArg).InstanceConstructors;
- foreach (var instanceCtor in typeArgCtors) {
- if (instanceCtor.Arity > 0)
- continue;
-
- if (instanceCtor.TryGetAttribute (RequiresUnreferencedCodeAttribute, out var requiresUnreferencedCodeAttribute)) {
- syntaxNodeAnalysisContext.ReportDiagnostic (Diagnostic.Create (s_requiresUnreferencedCodeRule,
- syntaxNodeAnalysisContext.Node.GetLocation (),
- containingSymbol.GetDisplayName (),
- (string) requiresUnreferencedCodeAttribute.ConstructorArguments[0].Value!,
- GetUrlFromAttribute (requiresUnreferencedCodeAttribute)));
- }
- }
- }
- };
-
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create (s_dynamicTypeInvocationRule, s_makeGenericMethodRule, s_makeGenericTypeRule, s_requiresUnreferencedCodeRule, s_requiresUnreferencedCodeAttributeMismatch);
@@ -133,9 +80,6 @@ namespace ILLink.RoslynAnalyzer
private protected override ImmutableArray<(Action<OperationAnalysisContext> Action, OperationKind[] OperationKind)> ExtraOperationActions =>
ImmutableArray.Create ((s_dynamicTypeInvocation, new OperationKind[] { OperationKind.DynamicInvocation }));
- private protected override ImmutableArray<(Action<SyntaxNodeAnalysisContext> Action, SyntaxKind[] SyntaxKind)> ExtraSyntaxNodeActions =>
- ImmutableArray.Create ((s_constructorConstraint, new SyntaxKind[] { SyntaxKind.GenericName }));
-
protected override bool VerifyAttributeArguments (AttributeData attribute) =>
attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg;
diff --git a/src/ILLink.Shared/DiagnosticId.cs b/src/ILLink.Shared/DiagnosticId.cs
index 10dda58b6..b7871d6f5 100644
--- a/src/ILLink.Shared/DiagnosticId.cs
+++ b/src/ILLink.Shared/DiagnosticId.cs
@@ -45,7 +45,7 @@ namespace ILLink.Shared
AvoidAssemblyLocationInSingleFile = 3000,
AvoidAssemblyGetFilesInSingleFile = 3001,
RequiresAssemblyFiles = 3002,
- RequiresAssembyFilesAttributeMismatch = 3003
+ RequiresAssemblyFilesAttributeMismatch = 3003
}
public static class DiagnosticIdExtensions
diff --git a/src/ILLink.Shared/DiagnosticString.cs b/src/ILLink.Shared/DiagnosticString.cs
index 4178c22b3..a72f9f7b1 100644
--- a/src/ILLink.Shared/DiagnosticString.cs
+++ b/src/ILLink.Shared/DiagnosticString.cs
@@ -1,6 +1,5 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
namespace ILLink.Shared
{
diff --git a/src/ILLink.Shared/SharedStrings.resx b/src/ILLink.Shared/SharedStrings.resx
index 37e46db93..83af489f2 100644
--- a/src/ILLink.Shared/SharedStrings.resx
+++ b/src/ILLink.Shared/SharedStrings.resx
@@ -147,6 +147,12 @@
<data name="RequiresUnreferencedCodeAttributeMismatchTitle" xml:space="preserve">
<value>'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.</value>
</data>
+ <data name="RequiresAssemblyFilesAttributeMismatchMessage" xml:space="preserve">
+ <value>{0}. 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides.</value>
+ </data>
+ <data name="RequiresAssemblyFilesAttributeMismatchTitle" xml:space="preserve">
+ <value>'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides.</value>
+ </data>
<data name="BaseRequiresMismatchMessage" xml:space="preserve">
<value>Base member '{2}' with '{0}' has a derived member '{1}' without '{0}'</value>
</data>
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
index 122fd337c..570752746 100644
--- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
+++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
@@ -1100,8 +1100,7 @@ namespace Mono.Linker.Dataflow
reflectionContext.RecordHandledPattern ();
} else {
// Otherwise fall back to the bitfield requirements
- var requiredMemberTypes = HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicConstructors : DynamicallyAccessedMemberTypes.None;
- requiredMemberTypes |= HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicConstructors : DynamicallyAccessedMemberTypes.None;
+ var requiredMemberTypes = GetDynamicallyAccessedMemberTypesFromBindingFlagsForConstructors (bindingFlags);
// We can scope down the public constructors requirement if we know the number of parameters is 0
if (requiredMemberTypes == DynamicallyAccessedMemberTypes.PublicConstructors && ctorParameterCount == 0)
requiredMemberTypes = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor;
@@ -2088,7 +2087,33 @@ namespace Mono.Linker.Dataflow
static BindingFlags? GetBindingFlagsFromValue (ValueNode? parameter) => (BindingFlags?) parameter.AsConstInt ();
- static bool BindingFlagsAreUnsupported (BindingFlags? bindingFlags) => bindingFlags == null || (bindingFlags & BindingFlags.IgnoreCase) == BindingFlags.IgnoreCase || (int) bindingFlags > 255;
+ static bool BindingFlagsAreUnsupported (BindingFlags? bindingFlags)
+ {
+ if (bindingFlags == null)
+ return true;
+
+ // Binding flags we understand
+ const BindingFlags UnderstoodBindingFlags =
+ BindingFlags.DeclaredOnly |
+ BindingFlags.Instance |
+ BindingFlags.Static |
+ BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.FlattenHierarchy |
+ BindingFlags.ExactBinding;
+
+ // Binding flags that don't affect binding outside InvokeMember (that we don't analyze).
+ const BindingFlags IgnorableBindingFlags =
+ BindingFlags.InvokeMethod |
+ BindingFlags.CreateInstance |
+ BindingFlags.GetField |
+ BindingFlags.SetField |
+ BindingFlags.GetProperty |
+ BindingFlags.SetProperty;
+
+ BindingFlags flags = bindingFlags.Value;
+ return (flags & ~(UnderstoodBindingFlags | IgnorableBindingFlags)) != 0;
+ }
static bool HasBindingFlag (BindingFlags? bindingFlags, BindingFlags? search) => bindingFlags != null && (bindingFlags & search) == search;
@@ -2212,27 +2237,33 @@ namespace Mono.Linker.Dataflow
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForNestedTypes (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicNestedTypes : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicNestedTypes : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicNestedTypes : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForConstructors (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicConstructors : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicConstructors : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicConstructors : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForMethods (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicMethods : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicMethods : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicMethods : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForFields (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicFields : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicFields : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicFields : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForProperties (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicProperties : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicProperties : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicProperties : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForEvents (BindingFlags? bindingFlags) =>
(HasBindingFlag (bindingFlags, BindingFlags.Public) ? DynamicallyAccessedMemberTypes.PublicEvents : DynamicallyAccessedMemberTypes.None) |
- (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicEvents : DynamicallyAccessedMemberTypes.None);
+ (HasBindingFlag (bindingFlags, BindingFlags.NonPublic) ? DynamicallyAccessedMemberTypes.NonPublicEvents : DynamicallyAccessedMemberTypes.None) |
+ (BindingFlagsAreUnsupported (bindingFlags) ? DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents : DynamicallyAccessedMemberTypes.None);
static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesFromBindingFlagsForMembers (BindingFlags? bindingFlags) =>
GetDynamicallyAccessedMemberTypesFromBindingFlagsForConstructors (bindingFlags) |
GetDynamicallyAccessedMemberTypesFromBindingFlagsForEvents (bindingFlags) |
diff --git a/src/linker/Linker.Steps/BaseSubStep.cs b/src/linker/Linker.Steps/BaseSubStep.cs
index 4826c7014..af991fda9 100644
--- a/src/linker/Linker.Steps/BaseSubStep.cs
+++ b/src/linker/Linker.Steps/BaseSubStep.cs
@@ -1,7 +1,6 @@
// 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.Diagnostics;
using Mono.Cecil;
diff --git a/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs b/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs
index 8497a61ea..64561aa6b 100644
--- a/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs
+++ b/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs
@@ -1,7 +1,6 @@
// 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 Mono.Cecil;
diff --git a/src/linker/Linker.Steps/DiscoverSerializationHandler.cs b/src/linker/Linker.Steps/DiscoverSerializationHandler.cs
index 0b30d6ea4..6ac6da881 100644
--- a/src/linker/Linker.Steps/DiscoverSerializationHandler.cs
+++ b/src/linker/Linker.Steps/DiscoverSerializationHandler.cs
@@ -2,12 +2,8 @@
// 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 Mono.Cecil;
-using Mono.Linker.Dataflow;
-using Mono.Linker.Steps;
namespace Mono.Linker.Steps
{
diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs
index 524c9195e..4921299ef 100644
--- a/src/linker/Linker.Steps/MarkStep.cs
+++ b/src/linker/Linker.Steps/MarkStep.cs
@@ -1387,7 +1387,9 @@ namespace Mono.Linker.Steps
MarkExportedTypesTarget.ProcessAssembly (assembly, Context);
if (ProcessReferencesStep.IsFullyPreservedAction (Context.Annotations.GetAction (assembly))) {
- MarkEntireAssembly (assembly);
+ if (!Context.TryGetCustomData ("DisableMarkingOfCopyAssemblies", out string? disableMarkingOfCopyAssembliesValue) ||
+ disableMarkingOfCopyAssembliesValue != "true")
+ MarkEntireAssembly (assembly);
return;
}
diff --git a/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs b/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs
index f97004fd0..8f15014f3 100644
--- a/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs
+++ b/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs
@@ -1,7 +1,6 @@
// 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;
diff --git a/src/linker/Linker.Steps/OutputStep.cs b/src/linker/Linker.Steps/OutputStep.cs
index b28d52c8d..2fd32880d 100644
--- a/src/linker/Linker.Steps/OutputStep.cs
+++ b/src/linker/Linker.Steps/OutputStep.cs
@@ -32,7 +32,6 @@ using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using Mono.Cecil;
-using Mono.Cecil.Cil;
namespace Mono.Linker.Steps
{
diff --git a/src/linker/Linker.Steps/SubStepsDispatcher.cs b/src/linker/Linker.Steps/SubStepsDispatcher.cs
index 3ed5a6e1c..338bbda8b 100644
--- a/src/linker/Linker.Steps/SubStepsDispatcher.cs
+++ b/src/linker/Linker.Steps/SubStepsDispatcher.cs
@@ -1,7 +1,6 @@
// 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;
diff --git a/src/linker/Linker/AttributeInfo.cs b/src/linker/Linker/AttributeInfo.cs
index 23b31c433..ea430b2de 100644
--- a/src/linker/Linker/AttributeInfo.cs
+++ b/src/linker/Linker/AttributeInfo.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using Mono.Cecil;
namespace Mono.Linker
diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs
index 2c52424d5..46db485f5 100644
--- a/src/linker/Linker/Driver.cs
+++ b/src/linker/Linker/Driver.cs
@@ -763,7 +763,7 @@ namespace Mono.Linker
// to the error code.
// May propagate exceptions, which will result in the process getting an
// exit code determined by dotnet.
- public int Run (ILogger? customLogger = null)
+ public int Run (ILogger? customLogger = null, bool throwOnFatalLinkerException = false)
{
int setupStatus = SetupContext (customLogger);
if (setupStatus > 0)
@@ -782,6 +782,8 @@ namespace Mono.Linker
Debug.Assert (lex.MessageContainer.Category == MessageCategory.Error);
Debug.Assert (lex.MessageContainer.Code != null);
Debug.Assert (lex.MessageContainer.Code.Value != 0);
+ if (throwOnFatalLinkerException)
+ throw;
return lex.MessageContainer.Code ?? 1;
} catch (ResolutionException e) {
Context.LogError ($"{e.Message}", 1040);
diff --git a/src/linker/Linker/EmbeddedXmlInfo.cs b/src/linker/Linker/EmbeddedXmlInfo.cs
index 14871394b..815bbb8d2 100644
--- a/src/linker/Linker/EmbeddedXmlInfo.cs
+++ b/src/linker/Linker/EmbeddedXmlInfo.cs
@@ -2,10 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.IO;
using System.Linq;
using System.Xml;
-using System.Xml.XPath;
using Mono.Cecil;
using Mono.Linker.Steps;
diff --git a/src/linker/Linker/MemberReferenceExtensions.cs b/src/linker/Linker/MemberReferenceExtensions.cs
index b24364aaa..14278fdef 100644
--- a/src/linker/Linker/MemberReferenceExtensions.cs
+++ b/src/linker/Linker/MemberReferenceExtensions.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Diagnostics;
+using System.Diagnostics;
using System.Text;
using Mono.Cecil;
diff --git a/src/linker/Linker/MethodDefinitionExtensions.cs b/src/linker/Linker/MethodDefinitionExtensions.cs
index 165b75138..d8b370422 100644
--- a/src/linker/Linker/MethodDefinitionExtensions.cs
+++ b/src/linker/Linker/MethodDefinitionExtensions.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using Mono.Cecil;
namespace Mono.Linker
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))