public void TestCancellationDuringSuppressorExecution(bool concurrent)
        {
            string source      = @"class C1 { }";
            var    options     = TestOptions.DebugDll.WithConcurrentBuild(concurrent);
            var    compilation = CreateCompilation(source, options: options);

            compilation.VerifyDiagnostics();

            var analyzer = new CompilationAnalyzerWithSeverity(
                DiagnosticSeverity.Warning,
                configurable: true
                );
            var expectedDiagnostic = Diagnostic(analyzer.Descriptor.Id, source);

            VerifyAnalyzerDiagnostics(
                compilation,
                new DiagnosticAnalyzer[] { analyzer },
                expectedDiagnostic
                );

            var suppressor = new DiagnosticSuppressorForId_ThrowsOperationCancelledException(
                analyzer.Descriptor.Id
                );
            var cancellationToken       = suppressor.CancellationTokenSource.Token;
            var analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor };

            Assert.Throws <OperationCanceledException>(
                () =>
                compilation.GetAnalyzerDiagnostics(
                    analyzersAndSuppressors,
                    reportSuppressedDiagnostics: true,
                    cancellationToken: cancellationToken
                    )
                );
        }
Example #2
0
        public void TestNonReportedDiagnosticCannotBeSuppressed()
        {
            string source      = @"
class C { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            const string nonReportedDiagnosticId = "NonReportedId";
            var          analyzer   = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);
            var          suppressor = new DiagnosticSuppressor_NonReportedDiagnosticCannotBeSuppressed(analyzer.Descriptor.Id, nonReportedDiagnosticId);
            var          analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor };

            // "Non-reported diagnostic with ID '{0}' cannot be suppressed."
            var exceptionMessage = string.Format(CodeAnalysisResources.NonReportedDiagnosticCannotBeSuppressed, nonReportedDiagnosticId);

            VerifyAnalyzerDiagnostics(compilation, analyzersAndSuppressors,
                                      Diagnostic("AD0001").WithArguments(suppressor.ToString(),
                                                                         typeof(System.ArgumentException).FullName,
                                                                         exceptionMessage)
                                      .WithLocation(1, 1),
                                      Diagnostic("ID1000", "class C { }").WithLocation(2, 1));

            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors);
        }
Example #3
0
        public void TestInvalidDiagnosticSuppressionReported()
        {
            string source      = @"
class C { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            const string unsupportedSuppressedId = "UnsupportedId";
            var          analyzer               = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);
            var          suppressor             = new DiagnosticSuppressor_InvalidDiagnosticSuppressionReported(analyzer.Descriptor.Id, unsupportedSuppressedId);
            var          analyzersAndSuppresors = new DiagnosticAnalyzer[] { analyzer, suppressor };

            // "Suppressed diagnostic ID '{0}' does not match suppressable ID '{1}' for the given suppression descriptor."
            var exceptionMessage = string.Format(CodeAnalysisResources.InvalidDiagnosticSuppressionReported, analyzer.Descriptor.Id, unsupportedSuppressedId);

            VerifyAnalyzerDiagnostics(compilation, analyzersAndSuppresors,
                                      Diagnostic("AD0001").WithArguments(suppressor.ToString(),
                                                                         typeof(System.ArgumentException).FullName,
                                                                         exceptionMessage)
                                      .WithLocation(1, 1),
                                      Diagnostic("ID1000", "class C { }").WithLocation(2, 1));

            VerifySuppressedDiagnostics(compilation, analyzersAndSuppresors);
        }
Example #4
0
        public void TestExceptionFromSuppressor()
        {
            string source = @"
class C { }";

            var compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var analyzer = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);

            testCore(new DiagnosticSuppressorThrowsExceptionFromSupportedSuppressions());
            testCore(new DiagnosticSuppressorThrowsExceptionFromReportedSuppressions(analyzer.Descriptor.Id));
            return;

            // Local functions.
            void testCore(DiagnosticSuppressor suppressor)
            {
                var analyzersAndSuppresors = new DiagnosticAnalyzer[] { analyzer, suppressor };

                VerifyAnalyzerDiagnostics(compilation, analyzersAndSuppresors,
                                          Diagnostic("AD0001").WithArguments(suppressor.ToString(),
                                                                             typeof(NotImplementedException).FullName,
                                                                             new NotImplementedException().Message)
                                          .WithLocation(1, 1),
                                          Diagnostic("ID1000", "class C { }").WithLocation(2, 1));

                VerifySuppressedDiagnostics(compilation, analyzersAndSuppresors);
            }
        }
        public void TestSuppression_MultipleSuppressors_DifferentDiagnostic()
        {
            string source      = @"class C1 { private readonly int f; }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics(
                // (1,33): warning CS0169: The field 'C1.f' is never used
                // class C1 { private readonly int f; }
                Diagnostic(ErrorCode.WRN_UnreferencedField, "f").WithArguments("C1.f").WithLocation(1, 33));

            var analyzer = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);

            VerifyAnalyzerDiagnostics(compilation, new DiagnosticAnalyzer[] { analyzer },
                                      Diagnostic(analyzer.Descriptor.Id, source));

            var suppressor1 = new DiagnosticSuppressorForId("CS0169");
            var suppressor2 = new DiagnosticSuppressorForId(analyzer.Descriptor.Id);

            var analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor1, suppressor2 };

            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors,
                                        Diagnostic("CS0169", "f", isSuppressed: true).WithArguments("C1.f").WithLocation(1, 33),
                                        Diagnostic(analyzer.Descriptor.Id, source, isSuppressed: true));

            VerifySuppressedAndFilteredDiagnostics(compilation, analyzersAndSuppressors);
        }
        public void TestSuppression_MultipleDiagnostics()
        {
            string source1     = @"class C1 { }";
            string source2     = @"class C2 { }";
            var    compilation = CreateCompilation(new[] { source1, source2 });

            compilation.VerifyDiagnostics();

            var analyzer            = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);
            var expectedDiagnostics = new DiagnosticDescription[] {
                Diagnostic(analyzer.Descriptor.Id, source1, isSuppressed: false).WithLocation(1, 1),
                Diagnostic(analyzer.Descriptor.Id, source2, isSuppressed: false).WithLocation(1, 1),
            };

            VerifyAnalyzerDiagnostics(compilation, new DiagnosticAnalyzer[] { analyzer }, expectedDiagnostics);

            var analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, new DiagnosticSuppressorForId(analyzer.Descriptor.Id) };

            expectedDiagnostics = new DiagnosticDescription[] {
                Diagnostic(analyzer.Descriptor.Id, source1, isSuppressed: true).WithLocation(1, 1),
                Diagnostic(analyzer.Descriptor.Id, source2, isSuppressed: true).WithLocation(1, 1),
            };
            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors, expectedDiagnostics);
            VerifySuppressedAndFilteredDiagnostics(compilation, analyzersAndSuppressors);
        }
        public void TestExceptionFromSuppressor()
        {
            string source = "class C { }";

            var compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var expectedException = new NotImplementedException();
            var analyzer          = new CompilationAnalyzerWithSeverity(
                DiagnosticSeverity.Warning,
                configurable: true
                );
            var suppressor = new DiagnosticSuppressorThrowsExceptionFromReportedSuppressions(
                analyzer.Descriptor.Id,
                expectedException
                );
            var exceptions = new List <Exception>();
            EventHandler <FirstChanceExceptionEventArgs> firstChanceException = (sender, e) =>
            {
                if (e.Exception == expectedException)
                {
                    exceptions.Add(e.Exception);
                }
            };

            try
            {
                AppDomain.CurrentDomain.FirstChanceException += firstChanceException;

                IFormattable context =
                    $@"{string.Format(CodeAnalysisResources.ExceptionContext, $@"Compilation: {compilation.AssemblyName}")}

{new LazyToString(() => exceptions[0])}
-----";
                var analyzersAndSuppresors = new DiagnosticAnalyzer[] { analyzer, suppressor };
                VerifyAnalyzerDiagnostics(
                    compilation,
                    analyzersAndSuppresors,
                    Diagnostic("AD0001")
                    .WithArguments(
                        suppressor.ToString(),
                        typeof(NotImplementedException).FullName,
                        new NotImplementedException().Message,
                        context
                        )
                    .WithLocation(1, 1),
                    Diagnostic("ID1000", "class C { }").WithLocation(1, 1)
                    );

                VerifySuppressedDiagnostics(compilation, analyzersAndSuppresors);
            }
            finally
            {
                AppDomain.CurrentDomain.FirstChanceException -= firstChanceException;
            }
        }
Example #8
0
        public void TestSuppression_AnalyzerDiagnostics_SeveritiesAndConfigurableMatrix()
        {
            string source      = @"
class C { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var configurations = new[] { false, true };
            var severities     = Enum.GetValues(typeof(DiagnosticSeverity));
            var originalSpecificDiagnosticOptions = compilation.Options.SpecificDiagnosticOptions;

            foreach (var configurable in configurations)
            {
                foreach (DiagnosticSeverity defaultSeverity in severities)
                {
                    foreach (DiagnosticSeverity effectiveSeverity in severities)
                    {
                        var diagnostic = Diagnostic("ID1000", "class C { }")
                                         .WithLocation(2, 1)
                                         .WithDefaultSeverity(defaultSeverity)
                                         .WithEffectiveSeverity(configurable ? effectiveSeverity : defaultSeverity);

                        if (defaultSeverity == DiagnosticSeverity.Warning &&
                            effectiveSeverity == DiagnosticSeverity.Error &&
                            configurable)
                        {
                            diagnostic = diagnostic.WithWarningAsError(true);
                        }

                        var analyzer   = new CompilationAnalyzerWithSeverity(defaultSeverity, configurable);
                        var suppressor = new DiagnosticSuppressorForId(analyzer.Descriptor.Id);
                        var analyzersWithoutSuppressor = new DiagnosticAnalyzer[] { analyzer };
                        var analyzersWithSuppressor    = new DiagnosticAnalyzer[] { analyzer, suppressor };

                        var specificDiagnosticOptions = originalSpecificDiagnosticOptions.Add(
                            key: analyzer.Descriptor.Id,
                            value: DiagnosticDescriptor.MapSeverityToReport(effectiveSeverity));
                        compilation = compilation.WithOptions(compilation.Options.WithSpecificDiagnosticOptions(specificDiagnosticOptions));

                        // Verify analyzer diagnostic without suppressor, also verify no suppressions.
                        VerifyAnalyzerDiagnostics(compilation, analyzersWithoutSuppressor, diagnostic);
                        VerifySuppressedDiagnostics(compilation, analyzersWithoutSuppressor);

                        // Verify suppressed analyzer diagnostic, except when default severity is Error or diagnostic is not-configurable.
                        if (defaultSeverity == DiagnosticSeverity.Error || !configurable)
                        {
                            VerifySuppressedDiagnostics(compilation, analyzersWithSuppressor);
                        }
                        else
                        {
                            VerifySuppressedDiagnostics(compilation, analyzersWithSuppressor, diagnostic);
                        }
                    }
                }
            }
        }
        public void TestUnsupportedSuppressionReported()
        {
            string source = @"
class C { }";

            var compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            const string supportedSuppressionId   = "supportedId";
            const string unsupportedSuppressionId = "unsupportedId";
            var          analyzer   = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);
            var          suppressor = new DiagnosticSuppressor_UnsupportedSuppressionReported(analyzer.Descriptor.Id, supportedSuppressionId, unsupportedSuppressionId);
            var          analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor };

            // "Reported suppression with ID '{0}' is not supported by the suppressor."
            var exceptionMessage = string.Format(CodeAnalysisResources.UnsupportedSuppressionReported, unsupportedSuppressionId);

            var exceptions = new List <Exception>();
            EventHandler <FirstChanceExceptionEventArgs> firstChanceException =
                (sender, e) =>
            {
                if (e.Exception is ArgumentException &&
                    e.Exception.Message == exceptionMessage)
                {
                    exceptions.Add(e.Exception);
                }
            };

            try
            {
                AppDomain.CurrentDomain.FirstChanceException += firstChanceException;

                IFormattable context = $@"{string.Format(CodeAnalysisResources.ExceptionContext, $@"Compilation: {compilation.AssemblyName}")}

{new LazyToString(() => exceptions[0])}
-----";
                VerifyAnalyzerDiagnostics(compilation, analyzersAndSuppressors,
                                          Diagnostic("AD0001").WithArguments(suppressor.ToString(),
                                                                             typeof(ArgumentException).FullName,
                                                                             exceptionMessage,
                                                                             context)
                                          .WithLocation(1, 1),
                                          Diagnostic("ID1000", "class C { }").WithLocation(2, 1));

                VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors);
            }
            finally
            {
                AppDomain.CurrentDomain.FirstChanceException -= firstChanceException;
            }
        }
Example #10
0
        public void TestNoSuppression_SpecificOptionsTurnsOffSuppressor()
        {
            string source      = @"class C1 { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var analyzer = new CompilationAnalyzerWithSeverity(
                DiagnosticSeverity.Warning,
                configurable: true
                );
            var expectedDiagnostic = Diagnostic(
                analyzer.Descriptor.Id,
                source,
                isSuppressed: false
                );

            VerifyAnalyzerDiagnostics(
                compilation,
                new DiagnosticAnalyzer[] { analyzer },
                expectedDiagnostic
                );

            const string suppressionId           = "SPR1001";
            var          analyzersAndSuppressors = new DiagnosticAnalyzer[]
            {
                analyzer,
                new DiagnosticSuppressorForId(analyzer.Descriptor.Id, suppressionId)
            };

            expectedDiagnostic = Diagnostic(analyzer.Descriptor.Id, source, isSuppressed: true);
            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors, expectedDiagnostic);

            var specificDiagnosticOptions = compilation.Options.SpecificDiagnosticOptions.Add(
                suppressionId,
                ReportDiagnostic.Suppress
                );

            compilation = compilation.WithOptions(
                compilation.Options.WithSpecificDiagnosticOptions(specificDiagnosticOptions)
                );
            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors);
        }
Example #11
0
        public void TestSuppression_MultipleSuppressors_SameDiagnostic()
        {
            string source      = @"class C1 { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var analyzer = new CompilationAnalyzerWithSeverity(
                DiagnosticSeverity.Warning,
                configurable: true
                );
            var expectedDiagnostic = Diagnostic(analyzer.Descriptor.Id, source, isSuppressed: false)
                                     .WithLocation(1, 1);

            VerifyAnalyzerDiagnostics(
                compilation,
                new DiagnosticAnalyzer[] { analyzer },
                expectedDiagnostic
                );

            // Multiple suppressors with same suppression ID.
            expectedDiagnostic = Diagnostic(analyzer.Descriptor.Id, source, isSuppressed: true)
                                 .WithLocation(1, 1);
            var analyzersAndSuppressors = new DiagnosticAnalyzer[]
            {
                analyzer,
                new DiagnosticSuppressorForId(analyzer.Descriptor.Id),
                new DiagnosticSuppressorForId(analyzer.Descriptor.Id)
            };

            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors, expectedDiagnostic);

            // Multiple suppressors with different suppression ID.
            analyzersAndSuppressors = new DiagnosticAnalyzer[]
            {
                analyzer,
                new DiagnosticSuppressorForId(analyzer.Descriptor.Id, suppressionId: "SPR0001"),
                new DiagnosticSuppressorForId(analyzer.Descriptor.Id, suppressionId: "SPR0002")
            };
            VerifySuppressedDiagnostics(compilation, analyzersAndSuppressors, expectedDiagnostic);
        }
        public void TestProgrammaticSuppressionInfo_DiagnosticSuppressor()
        {
            string source      = @"class C1 { }";
            var    compilation = CreateCompilation(source);

            compilation.VerifyDiagnostics();

            var analyzer           = new CompilationAnalyzerWithSeverity(DiagnosticSeverity.Warning, configurable: true);
            var expectedDiagnostic = Diagnostic(analyzer.Descriptor.Id, source);

            VerifyAnalyzerDiagnostics(compilation, new DiagnosticAnalyzer[] { analyzer }, expectedDiagnostic);

            const string suppressionId           = "SPR1001";
            var          suppressor              = new DiagnosticSuppressorForId(analyzer.Descriptor.Id, suppressionId);
            var          analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor };
            var          diagnostics             = compilation.GetAnalyzerDiagnostics(analyzersAndSuppressors, reportSuppressedDiagnostics: true);

            Assert.Single(diagnostics);
            var suppressionInfo = diagnostics.Select(d => d.ProgrammaticSuppressionInfo).Single().Suppressions.Single();

            Assert.Equal(suppressionId, suppressionInfo.Id);
            Assert.Equal(suppressor.SuppressionDescriptor.Justification, suppressionInfo.Justification);

            const string suppressionId2 = "SPR1002";
            var          suppressor2    = new DiagnosticSuppressorForId(analyzer.Descriptor.Id, suppressionId2);

            analyzersAndSuppressors = new DiagnosticAnalyzer[] { analyzer, suppressor, suppressor2 };
            diagnostics             = compilation.GetAnalyzerDiagnostics(analyzersAndSuppressors, reportSuppressedDiagnostics: true);
            Assert.Single(diagnostics);
            var programmaticSuppression = diagnostics.Select(d => d.ProgrammaticSuppressionInfo).Single();

            Assert.Equal(2, programmaticSuppression.Suppressions.Count);
            var orderedSuppressions = programmaticSuppression.Suppressions.Order().ToImmutableArrayOrEmpty();

            Assert.Equal(suppressionId, orderedSuppressions[0].Id);
            Assert.Equal(suppressor.SuppressionDescriptor.Justification, orderedSuppressions[0].Justification);
            Assert.Equal(suppressionId2, orderedSuppressions[1].Id);
            Assert.Equal(suppressor2.SuppressionDescriptor.Justification, orderedSuppressions[1].Justification);
        }