Пример #1
0
 /// <summary>
 /// Called to test a C# codefix when applied on the inputted string as a source
 /// </summary>
 /// <param name="oldSources">Code files, each in the form of a string before the CodeFix was applied to it</param>
 /// <param name="newSources">Code files, each 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="expectedPostFixDiagnostics">The set of diagnostics that are expected to exist after any fix(es) are applied to the original code.</param>
 /// <param name="hasEntrypoint"><c>true</c> to set the compiler in a mode as if it were compiling an exe (as opposed to a dll).</param>
 protected void VerifyCSharpFix(string[] oldSources, string[] newSources, int?codeFixIndex = null, PostFixDiagnostics expectedPostFixDiagnostics = PostFixDiagnostics.None, bool hasEntrypoint = false)
 {
     this.VerifyFix(LanguageNames.CSharp, this.GetCSharpDiagnosticAnalyzer(), this.GetCSharpCodeFixProvider(), oldSources, newSources, codeFixIndex, expectedPostFixDiagnostics, hasEntrypoint);
 }
Пример #2
0
        /// <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="oldSources">Code files, each in the form of a string before the CodeFix was applied to it</param>
        /// <param name="newSources">Code files, each 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 in the same location</param>
        /// <param name="expectedPostFixDiagnostics">The set of diagnostics that are expected to exist after any fix(es) are applied to the original code.</param>
        /// <param name="hasEntrypoint"><c>true</c> to set the compiler in a mode as if it were compiling an exe (as opposed to a dll).</param>
        private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string[] oldSources, string[] newSources, int?codeFixIndex, PostFixDiagnostics expectedPostFixDiagnostics, bool hasEntrypoint)
        {
            var project             = CreateProject(oldSources, language, hasEntrypoint);
            var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(ImmutableArray.Create(analyzer), project.Documents.ToArray(), hasEntrypoint);
            var compilerDiagnostics = project.Documents.SelectMany(doc => GetCompilerDiagnostics(doc)).ToList();
            var attempts            = analyzerDiagnostics.Length;

            // We'll go through enough for each diagnostic to be caught once
            bool fixApplied = false;

            for (int i = 0; i < attempts; ++i)
            {
                var diagnostic = analyzerDiagnostics[0]; // just get the first one -- the list gets smaller with each loop.
                var document   = project.GetDocument(diagnostic.Location.SourceTree);
                var actions    = new List <CodeAction>();
                var context    = new CodeFixContext(document, diagnostic, (a, d) => actions.Add(a), CancellationToken.None);
                codeFixProvider.RegisterCodeFixesAsync(context).Wait();
                if (!actions.Any())
                {
                    continue;
                }

                document   = ApplyFix(document, actions[codeFixIndex ?? 0]);
                fixApplied = true;
                project    = document.Project;

                this.Logger.WriteLine("Code after fix:");
                this.LogFileContent(document.GetSyntaxRootAsync().Result.ToFullString());

                analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(ImmutableArray.Create(analyzer), project.Documents.ToArray());
            }

            if (newSources != null && newSources[0] != null)
            {
                Assert.True(fixApplied, "No code fix offered.");

                // After applying all of the code fixes, compare the resulting string to the inputted one
                int j = 0;
                foreach (var document in project.Documents)
                {
                    var actual = GetStringFromDocument(document);
                    Assert.Equal(newSources[j++], actual, ignoreLineEndingDifferences: true);
                }
            }
            else
            {
                Assert.False(fixApplied, "No code fix expected, but was offered.");
            }

            var postFixDiagnostics     = project.Documents.SelectMany(doc => GetCompilerDiagnostics(doc)).Concat(GetSortedDiagnosticsFromDocuments(ImmutableArray.Create(analyzer), project.Documents.ToArray(), hasEntrypoint)).ToList();
            var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, postFixDiagnostics).ToList();

            IEnumerable <Diagnostic> unexpectedDiagnostics;

            switch (expectedPostFixDiagnostics)
            {
            case PostFixDiagnostics.None:
                unexpectedDiagnostics = postFixDiagnostics;
                break;

            case PostFixDiagnostics.Preexisting:
                unexpectedDiagnostics = newCompilerDiagnostics;
                break;

            case PostFixDiagnostics.New:
                unexpectedDiagnostics = Enumerable.Empty <Diagnostic>();    // We don't care what's present.
                break;

            default:
                throw new NotSupportedException();
            }

            var expectedDiagnostics = postFixDiagnostics.Except(unexpectedDiagnostics);

            this.Logger.WriteLine("Actual diagnostics:");
            this.Logger.WriteLine("EXPECTED:\r\n{0}", expectedDiagnostics.Any() ? FormatDiagnostics(expectedDiagnostics.ToArray()) : "    NONE.");
            this.Logger.WriteLine("UNEXPECTED:\r\n{0}", unexpectedDiagnostics.Any() ? FormatDiagnostics(unexpectedDiagnostics.ToArray()) : "    NONE.");

            // Check if applying the code fix introduced any new compiler diagnostics
            Assert.Empty(unexpectedDiagnostics);
        }