internal static List <CodeAction> GetFixActions(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string source) { var document = CodeAnalysisHelper.CreateDocument(source, language); var analyzerDiagnostics = CodeAnalysisHelper.GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); var actions = new List <CodeAction>(); var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None); codeFixProvider.RegisterCodeFixesAsync(context).Wait(); return(actions); }
/// <summary> /// Apply codefixes and returns reslt. /// Creates a Document from the source string, then gets diagnostics on it and applies the relevant codefixes. /// 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="oldSource">A class in the form of a string before the CodeFix was applied to it</param> /// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param> /// <param name="equivalenceKey">CodeAction.EquivalenceKey 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> internal static string GetFixResult(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string oldSource, string equivalenceKey, bool allowNewCompilerDiagnostics) { var document = CodeAnalysisHelper.CreateDocument(oldSource, language); var analyzerDiagnostics = CodeAnalysisHelper.GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); var compilerDiagnostics = CodeAnalysisHelper.GetCompilerDiagnostics(document); var attempts = analyzerDiagnostics.Length; for (int i = 0; i < attempts; ++i) { var actions = new List <CodeAction>(); var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None); codeFixProvider.RegisterCodeFixesAsync(context).Wait(); if (!actions.Any()) { break; } if (equivalenceKey != null) { document = CodeAnalysisHelper.ApplyFix(document, actions.Single(n => n.EquivalenceKey == equivalenceKey)); break; } document = CodeAnalysisHelper.ApplyFix(document, actions.ElementAt(0)); analyzerDiagnostics = CodeAnalysisHelper.GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); var newCompilerDiagnostics = CodeAnalysisHelper.GetNewDiagnostics(compilerDiagnostics, CodeAnalysisHelper.GetCompilerDiagnostics(document)); //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 document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace)); newCompilerDiagnostics = CodeAnalysisHelper.GetNewDiagnostics(compilerDiagnostics, CodeAnalysisHelper.GetCompilerDiagnostics(document)); Assert.IsTrue(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())), document.GetSyntaxRootAsync().Result.ToFullString())); } //check if there are analyzer diagnostics left after the code fix if (!analyzerDiagnostics.Any()) { break; } } var newSource = CodeAnalysisHelper.GetStringFromDocument(document); return(newSource); }