Skip to content

Commit

Permalink
Use attributes on lambdas in tests (#2682)
Browse files Browse the repository at this point in the history
* Use attributes on lambdas in tests

* Fix formatting

* Unindent attributes
  • Loading branch information
sbomer authored Mar 11, 2022
1 parent 5baeb5e commit 93eac59
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 72 deletions.
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<MicrosoftDotNetApiCompatVersion>7.0.0-beta.22154.3</MicrosoftDotNetApiCompatVersion>
<MicrosoftDotNetCodeAnalysisVersion>6.0.0-beta.21271.1</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftCodeAnalysisCSharpCodeStyleVersion>3.10.0-2.final</MicrosoftCodeAnalysisCSharpCodeStyleVersion>
<MicrosoftCodeAnalysisVersion>3.10.0-2.final</MicrosoftCodeAnalysisVersion>
<MicrosoftCodeAnalysisVersion>4.0.1</MicrosoftCodeAnalysisVersion>
<MicrosoftCodeAnalysisCSharpAnalyzerTestingXunitVersion>1.0.1-beta1.*</MicrosoftCodeAnalysisCSharpAnalyzerTestingXunitVersion>
<MicrosoftCodeAnalysisBannedApiAnalyzersVersion>3.3.2</MicrosoftCodeAnalysisBannedApiAnalyzersVersion>
<!-- This controls the version of the cecil package, or the version of cecil in the project graph
Expand Down
12 changes: 12 additions & 0 deletions test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ public override void VisitLocalFunctionStatement (LocalFunctionStatementSyntax n
ValidateDiagnostics (node, node.AttributeLists);
}

public override void VisitSimpleLambdaExpression (SimpleLambdaExpressionSyntax node)
{
base.VisitSimpleLambdaExpression (node);
ValidateDiagnostics (node, node.AttributeLists);
}

public override void VisitParenthesizedLambdaExpression (ParenthesizedLambdaExpressionSyntax node)
{
base.VisitParenthesizedLambdaExpression (node);
ValidateDiagnostics (node, node.AttributeLists);
}

public override void VisitAccessorDeclaration (AccessorDeclarationSyntax node)
{
base.VisitAccessorDeclaration (node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,47 +564,47 @@ public static void Test ()

class WarnInLocalFunction
{
[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestCall ()
{
LocalFunction ();

[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
void LocalFunction () => MethodWithRequires ();
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestCallWithClosure (int p = 0)
{
LocalFunction ();

[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
void LocalFunction ()
{
p++;
MethodWithRequires ();
}
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
static void TestReflectionAccess ()
{
LocalFunction ();

[ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
void LocalFunction () => typeof (RequiresInCompilerGeneratedCode)
.GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic)
.Invoke (null, new object[] { });
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestLdftn ()
{
LocalFunction ();

[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
void LocalFunction ()
{
var action = new Action (MethodWithRequires);
Expand All @@ -626,11 +626,11 @@ void LocalFunction ()
}
}

[ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
static void TestDynamicallyAccessedMethod ()
{
LocalFunction ();

[ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods ();
}

Expand Down Expand Up @@ -910,41 +910,45 @@ public static void Test ()

class WarnInLambda
{
[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestCall ()
{
Action _ = () => MethodWithRequires ();
Action _ =
[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
() => MethodWithRequires ();
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestCallWithClosure (int p = 0)
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
() => {
p++;
MethodWithRequires ();
};
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
static void TestReflectionAccess ()
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
() => {
typeof (RequiresInCompilerGeneratedCode)
.GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic)
.Invoke (null, new object[] { });
};
}

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static void TestLdftn ()
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026", "--MethodWithRequires--")]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
() => {
var action = new Action (MethodWithRequires);
};
}
Expand All @@ -961,10 +965,11 @@ static void TestLazyDelegate ()
};
}

[ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
static void TestDynamicallyAccessedMethod ()
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
() => {
typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods ();
};
}
Expand All @@ -987,66 +992,70 @@ class SuppressInLambda

// C# 10 allows attributes on lambdas
// - This would be useful as a workaround for the limitation as Requires could be applied to the lambda directly
// - Would be useful for testing - have to use the CompilerGeneratedCode = true trick instead

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
static void TestCall ()
{
Action _ = () => MethodWithRequires ();
Action _ =
[ExpectedWarning ("IL2026")]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
() => MethodWithRequires ();
}

[ExpectedWarning ("IL2067", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
static void TestCallWithReflectionAnalysisWarning ()
{
// This should not produce warning because the Requires
Action<Type> _ = (t) => t.RequiresPublicMethods ();
Action<Type> _ =
[ExpectedWarning ("IL2067", ProducedBy = ProducedBy.Trimmer)]
(t) => t.RequiresPublicMethods ();
}

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
static void TestCallWithClosure (int p = 0)
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026")]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
() => {
p++;
MethodWithRequires ();
};
}

// 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")]
[RequiresDynamicCode ("Suppress in body")]
static void TestReflectionAccess ()
{
Action _ = () => {
Action _ =
// Analyzer doesn't recognize reflection access - so doesn't warn in this case
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => {
typeof (RequiresInCompilerGeneratedCode)
.GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic)
.Invoke (null, new object[] { });
};
}

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
static void TestLdftn ()
{
Action _ = () => {
Action _ =
[ExpectedWarning ("IL2026")]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
() => {
var action = new Action (MethodWithRequires);
};
}
Expand All @@ -1063,27 +1072,29 @@ static void TestLazyDelegate ()
};
}

// 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")]
[RequiresDynamicCode ("Suppress in body")]
static void TestDynamicallyAccessedMethod ()
{
Action _ = () => {
Action _ =
// Analyzer doesn't apply DAM - so won't see this warnings
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => {
typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods ();
};
}

// TODO: Fix the discrepancy between linker and analyzer
// /~https://github.com/dotnet/linker/issues/2350
[ExpectedWarning ("IL2077", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
static async void TestMethodParameterWithRequirements (Type unknownType = null)
{
Action _ = () => unknownType.RequiresNonPublicMethods ();
Action _ =
// TODO: Fix the discrepancy between linker and analyzer
// /~https://github.com/dotnet/linker/issues/2350
[ExpectedWarning ("IL2077", ProducedBy = ProducedBy.Trimmer)]
() => unknownType.RequiresNonPublicMethods ();
}

// The warning is currently not detected by roslyn analyzer since it doesn't analyze DAM yet
Expand Down Expand Up @@ -1130,15 +1141,15 @@ public static void Test ()

class WarnInComplex
{
[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
static async void TestIteratorLocalFunctionInAsync ()
{
await MethodAsync ();
LocalFunction ();
await MethodAsync ();

[ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
[ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
IEnumerable<int> LocalFunction ()
{
yield return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,57 +342,64 @@ public static void Test ()

class SuppressInLambda
{
// Suppression currently doesn't propagate to local functions
// Suppression currently doesn't propagate to lambdas

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
static void TestCallRUCMethod ()
{
Action _ = () => RequiresUnreferencedCodeMethod ();
Action _ =
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => RequiresUnreferencedCodeMethod ();
}

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
static void TestReflectionAccessRUCMethod ()
{
Action _ = () => typeof (SuppressWarningsInCompilerGeneratedCode)
Action _ =
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => typeof (SuppressWarningsInCompilerGeneratedCode)
.GetMethod ("RequiresUnreferencedCodeMethod", System.Reflection.BindingFlags.NonPublic)
.Invoke (null, new object[] { });
}

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
static void TestLdftnOnRUCMethod ()
{
Action _ = () => { var _ = new Action (RequiresUnreferencedCodeMethod); };
Action _ =
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => { var _ = new Action (RequiresUnreferencedCodeMethod); };
}

[ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
static void TestDynamicallyAccessedMethod ()
{
Action _ = () => typeof (TypeWithRUCMethod).RequiresNonPublicMethods ();
Action _ =
[ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer)]
() => typeof (TypeWithRUCMethod).RequiresNonPublicMethods ();
}

[ExpectedWarning ("IL2077", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2077")]
static void TestMethodParameterWithRequirements (Type unknownType = null)
{
Action _ = () => unknownType.RequiresNonPublicMethods ();
Action _ =
[ExpectedWarning ("IL2077", ProducedBy = ProducedBy.Trimmer)]
() => unknownType.RequiresNonPublicMethods ();
}

[ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2091")]
static void TestGenericMethodParameterRequirement<TUnknown> ()
{
Action _ = () => MethodWithGenericWhichRequiresMethods<TUnknown> ();
Action _ =
[ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer)]
() => MethodWithGenericWhichRequiresMethods<TUnknown> ();
}

[ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2091")]
static void TestGenericTypeParameterRequirement<TUnknown> ()
{
Action _ = () => new TypeWithGenericWhichRequiresNonPublicFields<TUnknown> ();
Action _ =
[ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer)]
() => new TypeWithGenericWhichRequiresNonPublicFields<TUnknown> ();
}

public static void Test ()
Expand Down
Loading

0 comments on commit 93eac59

Please sign in to comment.