protected static void AnalyzeWithRule <T>(string input, string ruleId, string output = null, int issueToFix = -1, int actionToRun = 0, Action <int, Diagnostic> diagnosticCheck = null) where T : DiagnosticAnalyzer, new() { var text = new StringBuilder(); var expectedDiagnosics = new List <TextSpan> (); int start = -1; for (int i = 0; i < input.Length; i++) { char ch = input [i]; if (ch == '$') { if (start < 0) { start = text.Length; continue; } expectedDiagnosics.Add(TextSpan.FromBounds(start, text.Length)); start = -1; } else { text.Append(ch); } } var syntaxTree = CSharpSyntaxTree.ParseText(text.ToString()); Compilation compilation = CreateCompilationWithMscorlib(new [] { syntaxTree }); var diagnostics = new List <Diagnostic>(); var compilationWithAnalyzers = compilation.WithAnalyzers(System.Collections.Immutable.ImmutableArray <DiagnosticAnalyzer> .Empty.Add(new T())); diagnostics.AddRange(compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result); if (expectedDiagnosics.Count != diagnostics.Count) { Console.WriteLine("Diagnostics: " + diagnostics.Count); foreach (var diag in diagnostics) { Console.WriteLine(diag.Id + "/" + diag.GetMessage()); } Assert.Fail("Diagnostic count mismatch expected: " + expectedDiagnosics.Count + " but was:" + diagnostics.Count); } for (int i = 0; i < expectedDiagnosics.Count; i++) { var d = diagnostics [i]; var wholeSpan = GetWholeSpan(d); if (wholeSpan != expectedDiagnosics [i]) { Assert.Fail("Diagnostic " + i + " span mismatch expected: " + expectedDiagnosics[i] + " but was " + wholeSpan); } if (diagnosticCheck != null) { diagnosticCheck(i, d); } } if (output == null) { return; } var workspace = new TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "", "", LanguageNames.CSharp, null, null, null, null, new [] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text.ToString()), VersionStamp.Create()))) } )); if (issueToFix < 0) { diagnostics.Reverse(); foreach (var v in diagnostics) { RunFix(workspace, projectId, documentId, v); } } else { RunFix(workspace, projectId, documentId, diagnostics.ElementAt(issueToFix), actionToRun); } var txt = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId).GetTextAsync().Result.ToString(); if (output != txt) { Console.WriteLine("expected:"); Console.WriteLine(output); Console.WriteLine("got:"); Console.WriteLine(txt); Assert.Fail(); } }
protected static void Analyze <T>(Func <string, SyntaxTree> parseTextFunc, Func <SyntaxTree[], Compilation> createCompilationFunc, string language, string input, string output = null, int issueToFix = -1, int actionToRun = 0, Action <int, Diagnostic> diagnosticCheck = null) where T : DiagnosticAnalyzer, new() { var text = new StringBuilder(); var expectedDiagnosics = new List <TextSpan>(); int start = -1; for (int i = 0; i < input.Length; i++) { char ch = input[i]; if (ch == '$' && ((i > 0) && (input[i - 1] == '$'))) { // Ignore 2nd "$" in "$$" } else if (ch == '$' && (i + 1 >= input.Length || input[i + 1] != '$')) { if (start < 0) { start = text.Length; continue; } expectedDiagnosics.Add(TextSpan.FromBounds(start, text.Length)); start = -1; } else { text.Append(ch); } } var syntaxTree = parseTextFunc(text.ToString()); Compilation compilation = createCompilationFunc(new[] { syntaxTree }); var diagnostics = new List <Diagnostic>(); var compilationWithAnalyzers = compilation.WithAnalyzers(System.Collections.Immutable.ImmutableArray <DiagnosticAnalyzer> .Empty.Add(new T())); var result = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result; diagnostics.AddRange(result); diagnostics.Sort((d1, d2) => d1.Location.SourceSpan.Start.CompareTo(d2.Location.SourceSpan.Start)); expectedDiagnosics.Sort((d1, d2) => d1.Start.CompareTo(d2.Start)); if (expectedDiagnosics.Count != diagnostics.Count) { foreach (var diag in diagnostics) { Console.WriteLine(diag.Id + "/" + diag.GetMessage() + "/" + diag.Location.SourceSpan); } Assert.Fail("Diagnostic count mismatch expected: " + expectedDiagnosics.Count + " was " + diagnostics.Count); } for (int i = 0; i < expectedDiagnosics.Count; i++) { var d = diagnostics[i]; var wholeSpan = GetWholeSpan(d); if (wholeSpan != expectedDiagnosics[i]) { Assert.Fail("Diagnostic " + i + " span mismatch expected: " + expectedDiagnosics[i] + " but was " + wholeSpan); } if (diagnosticCheck != null) { diagnosticCheck(i, d); } } if (output == null) { return; } var workspace = new TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "a", "a.exe", language, null, null, null, null, new[] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text.ToString()), VersionStamp.Create()))) } )); if (issueToFix < 0) { diagnostics.Reverse(); foreach (var v in diagnostics) { RunFix(workspace, projectId, documentId, v); } } else { RunFix(workspace, projectId, documentId, diagnostics.ElementAt(issueToFix), actionToRun); } var txt = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId).GetTextAsync().Result.ToString(); output = Utils.HomogenizeEol(output); txt = Utils.HomogenizeEol(txt); if (output != txt) { Console.WriteLine("expected:"); Console.WriteLine(output); Console.WriteLine("got:"); Console.WriteLine(txt); Console.WriteLine("-----Mismatch:"); for (int i = 0; i < txt.Length; i++) { if (i >= output.Length) { Console.Write("#"); continue; } if (txt[i] != output[i]) { Console.Write("#"); continue; } Console.Write(txt[i]); } Assert.Fail(); } }