Beispiel #1
0
        /// <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));
        }
Beispiel #2
0
        public DiagnosticResult WithLocationIndicated(string[] testCode)
        {
            var pos = CodeReader.GetErrorPosition(testCode);

            return(this.AppendSpan(pos));
        }
Beispiel #3
0
        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);
            }
        }