/// <summary> /// Create a project using the input strings as sources. /// </summary> /// <remarks> /// <para>This method first creates a <see cref="Project"/> and then /// applies compilation options to the project by calling <see cref="ApplyCompilationOptions"/>.</para> /// </remarks> /// <param name="sources">Classes in the form of strings.</param> /// <param name="analyzers">The analyzers to use.</param> /// <param name="disabledDiagnostics">The analyzers to suppress.</param> /// <returns>A <see cref="Project"/> created out of the <see cref="Document"/>s created from the source /// strings.</returns> public static Project CreateProject(string[] sources, IEnumerable <DiagnosticAnalyzer> analyzers, IEnumerable <string> disabledDiagnostics = null) { var projectId = ProjectId.CreateNewId(debugName: TestProjectName); var solution = CreateSolution(projectId, LanguageNames.CSharp); var filenames = CodeReader.CreateFileNamesFromSources(sources, "cs"); for (var i = 0; i < sources.Length; i++) { var source = sources[i]; var newFileName = filenames[i]; var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName); solution = solution.AddDocument(documentId, newFileName, SourceText.From(source)); } var project = solution.GetProject(projectId); return(ApplyCompilationOptions(project, analyzers, disabledDiagnostics)); }
public DiagnosticResult WithLocationIndicated(string[] testCode) { var pos = CodeReader.GetErrorPosition(testCode); return(this.AppendSpan(pos)); }
private bool Equals(CodeReader other) { var pos = 0; var otherPos = 0; var line = 1; while (pos < this.code.Length && otherPos < other.code.Length) { if (this.code[pos] == '\r') { pos++; continue; } if (other.code[otherPos] == '\r') { otherPos++; continue; } if (this.code[pos] != other.code[otherPos]) { Console.WriteLine($"Mismatch on line {line}"); var expected = this.code.Split('\n')[line - 1].Trim('\r'); var actual = other.code.Split('\n')[line - 1].Trim('\r'); var diffPos = Math.Min(expected.Length, actual.Length); for (int i = 0; i < Math.Min(expected.Length, actual.Length); i++) { if (expected[i] != actual[i]) { diffPos = i; break; } } Console.WriteLine($"Expected: {expected}"); Console.WriteLine($"Actual: {actual}"); Console.WriteLine($" {new string(' ', diffPos)}^"); return(false); } if (this.code[pos] == '\n') { line++; } pos++; otherPos++; } while (pos < this.code.Length && this.code[pos] == '\r') { pos++; } while (otherPos < other.code.Length && other.code[otherPos] == '\r') { otherPos++; } return(pos == this.code.Length && otherPos == other.code.Length); }
private async Task VerifyFixInternalAsync( ImmutableArray <DiagnosticAnalyzer> analyzers, CodeFixProvider codeFixProvider, string[] oldSources, string[] newSources, int?codeFixIndex, bool allowNewCompilerDiagnostics, int numberOfIterations, Func <ImmutableArray <DiagnosticAnalyzer>, CodeFixProvider, int?, Project, int, CancellationToken, Task <Project> > getFixedProject, CancellationToken cancellationToken) { var project = CodeFactory.CreateProject(oldSources, analyzers); var compilerDiagnostics = await GetCompilerDiagnosticsAsync(project, cancellationToken).ConfigureAwait(false); project = await getFixedProject(analyzers, codeFixProvider, codeFixIndex, project, numberOfIterations, cancellationToken).ConfigureAwait(false); var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, await GetCompilerDiagnosticsAsync(project, cancellationToken).ConfigureAwait(false)); // 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 project = await ReformatProjectDocumentsAsync(project, cancellationToken).ConfigureAwait(false); newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, await GetCompilerDiagnosticsAsync(project, cancellationToken).ConfigureAwait(false)); var message = new StringBuilder(); message.Append("Fix introduced new compiler diagnostics:\r\n"); newCompilerDiagnostics.Aggregate(message, (sb, d) => sb.Append(d.ToString()).Append("\r\n")).IgnoreReturnValue(); foreach (var document in project.Documents) { message.Append("\r\n").Append(document.Name).Append(":\r\n"); message.Append((await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false)).ToFullString()); message.Append("\r\n"); } Assert.Fail(message.ToString()); } // After applying all of the code fixes, compare the resulting string to the inputted one var updatedDocuments = project.Documents.ToArray(); Assert.AreEqual($"{newSources.Length} documents", $"{updatedDocuments.Length} documents"); for (var i = 0; i < updatedDocuments.Length; i++) { var actual = await GetStringFromDocumentAsync(updatedDocuments[i], cancellationToken).ConfigureAwait(false); var expectedCode = new CodeReader(newSources[i]); var actualCode = new CodeReader(actual); if (expectedCode != actualCode) { Console.WriteLine("Expected:"); Console.Write(expectedCode); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Actual:"); Console.Write(actualCode); Console.WriteLine(); } Assert.AreEqual(expectedCode, actualCode); } }