diff options
author | Tlakaelel Axayakatl Ceja <tlakaelel.ceja@microsoft.com> | 2021-12-09 04:39:32 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-09 04:39:32 +0300 |
commit | c0163348df53e676c475dc7593cdedb9194da784 (patch) | |
tree | f01fbd4aef30c40a2018ec2737046a8f4d6549d4 /test | |
parent | 525aae9250d7b8ac198b04a53fb5eb8d3da8db34 (diff) |
Fix NullReferenceException in Analyzer (#2400)
* Don't check if the parent type has Requires if the member is already a TypeSymbol (fixes null ref)
* Change IsMemberInRequiresScope argument name from containingSymbol to member, since we call this function from several places and does not always contain the containingSymbol
* Add test for nullref
* Fail tests when analyzer throws an exception
Co-authored-by: Sven Boemer <sbomer@gmail.com>
Diffstat (limited to 'test')
5 files changed, 36 insertions, 14 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs index b54b65f8e..d2f8bf64d 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs @@ -409,5 +409,20 @@ class C return VerifyRequiresUnreferencedCodeAnalyzer (source); } + + [Fact] + public Task VerifyThatAnalysisOfFieldsDoesNotNullRef () + { + var source = @" +using System.Diagnostics.CodeAnalysis; + +[DynamicallyAccessedMembers (field)] +class C +{ + public const DynamicallyAccessedMemberTypes field = DynamicallyAccessedMemberTypes.PublicMethods; +}"; + + return VerifyRequiresUnreferencedCodeAnalyzer (source); + } } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs index 4c3db2687..edca78bfe 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs @@ -1,9 +1,10 @@ -// 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. using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -21,14 +22,14 @@ namespace ILLink.RoslynAnalyzer.Tests new RequiresAssemblyFilesAnalyzer (), new RequiresUnreferencedCodeAnalyzer ()); - public static Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel)> CreateCompilation ( + public static Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel, List<Diagnostic> ExceptionDiagnostics)> CreateCompilation ( string src, (string, string)[]? globalAnalyzerOptions = null, IEnumerable<MetadataReference>? additionalReferences = null, IEnumerable<SyntaxTree>? additionalSources = null) => CreateCompilation (CSharpSyntaxTree.ParseText (src), globalAnalyzerOptions, additionalReferences, additionalSources); - public static async Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel)> CreateCompilation ( + public static async Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel, List<Diagnostic> ExceptionDiagnostics)> CreateCompilation ( SyntaxTree src, (string, string)[]? globalAnalyzerOptions = null, IEnumerable<MetadataReference>? additionalReferences = null, @@ -48,18 +49,19 @@ namespace ILLink.RoslynAnalyzer.Tests ImmutableArray<AdditionalText>.Empty, new SimpleAnalyzerOptions (globalAnalyzerOptions)); + var exceptionDiagnostics = new List<Diagnostic> (); + var compWithAnalyzerOptions = new CompilationWithAnalyzersOptions ( analyzerOptions, - (_1, _2, _3) => { }, + (Exception exception, DiagnosticAnalyzer diagnosticAnalyzer, Diagnostic diagnostic) => { + exceptionDiagnostics.Add (diagnostic); + }, concurrentAnalysis: true, logAnalyzerExecutionTime: false); - return (new CompilationWithAnalyzers (comp, SupportedDiagnosticAnalyzers, compWithAnalyzerOptions), comp.GetSemanticModel (src)); + return (new CompilationWithAnalyzers (comp, SupportedDiagnosticAnalyzers, compWithAnalyzerOptions), comp.GetSemanticModel (src), exceptionDiagnostics); } - public static async Task<Compilation> GetCompilation (string source, IEnumerable<MetadataReference>? additionalReferences = null, IEnumerable<SyntaxTree>? additionalSources = null) - => (await CreateCompilation (source, additionalReferences: additionalReferences ?? Array.Empty<MetadataReference> ())).Compilation.Compilation; - class SimpleAnalyzerOptions : AnalyzerConfigOptionsProvider { public SimpleAnalyzerOptions ((string, string)[]? globalOptions) diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index 3cae7cdb7..194a1a96b 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -52,12 +52,16 @@ namespace ILLink.RoslynAnalyzer.Tests var testDependenciesSource = GetTestDependencies (rootSourceDir, tree) .Select (f => SyntaxFactory.ParseSyntaxTree (SourceText.From (File.OpenRead (f)))); - var (comp, model) = await TestCaseCompilation.CreateCompilation ( + + var (comp, model, exceptionDiagnostics) = await TestCaseCompilation.CreateCompilation ( tree, msbuildProperties, additionalSources: testDependenciesSource); - var diags = await comp.GetAnalyzerDiagnosticsAsync (); + // Note that the exception diagnostics will be empty until the analyzer has run, + // so be sure to get them after awaiting GetAnalyzerDiagnosticsAsync(). + var diags = (await comp.GetAnalyzerDiagnosticsAsync ()).AddRange (exceptionDiagnostics); + var testChecker = new TestChecker ((CSharpSyntaxTree) tree, model, diags); testChecker.Check (); } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs index e7af1b930..56b5c1e72 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs @@ -33,8 +33,8 @@ namespace ILLink.RoslynAnalyzer.Tests _tree = tree; _semanticModel = semanticModel; _diagnostics = diagnostics - // Filter down to diagnostics which originate from this tree - .Where (d => d.Location.SourceTree == tree).ToList (); + // Filter down to diagnostics which originate from this tree or have no location + .Where (d => d.Location.SourceTree == tree || d.Location.SourceTree == null).ToList (); // Filled in later _unmatched = new List<Diagnostic> (); diff --git a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs index 5afc179b8..79800c3f8 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -37,7 +37,8 @@ namespace ILLink.RoslynAnalyzer.Tests /// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/> public static async Task VerifyAnalyzerAsync (string src, (string, string)[]? analyzerOptions = null, IEnumerable<MetadataReference>? additionalReferences = null, params DiagnosticResult[] expected) { - var diags = await (await TestCaseCompilation.CreateCompilation (src, analyzerOptions, additionalReferences)).Compilation.GetAllDiagnosticsAsync (); + var (comp, _, exceptionDiagnostics) = await TestCaseCompilation.CreateCompilation (src, analyzerOptions, additionalReferences); + var diags = (await comp.GetAllDiagnosticsAsync ()).AddRange (exceptionDiagnostics); var analyzers = ImmutableArray.Create<DiagnosticAnalyzer> (new TAnalyzer ()); VerifyDiagnosticResults (diags, analyzers, expected, DefaultVerifier); } |