/// <summary> /// Verifies that /// 1. <paramref name="fix"/> supports fixing diagnostics reported by <paramref name="analyzer"/>. /// 2. <paramref name="diagnosticsAndSources"/> produces diagnostics fixable by <paramref name="fix"/>. /// 3. Applying <paramref name="fix"/> results in <paramref name="after"/>. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="diagnosticsAndSources"/> with.</param> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply on the <see cref="Diagnostic"/> reported.</param> /// <param name="diagnosticsAndSources">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="after">The expected code produced by applying <paramref name="fix"/>.</param> /// <param name="fixTitle">The expected title of the fix. Must be provided if more than one code action is registered.</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void CodeFix( DiagnosticAnalyzer analyzer, CodeFixProvider fix, DiagnosticsAndSources diagnosticsAndSources, IReadOnlyList <string> after, string?fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { VerifyCodeFixSupportsAnalyzer(analyzer, fix); VerifyAnalyzerSupportsDiagnostics(analyzer, diagnosticsAndSources.ExpectedDiagnostics); var sln = CodeFactory.CreateSolution( diagnosticsAndSources: diagnosticsAndSources, analyzer: analyzer, compilationOptions: compilationOptions, #pragma warning disable CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() suppressWarnings ?? SuppressedDiagnostics, metadataReferences ?? MetadataReferences); #pragma warning restore CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() var diagnostics = Analyze.GetDiagnostics(analyzer, sln); VerifyDiagnostics(diagnosticsAndSources, diagnostics, sln); VerifyFix(sln, diagnostics, analyzer, fix, after, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that <paramref name="diagnosticsAndSources"/> produces the expected diagnostics. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="diagnosticsAndSources"/> with.</param> /// <param name="diagnosticsAndSources">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void Diagnostics( DiagnosticAnalyzer analyzer, DiagnosticsAndSources diagnosticsAndSources, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { VerifyAnalyzerSupportsDiagnostics(analyzer, diagnosticsAndSources.ExpectedDiagnostics); var sln = CodeFactory.CreateSolution( diagnosticsAndSources, analyzer, compilationOptions, #pragma warning disable CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() suppressWarnings ?? SuppressedDiagnostics, metadataReferences ?? MetadataReferences); #pragma warning restore CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() var diagnostics = Analyze.GetDiagnostics(analyzer, sln); VerifyDiagnostics(diagnosticsAndSources, diagnostics, sln); if (allowCompilationErrors == AllowCompilationErrors.No) { NoCompilerErrors(sln); } }
/// <summary> /// Verifies that <paramref name="code"/> produces the expected diagnostics. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="code"/> with.</param> /// <param name="code">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void Diagnostics( DiagnosticAnalyzer analyzer, IReadOnlyList <string> code, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { Diagnostics( analyzer, DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, code), allowCompilationErrors: allowCompilationErrors, suppressWarnings: suppressWarnings, metadataReferences: metadataReferences, compilationOptions: compilationOptions); }
/// <summary> /// Verifies that <paramref name="code"/> produces the expected diagnostics. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="code"/> with.</param> /// <param name="expectedDiagnostic">The <see cref="ExpectedDiagnostic"/> with information about the expected <see cref="Diagnostic"/>. If <paramref name="analyzer"/> supports more than one <see cref="DiagnosticDescriptor.Id"/> this must be provided.</param> /// <param name="code">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void Diagnostics( DiagnosticAnalyzer analyzer, ExpectedDiagnostic expectedDiagnostic, string code, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { Diagnostics( analyzer, DiagnosticsAndSources.Create(expectedDiagnostic, code), allowCompilationErrors: allowCompilationErrors, suppressWarnings: suppressWarnings, metadataReferences: metadataReferences, compilationOptions: compilationOptions); }
/// <summary> /// Verifies that /// 1. <paramref name="solution"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="solution"/> with.</param> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply on the <see cref="Diagnostic"/> reported.</param> /// <param name="expectedDiagnostic">The <see cref="ExpectedDiagnostic"/> with information about the expected <see cref="Diagnostic"/>. If <paramref name="analyzer"/> supports more than one <see cref="DiagnosticDescriptor.Id"/> this must be provided.</param> /// <param name="solution">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="after">The expected code produced by applying <paramref name="fix"/>.</param> /// <param name="fixTitle">The expected title of the fix. Must be provided if more than one code action is registered.</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> public static void CodeFix( DiagnosticAnalyzer analyzer, CodeFixProvider fix, ExpectedDiagnostic expectedDiagnostic, Solution solution, string after, string?fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { VerifyAnalyzerSupportsDiagnostic(analyzer, expectedDiagnostic); VerifyCodeFixSupportsAnalyzer(analyzer, fix); var diagnostics = Analyze.GetDiagnostics(analyzer, solution); var diagnosticsAndSources = DiagnosticsAndSources.Create( expectedDiagnostic, solution.Projects.SelectMany(x => x.Documents).Select(x => x.GetCode()).ToArray()); VerifyDiagnostics(diagnosticsAndSources, diagnostics, solution); VerifyFix(solution, diagnostics, analyzer, fix, MergeFixedCode(diagnosticsAndSources.Code, after), fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix does not change the code. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="code"/> with.</param> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply on the <see cref="Diagnostic"/> reported.</param> /// <param name="expectedDiagnostic">The <see cref="ExpectedDiagnostic"/> with information about the expected <see cref="Diagnostic"/>. If <paramref name="analyzer"/> supports more than one <see cref="DiagnosticDescriptor.Id"/> this must be provided.</param> /// <param name="code">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void NoFix( DiagnosticAnalyzer analyzer, CodeFixProvider fix, ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> code, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { NoFix( analyzer: analyzer, fix: fix, diagnosticsAndSources: DiagnosticsAndSources.Create(expectedDiagnostic, code), allowCompilationErrors: allowCompilationErrors, suppressWarnings: suppressWarnings, metadataReferences: metadataReferences, compilationOptions: compilationOptions); }
/// <summary> /// Verifies that /// 1. <paramref name="fix"/> supports fixing diagnostics reported by <paramref name="analyzer"/>. /// 2. <paramref name="before"/> produces diagnostics fixable by <paramref name="fix"/>. /// 3. Applying <paramref name="fix"/> results in <paramref name="after"/>. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="before"/> with.</param> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply on the <see cref="Diagnostic"/> reported.</param> /// <param name="before">The code to analyze with <paramref name="analyzer"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="after">The expected code produced by applying <paramref name="fix"/>.</param> /// <param name="fixTitle">The expected title of the fix. Must be provided if more than one code action is registered.</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void CodeFix( DiagnosticAnalyzer analyzer, CodeFixProvider fix, IReadOnlyList <string> before, string after, string?fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { CodeFix( analyzer: analyzer, fix: fix, diagnosticsAndSources: DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, before), after: MergeFixedCode(before, after), fixTitle: fixTitle, allowCompilationErrors: allowCompilationErrors, suppressWarnings: suppressWarnings, metadataReferences: metadataReferences, compilationOptions: compilationOptions); }
/// <summary> /// Verifies that /// 1. <paramref name="fix"/> supports fixing <paramref name="expectedDiagnostic"/>. /// 2. <paramref name="before"/> produces diagnostics fixable by <paramref name="fix"/>. /// 3. Applying <paramref name="fix"/> results in <paramref name="after"/>. /// </summary> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply on the <see cref="Diagnostic"/> reported.</param> /// <param name="expectedDiagnostic">The <see cref="ExpectedDiagnostic"/> with information about the expected <see cref="Diagnostic"/>.</param> /// <param name="before">The code to analyze for <paramref name="expectedDiagnostic"/>. Indicate error position with ↓ (alt + 25).</param> /// <param name="after">The expected code produced by applying <paramref name="fix"/>.</param> /// <param name="fixTitle">The expected title of the fix. Must be provided if more than one code action is registered.</param> /// <param name="allowCompilationErrors">Specify if compilation errors are accepted in the fixed code. This can be for example syntax errors. Default value is <see cref="AllowCompilationErrors.No"/>.</param> /// <param name="suppressWarnings">A collection of <see cref="DiagnosticDescriptor.Id"/> to suppress when analyzing the code. Default is <see langword="null" /> meaning <see cref="SuppressedDiagnostics"/> are used.</param> /// <param name="metadataReferences">A collection of <see cref="MetadataReference"/> to use when compiling. Default is <see langword="null" /> meaning <see cref="MetadataReferences"/> are used.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> public static void CodeFix( CodeFixProvider fix, ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> before, IReadOnlyList <string> after, string?fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No, IEnumerable <string>?suppressWarnings = null, IEnumerable <MetadataReference>?metadataReferences = null, CSharpCompilationOptions?compilationOptions = null) { CodeFix( analyzer: new PlaceholderAnalyzer(expectedDiagnostic.Id), fix: fix, diagnosticsAndSources: DiagnosticsAndSources.Create(expectedDiagnostic, before), after: after, fixTitle: fixTitle, allowCompilationErrors: allowCompilationErrors, suppressWarnings: suppressWarnings, metadataReferences: metadataReferences, compilationOptions: compilationOptions); }
private static async Task FixAllByScopeAsync(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> fixedCode, string fixTitle, AllowCompilationErrors allowCompilationErrors, Solution solution, FixAllScope scope) { VerifyCodeFixSupportsAnalyzer(analyzer, codeFix); var fixedSolution = await Fix.ApplyAllFixableScopeByScopeAsync(solution, analyzer, codeFix, scope, fixTitle, CancellationToken.None).ConfigureAwait(false); await AreEqualAsync(fixedCode, fixedSolution, $"Applying fixes for {scope} failed.").ConfigureAwait(false); if (allowCompilationErrors == AllowCompilationErrors.No) { await VerifyNoCompilerErrorsAsync(codeFix, fixedSolution).ConfigureAwait(false); } }
private static async Task FixAllOneByOneAsync(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> fixedCode, string fixTitle, AllowCompilationErrors allowCompilationErrors, Solution solution) { var fixedSolution = await Fix.ApplyAllFixableOneByOneAsync(solution, analyzer, codeFix, fixTitle, CancellationToken.None).ConfigureAwait(false); await AreEqualAsync(fixedCode, fixedSolution, "Applying fixes one by one failed.").ConfigureAwait(false); if (allowCompilationErrors == AllowCompilationErrors.No) { await VerifyNoCompilerErrorsAsync(codeFix, fixedSolution).ConfigureAwait(false); } }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="suppressedDiagnostics">The diagnostics to suppress when compiling.</param> /// <param name="metadataReferences">The meta data metadataReferences to add to the compilation.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> /// <param name="scope">The scope to apply fixes for.</param> public static void FixAllByScope(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> codeWithErrorsIndicated, IReadOnlyList <string> fixedCode, string fixTitle, IEnumerable <string> suppressedDiagnostics, IEnumerable <MetadataReference> metadataReferences, AllowCompilationErrors allowCompilationErrors, FixAllScope scope) { var diagnosticsAndSources = DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, codeWithErrorsIndicated); VerifyAnalyzerSupportsDiagnostics(analyzer, diagnosticsAndSources.ExpectedDiagnostics); VerifyCodeFixSupportsAnalyzer(analyzer, codeFix); var sln = CodeFactory.CreateSolution(diagnosticsAndSources, analyzer, suppressedDiagnostics, metadataReferences); var diagnostics = Analyze.GetDiagnostics(sln, analyzer); VerifyDiagnostics(diagnosticsAndSources, diagnostics); FixAllByScope(analyzer, codeFix, sln, fixedCode, fixTitle, allowCompilationErrors, scope); }
/// <summary> /// Verifies that /// 1. <paramref name="diagnosticsAndSources"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="diagnosticsAndSources">The code and expected diagnostics.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="suppressedDiagnostics">The diagnostics to suppress when compiling.</param> /// <param name="metadataReferences">The meta data metadataReferences to add to the compilation.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, DiagnosticsAndSources diagnosticsAndSources, IReadOnlyList <string> fixedCode, IEnumerable <string> suppressedDiagnostics, IEnumerable <MetadataReference> metadataReferences, string fixTitle, AllowCompilationErrors allowCompilationErrors) { VerifyAnalyzerSupportsDiagnostics(analyzer, diagnosticsAndSources.ExpectedDiagnostics); VerifyCodeFixSupportsAnalyzer(analyzer, codeFix); var sln = CodeFactory.CreateSolution(diagnosticsAndSources, analyzer, suppressedDiagnostics, metadataReferences); var diagnostics = Analyze.GetDiagnostics(analyzer, sln); VerifyDiagnostics(diagnosticsAndSources, diagnostics); FixAllOneByOne(analyzer, codeFix, sln, fixedCode, fixTitle, allowCompilationErrors); var fixAllProvider = codeFix.GetFixAllProvider(); if (fixAllProvider != null) { foreach (var scope in fixAllProvider.GetSupportedFixAllScopes()) { FixAllByScope(analyzer, codeFix, sln, fixedCode, fixTitle, allowCompilationErrors, scope); } } }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TAnalyzer">The type of the analyzer.</typeparam> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll <TAnalyzer, TCodeFix>(IReadOnlyList <string> codeWithErrorsIndicated, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { var analyzer = new TAnalyzer(); FixAll( analyzer, new TCodeFix(), DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, codeWithErrorsIndicated), MergeFixedCodeWithErrorsIndicated(codeWithErrorsIndicated, fixedCode), SuppressedDiagnostics, MetadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TAnalyzer">The type of the analyzer.</typeparam> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll <TAnalyzer, TCodeFix>(ExpectedDiagnostic expectedDiagnostic, string codeWithErrorsIndicated, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { var analyzer = new TAnalyzer(); var codeFix = new TCodeFix(); FixAll( analyzer, codeFix, DiagnosticsAndSources.Create(expectedDiagnostic, new[] { codeWithErrorsIndicated }), new[] { fixedCode }, SuppressedDiagnostics, MetadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="metadataReference">The meta data metadataReference to add to the compilation.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> /// <param name="scope">The scope to apply fixes for.</param> public static async Task FixAllByScopeAsync(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> codeWithErrorsIndicated, IReadOnlyList <string> fixedCode, IReadOnlyList <MetadataReference> metadataReference, string fixTitle, AllowCompilationErrors allowCompilationErrors, FixAllScope scope) { var data = await CreateDiagnosticsMetadataAsync( analyzer, codeFix, DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, codeWithErrorsIndicated), CodeFactory.DefaultCompilationOptions(analyzer, SuppressedDiagnostics), metadataReference); await FixAllByScopeAsync(analyzer, codeFix, fixedCode, fixTitle, allowCompilationErrors, data, scope); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="metadataReferences">The meta data references to use when compiling the code.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, ExpectedDiagnostic expectedDiagnostic, string codeWithErrorsIndicated, string fixedCode, IEnumerable <MetadataReference> metadataReferences = null, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { FixAll( analyzer, codeFix, DiagnosticsAndSources.Create(expectedDiagnostic, new[] { codeWithErrorsIndicated }), MergeFixedCodeWithErrorsIndicated(new[] { codeWithErrorsIndicated }, fixedCode), SuppressedDiagnostics, metadataReferences ?? MetadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="code">The code to analyze.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll <TCodeFix>(ExpectedDiagnostic expectedDiagnostic, string code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TCodeFix : CodeFixProvider, new() { var analyzer = new PlaceholderAnalyzer(expectedDiagnostic.Id); FixAll( analyzer, new TCodeFix(), DiagnosticsAndSources.Create(expectedDiagnostic, new[] { code }), new[] { fixedCode }, SuppressedDiagnostics, MetadataReferences, fixTitle, allowCompilationErrors); }
public static void FixAllInDocument <TCodeFix>(string id, string codeWithErrorsIndicated, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TCodeFix : CodeFixProvider, new() { var analyzer = new PlaceholderAnalyzer(id); FixAllByScopeAsync( analyzer, new TCodeFix(), new[] { codeWithErrorsIndicated }, new[] { fixedCode }, MetadataReferences, fixTitle, allowCompilationErrors, FixAllScope.Document) .GetAwaiter() .GetResult(); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="fix">The <see cref="CodeFixProvider"/> to apply.</param> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="code">The code to analyze.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll(CodeFixProvider fix, ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> code, IReadOnlyList <string> fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { var analyzer = new PlaceholderAnalyzer(expectedDiagnostic.Id); FixAll( analyzer, fix, DiagnosticsAndSources.Create(expectedDiagnostic, code), fixedCode, SuppressedDiagnostics, MetadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="code">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void CodeFix(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { AssertCodeFixCanFixDiagnosticsFromAnalyzer(analyzer, codeFix); AssertAnalyzerSupportsExpectedDiagnostic(analyzer, expectedDiagnostic, out var descriptor, out var suppressedDiagnostics); CodeFixAsync( analyzer, codeFix, DiagnosticsAndSources.Create(expectedDiagnostic, code), fixedCode, fixTitle, CodeFactory.DefaultCompilationOptions(descriptor, SuppressedDiagnostics.Concat(suppressedDiagnostics)), MetadataReferences, allowCompilationErrors) .GetAwaiter() .GetResult(); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="metadataReferences">The meta data references to use when compiling the code.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> codeWithErrorsIndicated, IReadOnlyList <string> fixedCode, IEnumerable <MetadataReference> metadataReferences, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { FixAll( analyzer, codeFix, DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, codeWithErrorsIndicated), fixedCode, SuppressedDiagnostics, metadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="code">The code to analyze.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void CodeFix <TCodeFix>(ExpectedDiagnostic expectedDiagnostic, string code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TCodeFix : CodeFixProvider, new() { var analyzer = new PlaceholderAnalyzer(expectedDiagnostic.Id); CodeFixAsync( analyzer, new TCodeFix(), DiagnosticsAndSources.Create(expectedDiagnostic, new[] { code }), fixedCode, fixTitle, CodeFactory.DefaultCompilationOptions(analyzer, SuppressedDiagnostics), MetadataReferences, allowCompilationErrors) .GetAwaiter() .GetResult(); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TAnalyzer">The type of the analyzer.</typeparam> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAllInDocument <TAnalyzer, TCodeFix>(string codeWithErrorsIndicated, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { var analyzer = new TAnalyzer(); FixAllByScope( analyzer, new TCodeFix(), new[] { codeWithErrorsIndicated }, new[] { fixedCode }, fixTitle, SuppressedDiagnostics, MetadataReferences, allowCompilationErrors, FixAllScope.Document); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="code">The code to analyze.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void CodeFix <TCodeFix>(ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TCodeFix : CodeFixProvider, new() { var analyzer = new PlaceholderAnalyzer(expectedDiagnostic.Id); AssertAnalyzerSupportsExpectedDiagnostic(analyzer, expectedDiagnostic, out var descriptor, out var suppressedDiagnostics); CodeFixAsync( analyzer, new TCodeFix(), DiagnosticsAndSources.Create(expectedDiagnostic, code), fixedCode, fixTitle, CodeFactory.DefaultCompilationOptions(descriptor, SuppressedDiagnostics.Concat(suppressedDiagnostics)), MetadataReferences, allowCompilationErrors) .GetAwaiter() .GetResult(); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TAnalyzer">The type of the analyzer.</typeparam> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAllOneByOne <TAnalyzer, TCodeFix>(string codeWithErrorsIndicated, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { var analyzer = new TAnalyzer(); var diagnosticsAndSources = DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, codeWithErrorsIndicated); VerifyAnalyzerSupportsDiagnostics(analyzer, diagnosticsAndSources.ExpectedDiagnostics); var codeFix = new TCodeFix(); VerifyCodeFixSupportsAnalyzer(analyzer, codeFix); var sln = CodeFactory.CreateSolution(diagnosticsAndSources, analyzer, SuppressedDiagnostics, MetadataReferences); var diagnostics = Analyze.GetDiagnostics(analyzer, sln); VerifyDiagnostics(diagnosticsAndSources, diagnostics); FixAllOneByOne(analyzer, codeFix, sln, new[] { fixedCode }, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="diagnosticsAndSources"/> produces the expected diagnostics when analyzed. /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="diagnosticsAndSources">The code and expected diagnostics.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/> to use.</param> /// <param name="metadataReferences">The meta data metadataReferences to add to the compilation.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task CodeFixAsync(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, DiagnosticsAndSources diagnosticsAndSources, string fixedCode, string fixTitle, CSharpCompilationOptions compilationOptions, IReadOnlyList <MetadataReference> metadataReferences, AllowCompilationErrors allowCompilationErrors) { AssertCodeFixCanFixDiagnosticsFromAnalyzer(analyzer, codeFix); var data = await DiagnosticsWithMetadataAsync(analyzer, diagnosticsAndSources, compilationOptions, metadataReferences).ConfigureAwait(false); var fixableDiagnostics = data.ActualDiagnostics.SelectMany(x => x) .Where(x => codeFix.FixableDiagnosticIds.Contains(x.Id)) .ToArray(); if (fixableDiagnostics.Length == 0) { var message = $"Code analyzed with {analyzer} did not generate any diagnostics fixable by {codeFix}.{Environment.NewLine}" + $"The analyzed code contained the following diagnostics: {{{string.Join(", ", data.ExpectedDiagnostics.Select(d => d.Id))}}}{Environment.NewLine}" + $"The code fix supports the following diagnostics: {{{string.Join(", ", codeFix.FixableDiagnosticIds)}}}"; throw AssertException.Create(message); } if (fixableDiagnostics.Length > 1) { var message = $"Code analyzed with {analyzer} generated more than one diagnostic fixable by {codeFix}.{Environment.NewLine}" + $"The analyzed code contained the following diagnostics: {{{string.Join(", ", data.ExpectedDiagnostics.Select(d => d.Id))}}}{Environment.NewLine}" + $"The code fix supports the following diagnostics: {{{string.Join(", ", codeFix.FixableDiagnosticIds)}}}{Environment.NewLine}" + $"Maybe you meant to call AnalyzerAssert.FixAll?"; throw AssertException.Create(message); } var diagnostic = fixableDiagnostics.Single(); var fixedSolution = await Fix.ApplyAsync(data.Solution, codeFix, diagnostic, fixTitle, CancellationToken.None).ConfigureAwait(false); if (ReferenceEquals(data.Solution, fixedSolution)) { throw AssertException.Create($"{codeFix} did not change any document."); } var fixedSource = await CodeReader.GetStringFromDocumentAsync( fixedSolution.GetDocument(data.Solution.GetDocument(diagnostic.Location.SourceTree).Id), Formatter.Annotation, CancellationToken.None) .ConfigureAwait(false); CodeAssert.AreEqual(fixedCode, fixedSource); if (allowCompilationErrors == AllowCompilationErrors.No) { await AssertNoCompilerErrorsAsync(codeFix, fixedSolution).ConfigureAwait(false); } }
private static void FixAllByScope(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, Solution sln, IReadOnlyList <string> fixedCode, string fixTitle, AllowCompilationErrors allowCompilationErrors, FixAllScope scope) { VerifyCodeFixSupportsAnalyzer(analyzer, codeFix); var fixedSolution = Fix.ApplyAllFixableScopeByScopeAsync(sln, analyzer, codeFix, scope, fixTitle, CancellationToken.None).GetAwaiter().GetResult(); AreEqualAsync(fixedCode, fixedSolution, $"Applying fixes for {scope} failed.").GetAwaiter().GetResult(); if (allowCompilationErrors == AllowCompilationErrors.No) { VerifyNoCompilerErrorsAsync(codeFix, fixedSolution).GetAwaiter().GetResult(); } }
public static void CodeFix <TCodeFix>(string id, IReadOnlyList <string> code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TCodeFix : CodeFixProvider, new() { var analyzer = new PlaceholderAnalyzer(id); CodeFixAsync( analyzer, new TCodeFix(), DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, code), fixedCode, fixTitle, CodeFactory.DefaultCompilationOptions(analyzer, SuppressedDiagnostics), MetadataReferences, allowCompilationErrors) .GetAwaiter() .GetResult(); }
/// <summary> /// Verifies that /// 1. <paramref name="codeWithErrorsIndicated"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <typeparam name="TAnalyzer">The type of the analyzer.</typeparam> /// <typeparam name="TCodeFix">The type of the code fix.</typeparam> /// <param name="expectedDiagnostic">The expected diagnostic.</param> /// <param name="codeWithErrorsIndicated">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void FixAll <TAnalyzer, TCodeFix>(ExpectedDiagnostic expectedDiagnostic, IReadOnlyList <string> codeWithErrorsIndicated, IReadOnlyList <string> fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { FixAll( new TAnalyzer(), new TCodeFix(), DiagnosticsAndSources.Create(expectedDiagnostic, codeWithErrorsIndicated), fixedCode, SuppressedDiagnostics, MetadataReferences, fixTitle, allowCompilationErrors); }
/// <summary> /// Verifies that /// 1. <paramref name="code"/> produces the expected diagnostics /// 2. The code fix fixes the code. /// </summary> /// <param name="analyzer">The analyzer to run on the code..</param> /// <param name="codeFix">The code fix to apply.</param> /// <param name="code">The code with error positions indicated.</param> /// <param name="fixedCode">The expected code produced by the code fix.</param> /// <param name="fixTitle">The title of the fix to apply if more than one.</param> /// <param name="allowCompilationErrors">If compilation errors are accepted in the fixed code.</param> public static void CodeFix(DiagnosticAnalyzer analyzer, CodeFixProvider codeFix, IReadOnlyList <string> code, string fixedCode, string fixTitle = null, AllowCompilationErrors allowCompilationErrors = AllowCompilationErrors.No) { CodeFixAsync( analyzer, codeFix, DiagnosticsAndSources.CreateFromCodeWithErrorsIndicated(analyzer, code), fixedCode, fixTitle, CodeFactory.DefaultCompilationOptions(analyzer, SuppressedDiagnostics), MetadataReferences, allowCompilationErrors) .GetAwaiter() .GetResult(); }