Пример #1
0
        protected void VerifyFix(string language, IDiagnosticAnalyzer analyzer, ICodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics)
        {
            var document = CreateDocument(oldSource, language);

            VerifyFix(document, analyzer, codeFixProvider, newSource, codeFixIndex, useCompilerAnalyzerDriver: true, allowNewCompilerDiagnostics: allowNewCompilerDiagnostics);
            VerifyFix(document, analyzer, codeFixProvider, newSource, codeFixIndex, useCompilerAnalyzerDriver: false, allowNewCompilerDiagnostics: allowNewCompilerDiagnostics);
        }
        private static void VerifyDiagnosticLocation(IDiagnosticAnalyzer analyzer, Diagnostic diagnostic, Location actual, DiagnosticResultLocation expected)
        {
            var actualSpan = actual.GetLineSpan();

            Assert.True(actualSpan.Path == expected.Path || (actualSpan.Path != null && actualSpan.Path.Contains("Test0.") && expected.Path.Contains("Test.")),
                string.Format("Expected diagnostic to be in file \"{0}\" was actually in file \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                    expected.Path, actualSpan.Path, FormatDiagnostics(analyzer, diagnostic)));

            var actualLinePosition = actualSpan.StartLinePosition;

            // Only check line position if there is an actual line in the real diagnostic
            if (actualLinePosition.Line > 0)
            {
                if (actualLinePosition.Line + 1 != expected.Line)
                {
                    Assert.True(false,
                        string.Format("Expected diagnostic to be on line \"{0}\" was actually on line \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                            expected.Line, actualLinePosition.Line + 1, FormatDiagnostics(analyzer, diagnostic)));
                }
            }

            // Only check column position if there is an actual column position in the real diagnostic
            if (actualLinePosition.Character > 0)
            {
                if (actualLinePosition.Character + 1 != expected.Column)
                {
                    Assert.True(false,
                        string.Format("Expected diagnostic to start at column \"{0}\" was actually at column \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                            expected.Column, actualLinePosition.Character + 1, FormatDiagnostics(analyzer, diagnostic)));
                }
            }
        }
Пример #3
0
        private void VerifyFix(Document document, IDiagnosticAnalyzer analyzer, ICodeFixProvider codeFixProvider, string newSource, int? codeFixIndex, bool useCompilerAnalyzerDriver, bool allowNewCompilerDiagnostics)
        {
            var analyzerDiagnostics = GetSortedDiagnostics(analyzer, document, useCompilerAnalyzerDriver: useCompilerAnalyzerDriver);
            var compilerDiagnostics = document.GetSemanticModelAsync().Result.GetDiagnostics();

            // TODO(mavasani): Delete the below if statement once FxCop Analyzers have been ported to new IDiagnosticAnalyzer API.
            if (!useCompilerAnalyzerDriver)
            {
                Assert.True(analyzerDiagnostics.IsEmpty());
                return;
            }

            var attempts = analyzerDiagnostics.Length;

            for (int i = 0; i < attempts; ++i)
            {
                var actions = codeFixProvider.GetFixesAsync(document, analyzerDiagnostics[0].Location.SourceSpan, analyzerDiagnostics, CancellationToken.None).Result;
                if (!actions.Any())
                {
                    break;
                }

                if (codeFixIndex != null)
                {
                    document = document.Apply(actions.ElementAt((int)codeFixIndex));
                    break;
                }

                document = document.Apply(actions.ElementAt(0));
                
                analyzerDiagnostics = GetSortedDiagnostics(analyzer, document, useCompilerAnalyzerDriver: useCompilerAnalyzerDriver);
                var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, document.GetSemanticModelAsync().Result.GetDiagnostics());
                if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any())
                {
                    // Format and get the compiler diagnostics again so that the locations make sense in the output
                    document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace));
                    newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, document.GetSemanticModelAsync().Result.GetDiagnostics());

                    Assert.True(false,
                        string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
                            newCompilerDiagnostics.Select(d => d.ToString()).Join("\r\n"),
                            document.GetSyntaxRootAsync().Result.ToFullString()));
                }

                if (analyzerDiagnostics.IsEmpty())
                {
                    break;
                }
            }

            var newDocument = Simplifier.ReduceAsync(document, Simplifier.Annotation).Result;
            var root = newDocument.GetSyntaxRootAsync().Result;
            root = Formatter.Format(root, Formatter.Annotation, newDocument.Project.Solution.Workspace);
            var actual = root.GetText().ToString();
            Assert.Equal(newSource, actual);
        }
        /// <summary>
        /// General verifier for codefixes.
        /// Creates a Document from the source string, then gets diagnostics on it and applies the relevant codefixes.
        /// Then gets the string after the codefix is applied and compares it with the expected result.
        /// Note: If any codefix causes new diagnostics to show up, the test fails unless allowNewCompilerDiagnostics is set to true.
        /// </summary>
        /// <param name="language">The language the source code is in</param>
        /// <param name="analyzer">The analyzer to be applied to the source code</param>
        /// <param name="codeFixProvider">The codefix to be applied to the code wherever the relevant Diagnostic is found</param>
        /// <param name="oldSource">A class in the form of a string before the CodeFix was applied to it</param>
        /// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
        /// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
        /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
        private void VerifyFix(string language, IDiagnosticAnalyzer analyzer, ICodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics)
        {

            var document = CreateDocument(oldSource, language);
            var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });
            var compilerDiagnostics = GetCompilerDiagnostics(document);
            var attempts = analyzerDiagnostics.Length;

            for (int i = 0; i < attempts; ++i)
            {
                var actions = codeFixProvider.GetFixesAsync(document, analyzerDiagnostics[0].Location.SourceSpan, analyzerDiagnostics, CancellationToken.None).Result;
                if (!actions.Any())
                {
                    break;
                }

                if (codeFixIndex != null)
                {
                    document = ApplyFix(document, actions.ElementAt((int)codeFixIndex));
                    break;
                }

                document = ApplyFix(document, actions.ElementAt(0));
                analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });

                var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));

                //check if applying the code fix introduced any new compiler diagnostics
                if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any())
                {
                    // Format and get the compiler diagnostics again so that the locations make sense in the output
                    document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace));
                    newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));

                    Assert.IsTrue(false,
                        string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
                            string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())),
                            document.GetSyntaxRootAsync().Result.ToFullString()));
                }

                //check if there are analyzer diagnostics left after the code fix
                if (!analyzerDiagnostics.Any())
                {
                    break;
                }
            }

            //after applying all of the code fixes, compare the resulting string to the inputted one
            var actual = GetStringFromDocument(document);
            Assert.AreEqual(newSource, actual);
        }
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
        protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(IDiagnosticAnalyzer analyzer, Document[] documents)
        {
            var projects = new HashSet<Project>();
            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List<Diagnostic>();
            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().GetAwaiter().GetResult();

                var driver = GetAnalyzerDriver(analyzer, compilation.Language);

                compilation = compilation.WithEventQueue(driver.CompilationEventQueue);
                var discarded = compilation.GetDiagnostics();
                var diags = driver.GetDiagnosticsAsync().GetAwaiter().GetResult();
                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree = document.GetSyntaxTreeAsync().GetAwaiter().GetResult();
                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(diagnostics);
            diagnostics.Clear();
            return results;
        }
Пример #6
0
 private static void ExecuteAndCatchIfThrows(IDiagnosticAnalyzer a, Action <Diagnostic> addDiagnostic, bool continueOnError, CancellationToken cancellationToken, Action analyze)
 {
     try
     {
         analyze();
     }
     catch (OperationCanceledException oce) if (continueOnError)
         {
             if (oce.CancellationToken != cancellationToken)
             {
                 // Create a info diagnostic saying that the analyzer failed
                 addDiagnostic(GetAnalyzerDiagnostic(a, oce));
             }
         }
     catch (Exception e) if (continueOnError)
         {
             // Create a info diagnostic saying that the analyzer failed
             addDiagnostic(GetAnalyzerDiagnostic(a, e));
         }
 }
Пример #7
0
        public static void Verify(string path, IDiagnosticAnalyzer diagnosticAnalyzer)
        {
            var runner = new DiagnosticsRunner(ImmutableArray.Create(diagnosticAnalyzer));

            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(path, Encoding.UTF8));

            List <int> expected = new List <int>(ExpectedIssues(syntaxTree));

            foreach (var diagnostic in runner.GetDiagnostics(syntaxTree))
            {
                if (diagnostic.Id == diagnosticAnalyzer.SupportedDiagnostics.Single().Id)
                {
                    int line = diagnostic.Location.GetLineSpan().StartLinePosition.Line + 1;
                    expected.Should().Contain(line);
                    expected.Remove(line);
                }
            }

            expected.Should().BeEquivalentTo(Enumerable.Empty <int>());
        }
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <param name="spans">Optional TextSpan indicating where a Diagnostic will be found</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns>
        protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(IDiagnosticAnalyzer analyzer, Document[] documents)
        {
            var projects = new HashSet<Project>();
            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List<Diagnostic>();
            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().Result;
                var driver = new AnalyzerDriver<SyntaxKind>((new[] { analyzer }).ToImmutableArray(), n => n.CSharpKind(), null, CancellationToken.None);
                compilation = compilation.WithEventQueue(driver.CompilationEventQueue);
                var discarded = compilation.GetDiagnostics();
                var diags = driver.GetDiagnosticsAsync().Result;
                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree = document.GetSyntaxTreeAsync().Result;
                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(diagnostics);
            diagnostics.Clear();
            return results;
        }
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <param name="spans">Optional TextSpan indicating where a Diagnostic will be found</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns>
        protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(IDiagnosticAnalyzer analyzer, Document[] documents)
        {
            var projects = new HashSet <Project>();

            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List <Diagnostic>();

            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().Result;
                var diags       = AnalyzerDriver.GetDiagnostics(compilation, new[] { analyzer }, null, CancellationToken.None);
                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree     = document.GetSyntaxTreeAsync().Result;
                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(diagnostics);

            diagnostics.Clear();
            return(results);
        }
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <param name="spans">Optional TextSpan indicating where a Diagnostic will be found</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns>
        protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(IDiagnosticAnalyzer analyzer, Document[] documents)
        {
            var projects = new HashSet<Project>();
            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List<Diagnostic>();
            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().Result;
                var diags = AnalyzerDriver.GetDiagnostics(compilation, new[] { analyzer }, null, CancellationToken.None);
                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree = document.GetSyntaxTreeAsync().Result;
                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(diagnostics);
            diagnostics.Clear();
            return results;
        }
Пример #11
0
        /// <summary>
        /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options.
        /// </summary>
        private static bool IsDiagnosticAnalyzerSuppressed(IDiagnosticAnalyzer analyzer, CompilationOptions options, Action <Diagnostic> addDiagnostic, bool continueOnError, CancellationToken cancellationToken)
        {
            var supportedDiagnostics = ImmutableArray <DiagnosticDescriptor> .Empty;

            // Catch Exception from analyzer.SupportedDiagnostics
            ExecuteAndCatchIfThrows(analyzer, addDiagnostic, continueOnError, cancellationToken, () => { supportedDiagnostics = analyzer.SupportedDiagnostics; });

            var diagnosticOptions = options.SpecificDiagnosticOptions;

            foreach (var diag in supportedDiagnostics)
            {
                if (diagnosticOptions.ContainsKey(diag.Id) && diagnosticOptions[diag.Id] == ReportDiagnostic.Suppress)
                {
                    continue;
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #12
0
 protected static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, IDiagnosticAnalyzer analyzer)
 {
     var documentsAndUseSpan = GetDocumentsAndSpans(sources, language);
     var documents = documentsAndUseSpan.Item1;
     var useSpans = documentsAndUseSpan.Item2;
     var spans = documentsAndUseSpan.Item3;
     return GetSortedDiagnostics(analyzer, documents, useSpans ? spans : null);
 }
Пример #13
0
        private static IEnumerable<Diagnostic> GetDiagnosticsUsingIDEAnalyzerDriver(IDiagnosticAnalyzer analyzer, Document document, TextSpan? span)
        {
            // TODO(mavasani): Uncomment the below code once FxCop Analyzers have been ported to new IDiagnosticAnalyzer API.

            ////return includeProjectDiagnostics ?
            ////    DiagnosticProviderTestUtilities.GetAllDiagnostics(analyzerFactory, document, span) :
            ////    DiagnosticProviderTestUtilities.GetDocumentDiagnostics(analyzerFactory, document, span);

            return SpecializedCollections.EmptyEnumerable<Diagnostic>();
        }
Пример #14
0
 protected void Verify(string[] sources, string language, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
 {
     GetSortedDiagnostics(sources, language, analyzer).Verify(analyzer, expected);
 }
Пример #15
0
 protected void Verify(string[] sources, string language, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
 {
     GetSortedDiagnostics(sources, language, analyzer).Verify(analyzer, expected);
 }
Пример #16
0
 protected static Diagnostic[] GetSortedDiagnostics(IDiagnosticAnalyzer analyzer, Document document, TextSpan?[] spans = null)
 {
     return(GetSortedDiagnostics(analyzer, new[] { document }, spans));
 }
Пример #17
0
        private static void AnalyzeDocument(IDiagnosticAnalyzer analyzer, Document document, Action<Diagnostic> addDiagnostic, TextSpan? span = null)
        {
            Assert.True(analyzer.GetType().IsDefined(typeof(ExportDiagnosticAnalyzerAttribute)), "Top-level analyzers should have the ExportDiagnosticAnalyzerAttribute");
            Assert.True(analyzer.GetType().IsDefined(typeof(DiagnosticAnalyzerAttribute)), "Top-level analyzers should have the DiagnosticAnalyzerAttribute");

            AnalyzeDocumentCore(analyzer, document, addDiagnostic, span);
        }
Пример #18
0
 /// <summary>
 /// Given classes in the form of strings, their language, and an IDiagnosticAnlayzer to apply to it, return the diagnostics found in the string after converting it to a document.
 /// </summary>
 /// <param name="sources">Classes in the form of strings</param>
 /// <param name="language">The language the soruce classes are in</param>
 /// <param name="analyzer">The analyzer to be run on the sources</param>
 /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns>
 private static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, IDiagnosticAnalyzer analyzer)
 {
     return(GetSortedDiagnosticsFromDocuments(analyzer, GetDocuments(sources, language)));
 }
Пример #19
0
 private static Diagnostic GetAnalyzerDiagnostic(IDiagnosticAnalyzer analyzer, Exception e)
 {
     return(Diagnostic.Create(GetDiagnosticDescriptor(analyzer.GetType().ToString(), e.Message), Location.None));
 }
 protected void VerifyBasic(string source, string rootNamespace, IDiagnosticAnalyzer[] analyzers, params DiagnosticDescription[] diagnostics)
 {
     Assert.False(string.IsNullOrWhiteSpace(rootNamespace), string.Format("Invalid root namespace '{0}'", rootNamespace));
     Verify(source, LanguageNames.VisualBasic, analyzers, diagnostics, rootNamespace);
 }
Пример #21
0
        private static Diagnostic[] GetSortedDiagnostics(IDiagnosticAnalyzer analyzerFactory, Document document, bool useCompilerAnalyzerDriver, TextSpan? span = null)
        {
            TextSpan spanToTest = span.HasValue ? span.Value : document.GetSyntaxRootAsync().Result.FullSpan;

            var diagnostics = useCompilerAnalyzerDriver ?
                GetDiagnosticsUsingCompilerAnalyzerDriver(analyzerFactory, document, span) :
                GetDiagnosticsUsingIDEAnalyzerDriver(analyzerFactory, document, span);

            return GetSortedDiagnostics(diagnostics);
        }
        /// <summary>
        /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options.
        /// <paramref name="continueOnAnalyzerException"/> says whether the caller would like the exception thrown by the analyzers to be handled or not. If true - Handles ; False - Not handled.
        /// </summary>
        public static bool IsDiagnosticAnalyzerSuppressed(IDiagnosticAnalyzer analyzer, CompilationOptions options, Func<Exception, IDiagnosticAnalyzer, bool> continueOnAnalyzerException)
        {
            if (analyzer == null)
            {
                throw new ArgumentNullException("analyzer");
            }

            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            Action<Diagnostic> dummy = _ => { };
            return IsDiagnosticAnalyzerSuppressed(analyzer, options, dummy, continueOnAnalyzerException, CancellationToken.None);
        }
 /// <summary>
 /// Given classes in the form of strings, their language, and an IDiagnosticAnlayzer to apply to it, return the diagnostics found in the string after converting it to a document.
 /// </summary>
 /// <param name="sources">Classes in the form of strings</param>
 /// <param name="language">The language the soruce classes are in</param>
 /// <param name="analyzer">The analyzer to be run on the sources</param>
 /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns>
 private static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, IDiagnosticAnalyzer analyzer)
 {
     return GetSortedDiagnosticsFromDocuments(analyzer, GetDocuments(sources, language));
 }
Пример #24
0
 private static string FormatDiagnostics(IDiagnosticAnalyzer analyzer, IEnumerable <Diagnostic> diagnostics)
 {
     return(FormatDiagnostics(analyzer, diagnostics.ToArray()));
 }
Пример #25
0
        public static void Verify(this IEnumerable <Diagnostic> actualResults, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expectedResults)
        {
            int expectedCount = expectedResults.Count();
            int actualCount   = actualResults.Count();

            if (expectedCount != actualCount)
            {
                string diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults) : "    NONE.";

                Assert.True(false,
                            string.Format("Mismatch between number of diagnostics returned, expected \"{0}\" acutal \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput));
            }

            for (int i = 0; i < expectedResults.Length; i++)
            {
                var actual   = actualResults.ElementAt(i);
                var expected = expectedResults[i];

                if (expected.Line == -1 && expected.Column == -1)
                {
                    if (actual.Location != Location.None)
                    {
                        Assert.True(false,
                                    string.Format("Expected:\nA project diagnostic with No location\nActual:\n{0}",
                                                  FormatDiagnostics(analyzer, actual)));
                    }
                }
                else
                {
                    VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Locations.First());
                    var additionalLocations = actual.AdditionalLocations.ToArray();

                    if (additionalLocations.Length != expected.Locations.Length - 1)
                    {
                        Assert.True(false,
                                    string.Format("Expected {0} additional locations but got {1} for Diagnostic:\r\n    {2}\r\n",
                                                  expected.Locations.Length - 1, additionalLocations.Length,
                                                  FormatDiagnostics(analyzer, actual)));
                    }

                    for (int j = 0; j < additionalLocations.Length; ++j)
                    {
                        VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Locations[j + 1]);
                    }
                }

                if (actual.Id != expected.Id)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Id, actual.Id, FormatDiagnostics(analyzer, actual)));
                }

                if (actual.Severity != expected.Severity)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual)));
                }

                if (actual.GetMessage() != expected.Message)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual)));
                }
            }
        }
Пример #26
0
 protected static Diagnostic[] GetSortedDiagnostics(IDiagnosticAnalyzer analyzer, Document document, TextSpan?[] spans = null)
 {
     return GetSortedDiagnostics(analyzer, new[] { document }, spans);
 }
 protected virtual void Verify(string source, string language, IDiagnosticAnalyzer[] analyzers, DiagnosticDescription[] diagnostics, string rootNamespace = null)
 {
     Assert.True(analyzers != null && analyzers.Length > 0, "Must specify at least one diagnostic analyzer to test suppression");
     var compilation = CreateCompilation(source, language, analyzers, rootNamespace);
     compilation.VerifyAnalyzerDiagnostics(analyzers, diagnostics);
 }
Пример #28
0
        protected static Diagnostic[] GetSortedDiagnostics(IDiagnosticAnalyzer analyzer, Document[] documents, TextSpan?[] spans = null)
        {
            var projects = new HashSet<Project>();
            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = DiagnosticBag.GetInstance();
            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().Result;

                var compilationStartedAnalyzer = analyzer as ICompilationStartedAnalyzer;
                ICompilationEndedAnalyzer compilationEndedAnalyzer = null;
                if (compilationStartedAnalyzer != null)
                {
                    compilationEndedAnalyzer = compilationStartedAnalyzer.OnCompilationStarted(compilation, diagnostics.Add, default(CancellationToken));
                }

                for (int i = 0; i < documents.Length; i++)
                {
                    var document = documents[i];
                    var span = spans != null ? spans[i] : null;
                    AnalyzeDocument(analyzer, document, diagnostics.Add, span);
                    if (compilationEndedAnalyzer != null)
                    {
                        AnalyzeDocumentCore(compilationEndedAnalyzer, document, diagnostics.Add, span);
                    }
                }

                if (compilationEndedAnalyzer != null)
                {
                    compilationEndedAnalyzer.OnCompilationEnded(compilation, diagnostics.Add, default(CancellationToken));
                }
            }

            var results = GetSortedDiagnostics(diagnostics.AsEnumerable());
            diagnostics.Free();
            return results;
        }
Пример #29
0
        /// <summary>
        /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
        /// then verifies each of them.
        /// </summary>
        /// <param name="sources">An array of strings to create source documents from to run teh analyzers on</param>
        /// <param name="language">The language of the classes represented by the source strings</param>
        /// <param name="analyzer">The analyzer to be run on the source code</param>
        /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
        private void VerifyDiagnostics(string[] sources, string language, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
        {
            var diagnostics = GetSortedDiagnostics(sources, language, analyzer);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
Пример #30
0
 protected static void AnalyzeDocumentCore(IDiagnosticAnalyzer analyzer, Document document, Action<Diagnostic> addDiagnostic, TextSpan? span = null, bool continueOnError = false)
 {
     TextSpan spanToTest = span.HasValue ? span.Value : document.GetSyntaxRootAsync().Result.FullSpan;
     var semanticModel = document.GetSemanticModelAsync().Result;
     AnalyzerDriver.RunAnalyzers(semanticModel, spanToTest, ImmutableArray.Create(analyzer), addDiagnostic, continueOnError: continueOnError);
 }
 protected static void AnalyzeDocumentCore(IDiagnosticAnalyzer analyzer, Document document, Action<Diagnostic> addDiagnostic, TextSpan? span = null, Func<Exception, IDiagnosticAnalyzer, bool> continueOnAnalyzerException = null)
 {
     var semanticModel = document.GetSemanticModelAsync().Result;
     var diagnostics = semanticModel.Compilation.GetAnalyzerDiagnostics(new[] { analyzer }, continueOnAnalyzerException: continueOnAnalyzerException);
     foreach (var diagnostic in diagnostics)
     {
         if (!span.HasValue ||
             diagnostic.Location == Location.None ||
             diagnostic.Location.IsInMetadata ||
             (diagnostic.Location.SourceTree == semanticModel.SyntaxTree &&
             span.Value.Contains(diagnostic.Location.SourceSpan)))
         {
             addDiagnostic(diagnostic);
         }
     }
 }
Пример #32
0
 protected void Verify(string source, string language, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
 {
     Verify(new[] { source }, language, analyzer, expected);
 }
Пример #33
0
 protected static void ExecuteAndCatchIfThrows(IDiagnosticAnalyzer a, Action<Diagnostic> addDiagnostic, bool continueOnError, CancellationToken cancellationToken, Action analyze)
 {
     try
     {
         analyze();
     }
     catch (OperationCanceledException oce)
     {
         if (continueOnError)
         {
             if (oce.CancellationToken != cancellationToken)
             {
                 // Create a info diagnostic saying that the analyzer failed
                 addDiagnostic(GetAnalyzerDiagnostic(a, oce));
             }
         }
     }
     catch (Exception e)
     {
         if (continueOnError)
         {
             // Create a info diagnostic saying that the analyzer failed
             addDiagnostic(GetAnalyzerDiagnostic(a, e));
         }
     }
 }
Пример #34
0
        protected static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, IDiagnosticAnalyzer analyzer)
        {
            var documentsAndUseSpan = GetDocumentsAndSpans(sources, language);
            var documents           = documentsAndUseSpan.Item1;
            var useSpans            = documentsAndUseSpan.Item2;
            var spans = documentsAndUseSpan.Item3;

            return(GetSortedDiagnostics(analyzer, documents, useSpans ? spans : null));
        }
Пример #35
0
 protected void Verify(string source, string language, IDiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
 {
     Verify(new[] { source }, language, analyzer, expected);
 }
        /// <summary>
        /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options.
        /// </summary>
        private static bool IsDiagnosticAnalyzerSuppressed(
            IDiagnosticAnalyzer analyzer, 
            CompilationOptions options, 
            Action<Diagnostic> addDiagnostic, 
            Func<Exception, IDiagnosticAnalyzer, bool> continueOnAnalyzerException, 
            CancellationToken cancellationToken)
        {
            var supportedDiagnostics = ImmutableArray<DiagnosticDescriptor>.Empty;
            
            // Catch Exception from analyzer.SupportedDiagnostics
            ExecuteAndCatchIfThrows(analyzer, addDiagnostic, continueOnAnalyzerException, cancellationToken, () => { supportedDiagnostics = analyzer.SupportedDiagnostics; });

            var diagnosticOptions = options.SpecificDiagnosticOptions;

            foreach (var diag in supportedDiagnostics)
            {
                // Is this diagnostic suppressed by default (as written by the rule author)
                var isSuppressed = !diag.IsEnabledByDefault;

                // If the user said something about it, that overrides the author.
                if (diagnosticOptions.ContainsKey(diag.Id))
                {
                    isSuppressed = diagnosticOptions[diag.Id] == ReportDiagnostic.Suppress;
                }

                if (isSuppressed)
                {
                    continue;
                }
                else
                {
                    return false;
                }
            }

            return true;
        }
Пример #37
0
 private static IEnumerable<Diagnostic> GetDiagnosticsUsingCompilerAnalyzerDriver(IDiagnosticAnalyzer analyzer, Document document, TextSpan? span)
 {
     var semanticModel = document.GetSemanticModelAsync().Result;
     var compilation = semanticModel.Compilation;
     var diagnostics = new List<Diagnostic>();
     AnalyzeDocumentCore(analyzer, document, diagnostics.Add, span);
     return diagnostics;
 }
 protected void VerifyCSharp(string source, IDiagnosticAnalyzer[] analyzers, params DiagnosticDescription[] diagnostics)
 {
     Verify(source, LanguageNames.CSharp, analyzers, diagnostics);
 }
 protected static void ExecuteAndCatchIfThrows(IDiagnosticAnalyzer analyzer, Action<Diagnostic> addDiagnostic, Func<Exception, IDiagnosticAnalyzer, bool> continueOnAnalyzerException, CancellationToken cancellationToken, Action analyze)
 {
     try
     {
         analyze();
     }
     catch (OperationCanceledException oce) if (continueOnAnalyzerException(oce, analyzer))
     {
         if (oce.CancellationToken != cancellationToken)
         {
             // Create a info diagnostic saying that the analyzer failed
             addDiagnostic(GetAnalyzerDiagnostic(analyzer, oce));
         }
     }
     catch (Exception e) if (continueOnAnalyzerException(e, analyzer))
     {
         // Create a info diagnostic saying that the analyzer failed
         addDiagnostic(GetAnalyzerDiagnostic(analyzer, e));
     }
 }
 protected void VerifyBasic(string source, IDiagnosticAnalyzer[] analyzers, params DiagnosticDescription[] diagnostics)
 {
     Verify(source, LanguageNames.VisualBasic, analyzers, diagnostics);
 }
 internal static Diagnostic GetAnalyzerDiagnostic(IDiagnosticAnalyzer analyzer, Exception e)
 {
     return Diagnostic.Create(GetDiagnosticDescriptor(analyzer.GetType().ToString(), e.Message), Location.None);
 }
        private static Compilation CreateCompilation(string source, string language, IDiagnosticAnalyzer[] analyzers, string rootNamespace)
        {
            string fileName = language == LanguageNames.CSharp ? "Test.cs" : "Test.vb";
            string projectName = "TestProject";

            var syntaxTree = language == LanguageNames.CSharp ?
                CSharpSyntaxTree.ParseText(source, fileName) :
                VisualBasicSyntaxTree.ParseText(source, fileName);

            if (language == LanguageNames.CSharp)
            {
                return CSharpCompilation.Create(
                    projectName,
                    syntaxTrees: new[] { syntaxTree },
                    references: new[] { TestBase.MscorlibRef });
            }
            else
            {
                return VisualBasicCompilation.Create(
                    projectName,
                    syntaxTrees: new[] { syntaxTree },
                    references: new[] { TestBase.MscorlibRef },
                    options: new VisualBasicCompilationOptions(
                        OutputKind.DynamicallyLinkedLibrary,
                        rootNamespace: rootNamespace));
            }
        }
        protected static Diagnostic[] GetSortedDiagnostics(IDiagnosticAnalyzer analyzer, Document[] documents, TextSpan?[] spans = null)
        {
            var projects = new HashSet<Project>();
            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = DiagnosticBag.GetInstance();
            foreach (var project in projects)
            {
                var compilation = project.GetCompilationAsync().Result;
                var diags = compilation.GetAnalyzerDiagnostics(new[] { analyzer });

                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree = document.GetSyntaxTreeAsync().Result;
                            if (tree == diag.Location.SourceTree)
                            {
                                var span = spans != null ? spans[i] : null;
                                if (span == null || span.Value.Contains(diag.Location.SourceSpan))
                                {
                                    diagnostics.Add(diag);
                                }
                            }
                        }
                    }
                }
            }

            var results = GetSortedDiagnostics(diagnostics.AsEnumerable());
            diagnostics.Free();
            return results;
        }