예제 #1
0
 public void Given_Source_Then_Verify_Diagnostic_And_Codefix(
     string description, GeneratorSourcePackage sourcePackage, DiagnosticResult[] diagnosticResults)
 {
     VerifyCSharpDiagnostic(sourcePackage.GetInputSources(), diagnosticResults);
     VerifyCSharpGeneratorFix(sourcePackage);
 }
예제 #2
0
 /// <summary>
 /// Called to test a VB codefix when applied on the inputted string as a source
 /// </summary>
 /// <param name="sources">Source package to operate on</param>
 /// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
 /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
 protected void VerifyBasicGeneratorFix(GeneratorSourcePackage sources, int?codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
 {
     VerifyGeneratorFix(LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), GetBasicCodeFixProvider(), sources, codeFixIndex, allowNewCompilerDiagnostics);
 }
예제 #3
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="sources">Source package to operate on</param>
        /// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
        /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
        private void VerifyGeneratorFix(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, GeneratorSourcePackage sources, int?codeFixIndex, bool allowNewCompilerDiagnostics)
        {
            var compiledSources     = (sources.AdditionalSources?.ToImmutableList() ?? ImmutableList <string> .Empty).Insert(0, sources.OldSource).ToArray();
            var documents           = GetDocuments(compiledSources, language);
            var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, documents.Take(1).ToArray());
            var compilerDiagnostics = GetCompilerDiagnostics(documents[0]);
            var attempts            = analyzerDiagnostics.Length;

            var documentPackage = new GeneratorDocumentPackage
            {
                FixedDocument = documents[0]
            };

            for (int i = 0; i < attempts; ++i)
            {
                var actions = new List <CodeAction>();
                if (!codeFixProvider.FixableDiagnosticIds.Contains(analyzerDiagnostics[0].Id))
                {
                    continue;
                }
                var context = new CodeFixContext(documentPackage.FixedDocument, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None);
                codeFixProvider.RegisterCodeFixesAsync(context).Wait();

                if (!actions.Any())
                {
                    break;
                }

                if (codeFixIndex != null)
                {
                    documentPackage = ApplyGeneratorFix(documentPackage.FixedDocument, actions.ElementAt((int)codeFixIndex));
                    break;
                }

                documentPackage     = ApplyGeneratorFix(documentPackage.FixedDocument, actions.ElementAt(0));
                analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { documentPackage.FixedDocument });

                var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(documentPackage.FixedDocument));

                //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
                    documentPackage.FixedDocument = documentPackage.FixedDocument.WithSyntaxRoot(
                        Formatter.Format(
                            documentPackage.FixedDocument.GetSyntaxRootAsync().Result,
                            Formatter.Annotation,
                            documentPackage.FixedDocument.Project.Solution.Workspace));
                    newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(documentPackage.FixedDocument));

                    Assert.True(false,
                                string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
                                              string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())),
                                              documentPackage.FixedDocument.GetSyntaxRootAsync().Result.ToFullString()));
                }

                //check if there are analyzer diagnostics left after the code fix
                if (!analyzerDiagnostics.Any())
                {
                    break;
                }
            }

            //after applying all of the code fixes, compare the resulting string to the inputted one
            var actualFixed = GetStringFromDocument(documentPackage.FixedDocument);

            Assert.Equal(sources.FixedSource, actualFixed);
            if (sources.AddedSource != null)
            {
                Assert.True(documentPackage.AddedDocument != null, "Expected added (new) document, none found in results.");
                var actualAdded = GetStringFromDocument(documentPackage.AddedDocument);
                Assert.Equal(sources.AddedSource, actualAdded);
            }
            if (sources.ChangedSource != null)
            {
                Assert.True(documentPackage.ChangedDocument != null, "Expected changed (except the fixed one) document, none found in results.");
                var actualChanged = GetStringFromDocument(documentPackage.ChangedDocument);
                Assert.Equal(sources.ChangedSource, actualChanged);
            }
        }
예제 #4
0
 /// <summary>
 /// Called to test a C# codefix when applied on the inputted string as a source
 /// </summary>
 /// <param name="sources">Source package to operate on</param>
 /// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
 /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
 protected void VerifyCSharpGeneratorFix(GeneratorSourcePackage sources, int?codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
 {
     VerifyGeneratorFix(LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), GetCSharpCodeFixProvider(), sources, codeFixIndex, allowNewCompilerDiagnostics);
 }