コード例 #1
0
        // Verifies the results for the given web.config file path.
        private static void VerifyResults(string webConfigPath, IList <Diagnostic> allDiagnostics, string languageVersion)
        {
            var actualIssues   = allDiagnostics.Where(d => d.Location.GetLineSpan().Path.EndsWith(webConfigPath));
            var expectedIssues = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(File.ReadAllText(webConfigPath)).Lines).ToList();

            DiagnosticVerifier.CompareActualToExpected(languageVersion, actualIssues, expectedIssues, false);
        }
コード例 #2
0
ファイル: Verifier.cs プロジェクト: fsateler/sonar-csharp
        public static void VerifyAnalyzer(string path, SonarDiagnosticAnalyzer diagnosticAnalyzer, ParseOptions options = null,
                                          params MetadataReference[] additionalReferences)
        {
            var file         = new FileInfo(path);
            var parseOptions = GetParseOptionsAlternatives(options, file.Extension);

            var issueLocationCollector = new IssueLocationCollector();

            using (var workspace = new AdhocWorkspace())
            {
                var document = GetDocument(file, GeneratedAssemblyName, workspace, additionalReferences: additionalReferences);
                var project  = document.Project;

                foreach (var parseOption in parseOptions)
                {
                    if (parseOption != null)
                    {
                        project = project.WithParseOptions(parseOption);
                    }

                    var compilation = project.GetCompilationAsync().Result;

                    var diagnostics = GetDiagnostics(compilation, diagnosticAnalyzer);

                    var expectedIssues = issueLocationCollector
                                         .GetExpectedIssueLocations(compilation.SyntaxTrees.First().GetText().Lines)
                                         .ToList();

                    foreach (var diagnostic in diagnostics)
                    {
                        var location = diagnostic.Location;
                        var message  = diagnostic.GetMessage();

                        string issueId;
                        VerifyIssue(expectedIssues, issue => issue.IsPrimary, location, message, out issueId);

                        var sortedAdditionalLocations = diagnostic.AdditionalLocations
                                                        .OrderBy(x => x.GetLineNumberToReport())
                                                        .ThenBy(x => x.GetLineSpan().StartLinePosition.Character)
                                                        .ToList();
                        for (int i = 0; i < sortedAdditionalLocations.Count; i++)
                        {
                            location = sortedAdditionalLocations[i];
                            diagnostic.Properties.TryGetValue(i.ToString(), out message);

                            VerifyIssue(expectedIssues, issue => issue.IssueId == issueId && !issue.IsPrimary, location, message, out issueId);
                        }
                    }

                    if (expectedIssues.Count != 0)
                    {
                        Execute.Assertion.FailWith($"Issue expected but not raised on line(s) {string.Join(",", expectedIssues.Select(i => i.LineNumber))}.");
                    }
                }
            }
        }
        public void GetExpectedIssueLocations_No_Comments()
        {
            var code      = @"public class Foo
{
    public void Bar(object o)
    {
        Console.WriteLine(o);
    }
}";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().BeEmpty();
        }
コード例 #4
0
ファイル: Verifier.cs プロジェクト: chafdev/sonar-csharp
        private static void VerifyAnalyzer(IEnumerable <DocumentInfo> documents, string fileExtension, SonarDiagnosticAnalyzer diagnosticAnalyzer, ParseOptions options = null,
                                           params MetadataReference[] additionalReferences)
        {
            var parseOptions = GetParseOptionsAlternatives(options, fileExtension);

            using (var workspace = new AdhocWorkspace())
            {
                var project = CreateProject(fileExtension, GeneratedAssemblyName, workspace, additionalReferences);
                documents.ToList().ForEach(document => project = project.AddDocument(document.Name, document.Content).Project); // side effect on purpose (project is immutable)

                var issueLocationCollector = new IssueLocationCollector();

                foreach (var parseOption in parseOptions)
                {
                    if (parseOption != null)
                    {
                        project = project.WithParseOptions(parseOption);
                    }

                    var compilation = project.GetCompilationAsync().Result;

                    var diagnostics = GetDiagnostics(compilation, diagnosticAnalyzer);

                    var expectedIssues = issueLocationCollector
                                         .GetExpectedIssueLocations(compilation.SyntaxTrees.Skip(1).First().GetText().Lines)
                                         .ToList();

                    foreach (var diagnostic in diagnostics)
                    {
                        string issueId;
                        VerifyIssue(expectedIssues, issue => issue.IsPrimary, diagnostic.Location, diagnostic.GetMessage(), out issueId);

                        diagnostic.AdditionalLocations
                        .Select((location, i) => diagnostic.GetSecondaryLocation(i))
                        .OrderBy(x => x.Location.GetLineNumberToReport())
                        .ThenBy(x => x.Location.GetLineSpan().StartLinePosition.Character)
                        .ToList()
                        .ForEach(secondaryLocation =>
                        {
                            VerifyIssue(expectedIssues, issue => issue.IssueId == issueId && !issue.IsPrimary,
                                        secondaryLocation.Location, secondaryLocation.Message, out issueId);
                        });
                    }

                    if (expectedIssues.Count != 0)
                    {
                        Execute.Assertion.FailWith($"Issue expected but not raised on line(s) {string.Join(",", expectedIssues.Select(i => i.LineNumber))}.");
                    }
                }
            }
        }
        public void GetExpectedIssueLocations_Multiple_PrimaryIds()
        {
            var code = @"public class Foo
{
    public void Bar(object o) // Noncompliant [myId1]
    {
        Console.WriteLine(o); // Noncompliant [myId1]
    }
}";

            Action action = () => IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            action.Should().Throw <InvalidOperationException>()
            .WithMessage("Primary location with id [myId1] found on multiple lines: 3, 5");
        }
        public void GetExpectedIssueLocations_OnlyCommentedNoncompliant()
        {
            var code      = @"public class MyNoncompliantClass
{
    public void NoncompliantMethod(object o)
    {
        Console.WriteLine(o); // Noncompliant
    }
}";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().ContainSingle();
            locations.Select(l => l.IsPrimary).Should().Equal(new[] { true });
            locations.Select(l => l.LineNumber).Should().Equal(new[] { 5 });
        }
        public void GetExpectedIssueLocations_Invalid_Type_Format()
        {
            var code = @"public class Foo
{
    public void Bar(object o) // Is Noncompliant
    {
        Console.WriteLine(o);
    }
}";

            Action action = () => IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            action.Should().Throw <InvalidOperationException>()
            .WithMessage(@"Line 2 looks like it contains comment for noncompliant code, but it is not recognized as one of the expected pattern.
Either remove the Noncompliant/Secondary word or precise pattern '^^' from the comment, or fix the pattern.");
        }
        public void GetExpectedIssueLocations_Redundant_Locations()
        {
            var code = @"public class Foo
{
    public void Bar(object o) // Noncompliant ^17#3
//              ^^^
    {
        Console.WriteLine(o);
    }
}";

            Action action = () => IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            action.Should().Throw <InvalidOperationException>()
            .WithMessage("Unexpected redundant issue location on line 3. Issue location can be set either " +
                         "with 'precise issue location' or 'exact column location' pattern but not both.");
        }
        public void GetExpectedIssueLocations_Locations_VB()
        {
            var code      = @"
Public Class Foo

    Public Sub Bar(o As Object) ' Noncompliant
        ' Noncompliant@+1
        Console.WriteLine(o)
    End Sub

End Class";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().HaveCount(2);

            locations.Select(l => l.IsPrimary).Should().Equal(new[] { true, true });
            locations.Select(l => l.LineNumber).Should().Equal(new[] { 4, 6 });
        }
        public void GetExpectedIssueLocations_Locations_CS()
        {
            var code      = @"
public class Foo
{
    public void Bar(object o) // Noncompliant
    {
        // Noncompliant@+1
        Console.WriteLine(o);
    }
}";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().HaveCount(2);

            locations.Select(l => l.IsPrimary).Should().Equal(new[] { true, true });
            locations.Select(l => l.LineNumber).Should().Equal(new[] { 4, 7 });
        }
        public void GetExpectedIssueLocations_ExactColumns()
        {
            var code      = @"public class Foo
{
    public void Bar(object o) // Noncompliant ^17#3
                              // Secondary@-1 ^28#1
    {
        Console.WriteLine(o);
    }
}";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().HaveCount(2);

            locations.Select(l => l.IsPrimary).Should().BeEquivalentTo(new[] { true, false });
            locations.Select(l => l.LineNumber).Should().Equal(new[] { 3, 3 });
            locations.Select(l => l.Start).Should().Equal(new[] { 16, 27 });
            locations.Select(l => l.Length).Should().Equal(new[] { 3, 1 });
        }
        public void GetExpectedIssueLocations_Locations_Xml()
        {
            var code      = @"<Root>
<SelfClosing /><!-- Noncompliant -->
<SelfClosing /><!-- Noncompliant with additional comment and new line
-->
<InsideWithSpace><!-- Noncompliant--></InsideWithSpace>
<InsideNoSpace><!--Secondary--></InsideNoSpace>
<Innocent><!--Noncompliant@+1--></Innocent>
<Guilty />
<!--
Noncompliant - this should not be detected as expected issue
-->
</Root>";
            var locations = IssueLocationCollector.GetExpectedIssueLocations(SourceText.From(code).Lines);

            locations.Should().HaveCount(5);

            locations.Select(l => l.IsPrimary).Should().Equal(new[] { true, true, true, false, true });
            locations.Select(l => l.LineNumber).Should().Equal(new[] { 2, 3, 5, 6, 8 });
        }
コード例 #13
0
        public static void VerifyAnalyzer(IEnumerable <string> paths, SonarDiagnosticAnalyzer diagnosticAnalyzer, ParseOptions options = null,
                                          params MetadataReference[] additionalReferences)
        {
            if (paths == null || !paths.Any())
            {
                throw new ArgumentException("Please specify at least one file path to analyze.", nameof(paths));
            }

            var files = paths.Select(path => new FileInfo(path)).ToList();

            if (files.Select(file => file.Extension).Distinct().Count() != 1)
            {
                throw new ArgumentException("Please use a collection of paths with the same extension", nameof(paths));
            }

            var parseOptions = files.SelectMany(file => GetParseOptionsAlternatives(options, file.Extension)).Distinct();

            var issueLocationCollector = new IssueLocationCollector();

            using (var workspace = new AdhocWorkspace())
            {
                var project = CreateProject(files[0], GeneratedAssemblyName, workspace, additionalReferences);
                files.ForEach(file => project = project.AddDocument(file)); // side effect on purpose (project is immutable)

                foreach (var parseOption in parseOptions)
                {
                    if (parseOption != null)
                    {
                        project = project.WithParseOptions(parseOption);
                    }

                    var compilation = project.GetCompilationAsync().Result;

                    var diagnostics = GetDiagnostics(compilation, diagnosticAnalyzer);

                    var expectedIssues = issueLocationCollector
                                         .GetExpectedIssueLocations(compilation.SyntaxTrees.Skip(1).First().GetText().Lines)
                                         .ToList();

                    foreach (var diagnostic in diagnostics)
                    {
                        string issueId;
                        VerifyIssue(expectedIssues, issue => issue.IsPrimary, diagnostic.Location, diagnostic.GetMessage(), out issueId);

                        diagnostic.AdditionalLocations
                        .Select((location, i) => diagnostic.GetSecondaryLocation(i))
                        .OrderBy(x => x.Location.GetLineNumberToReport())
                        .ThenBy(x => x.Location.GetLineSpan().StartLinePosition.Character)
                        .ToList()
                        .ForEach(secondaryLocation =>
                        {
                            VerifyIssue(expectedIssues, issue => issue.IssueId == issueId && !issue.IsPrimary,
                                        secondaryLocation.Location, secondaryLocation.Message, out issueId);
                        });
                    }

                    if (expectedIssues.Count != 0)
                    {
                        Execute.Assertion.FailWith($"Issue expected but not raised on line(s) {string.Join(",", expectedIssues.Select(i => i.LineNumber))}.");
                    }
                }
            }
        }
コード例 #14
0
ファイル: Verifier.cs プロジェクト: xiaofan232/sonar-csharp
        private static void VerifyAnalyzer(IEnumerable <DocumentInfo> documents, string fileExtension, DiagnosticAnalyzer diagnosticAnalyzer,
                                           ParseOptions options = null, Action <DiagnosticAnalyzer, Compilation> additionalVerify = null, params MetadataReference[] additionalReferences)
        {
            try
            {
                HookSuppression();

                var parseOptions = GetParseOptionsAlternatives(options, fileExtension);

                using (var workspace = new AdhocWorkspace())
                {
                    var project = CreateProject(fileExtension, GeneratedAssemblyName, workspace, additionalReferences);
                    project = documents.Aggregate(project, (p, doc) => p.AddDocument(doc.Name, doc.Content).Project); // side effect on purpose (project is immutable)

                    var issueLocationCollector = new IssueLocationCollector();

                    foreach (var parseOption in parseOptions)
                    {
                        if (parseOption != null)
                        {
                            project = project.WithParseOptions(parseOption);
                        }

                        var compilation = project.GetCompilationAsync().Result;

                        var diagnostics = GetDiagnostics(compilation, diagnosticAnalyzer);

                        var expectedIssues = issueLocationCollector
                                             .GetExpectedIssueLocations(compilation.SyntaxTrees.Skip(1).First().GetText().Lines)
                                             .ToList();

                        foreach (var diagnostic in diagnostics)
                        {
                            VerifyIssue(expectedIssues, issue => issue.IsPrimary, diagnostic.Location, diagnostic.GetMessage(), out var issueId);

                            diagnostic.AdditionalLocations
                            .Select((location, i) => diagnostic.GetSecondaryLocation(i))
                            .OrderBy(x => x.Location.GetLineNumberToReport())
                            .ThenBy(x => x.Location.GetLineSpan().StartLinePosition.Character)
                            .ToList()
                            .ForEach(secondaryLocation =>
                            {
                                VerifyIssue(expectedIssues, issue => issue.IssueId == issueId && !issue.IsPrimary,
                                            secondaryLocation.Location, secondaryLocation.Message, out issueId);
                            });
                        }

                        if (expectedIssues.Count != 0)
                        {
                            Execute.Assertion.FailWith($"Issue expected but not raised on line(s) {string.Join(",", expectedIssues.Select(i => i.LineNumber))}.");
                        }

                        // When there are no diagnostics reported from the test (for example the FileLines analyzer
                        // does not report in each call to Verifier.VerifyAnalyzer) we skip the check for the extension
                        // method.
                        if (diagnostics.Any())
                        {
                            ExtensionMethodsCalledForAllDiagnostics(diagnosticAnalyzer).Should().BeTrue("The ReportDiagnosticWhenActive should be used instead of ReportDiagnostic");
                        }

                        additionalVerify?.Invoke(diagnosticAnalyzer, compilation);
                    }
                }
            }
            finally
            {
                UnHookSuppression();
            }
        }