internal static FixAllCodeActionContext Create( Project project, FixAllProviderInfo fixAllProviderInfo, CodeFixProvider originalFixProvider, IEnumerable<Diagnostic> originalFixDiagnostics, Func<Document, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getDocumentDiagnosticsAsync, Func<Project, bool, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getProjectDiagnosticsAsync, CancellationToken cancellationToken) { var diagnosticIds = GetFixAllDiagnosticIds(fixAllProviderInfo, originalFixDiagnostics).ToImmutableHashSet(); var diagnosticProvider = new FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); return new FixAllCodeActionContext(project, fixAllProviderInfo, originalFixProvider, originalFixDiagnostics, diagnosticIds, diagnosticProvider, cancellationToken); }
private FixAllCodeActionContext( Project project, FixAllProviderInfo fixAllProviderInfo, CodeFixProvider originalFixProvider, IEnumerable<Diagnostic> originalFixDiagnostics, ImmutableHashSet<string> diagnosticIds, FixAllDiagnosticProvider diagnosticProvider, CancellationToken cancellationToken) : base(project, originalFixProvider, FixAllScope.Project, null, diagnosticIds, diagnosticProvider, cancellationToken) { _fixAllProviderInfo = fixAllProviderInfo; _originalFixDiagnostics = originalFixDiagnostics; _diagnosticProvider = diagnosticProvider; }
public RunFixAllCodeActionService(ICsDiagnosticWorker diagnosticWorker, [ImportMany] IEnumerable <ICodeActionProvider> providers, CachingCodeFixProviderForProjects codeFixProvider, OmniSharpWorkspace workspace, ILoggerFactory loggerFactory) : base( workspace, providers, loggerFactory.CreateLogger <RunFixAllCodeActionService>(), diagnosticWorker, codeFixProvider) { _logger = loggerFactory.CreateLogger <RunFixAllCodeActionService>(); _fixAllDiagnosticProvider = new FixAllDiagnosticProvider(diagnosticWorker); }
internal static FixAllState Create( FixAllProvider fixAllProvider, Project project, FixAllProviderInfo fixAllProviderInfo, CodeFixProvider originalFixProvider, IEnumerable <Diagnostic> originalFixDiagnostics, Func <Document, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getDocumentDiagnosticsAsync, Func <Project, bool, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getProjectDiagnosticsAsync) { var diagnosticIds = GetFixAllDiagnosticIds(fixAllProviderInfo, originalFixDiagnostics).ToImmutableHashSet(); var diagnosticProvider = new FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); return(new FixAllState( fixAllProvider: fixAllProvider, project: project, codeFixProvider: originalFixProvider, scope: FixAllScope.Project, codeActionEquivalenceKey: null, diagnosticIds: diagnosticIds, fixAllDiagnosticProvider: diagnosticProvider)); }
internal FixAllState CreateFixAllState( FixAllProvider fixAllProvider, Document document, FixAllProviderInfo fixAllProviderInfo, CodeFixProvider originalFixProvider, IEnumerable <Diagnostic> originalFixDiagnostics, Func <Document, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getDocumentDiagnosticsAsync, Func <Project, bool, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getProjectDiagnosticsAsync) { var diagnosticIds = originalFixDiagnostics.Where(fixAllProviderInfo.CanBeFixed) .Select(d => d.Id) .ToImmutableHashSet(); var diagnosticProvider = new FixAllDiagnosticProvider(this, diagnosticIds); return(new FixAllState( fixAllProvider: fixAllProvider, document: document, codeFixProvider: originalFixProvider, scope: FixAllScope.Document, codeActionEquivalenceKey: null, diagnosticIds: diagnosticIds, fixAllDiagnosticProvider: diagnosticProvider)); }
private static void RunFixAllProvider(DiagnosticAnalyzer diagnosticAnalyzer, CodeFixProvider codeFixProvider, string codeFixTitle, FixAllProvider fixAllProvider, Document document, ParseOptions parseOption, string pathToExpected) { var currentDocument = document; var state = new DocumentState(diagnosticAnalyzer, currentDocument, parseOption); state.Diagnostics.Should().NotBeEmpty(); var fixAllDiagnosticProvider = new FixAllDiagnosticProvider( codeFixProvider.FixableDiagnosticIds.ToHashSet(), (doc, ids, ct) => Task.FromResult(state.Diagnostics.AsEnumerable()), null); var fixAllContext = new FixAllContext(currentDocument, codeFixProvider, FixAllScope.Document, codeFixTitle, codeFixProvider.FixableDiagnosticIds, fixAllDiagnosticProvider, CancellationToken.None); var codeActionToExecute = fixAllProvider.GetFixAsync(fixAllContext).Result; codeActionToExecute.Should().NotBeNull(); currentDocument = ApplyCodeFix(currentDocument, codeActionToExecute); state = new DocumentState(diagnosticAnalyzer, currentDocument, parseOption); AreEqualIgnoringLineEnding(pathToExpected, state); }
void PopulateFixes (FixMenuDescriptor menu, ref int items) { int mnemonic = 1; bool gotImportantFix = false, addedSeparator = false; foreach (var fix_ in GetCurrentFixes ().CodeFixActions.OrderByDescending (i => Tuple.Create (IsAnalysisOrErrorFix (i.CodeAction), (int)0, GetUsage (i.CodeAction.EquivalenceKey)))) { // filter out code actions that are already resolutions of a code issue if (IsAnalysisOrErrorFix (fix_.CodeAction)) gotImportantFix = true; if (!addedSeparator && gotImportantFix && !IsAnalysisOrErrorFix (fix_.CodeAction)) { menu.Add (FixMenuEntry.Separator); addedSeparator = true; } var fix = fix_; var label = CreateLabel (fix.CodeAction.Title, ref mnemonic); var thisInstanceMenuItem = new FixMenuEntry (label, delegate { new ContextActionRunner (fix.CodeAction, Editor, DocumentContext).Run (null, EventArgs.Empty); ConfirmUsage (fix.CodeAction.EquivalenceKey); }); menu.Add (thisInstanceMenuItem); items++; } bool first = true; foreach (var fix in GetCurrentFixes ().CodeRefactoringActions) { if (first) { if (items > 0) menu.Add (FixMenuEntry.Separator); first = false; } var label = CreateLabel (fix.CodeAction.Title, ref mnemonic); var thisInstanceMenuItem = new FixMenuEntry (label, delegate { new ContextActionRunner (fix.CodeAction, Editor, DocumentContext).Run (null, EventArgs.Empty); ConfirmUsage (fix.CodeAction.EquivalenceKey); }); menu.Add (thisInstanceMenuItem); items++; } first = false; foreach (var fix_ in GetCurrentFixes ().DiagnosticsAtCaret) { var fix = fix_; var label = GettextCatalog.GetString ("_Options for \"{0}\"", fix.GetMessage ()); var subMenu = new FixMenuDescriptor (label); CodeDiagnosticDescriptor descriptor = BuiltInCodeDiagnosticProvider.GetCodeDiagnosticDescriptor (fix.Id); if (descriptor == null) continue; if (first) { menu.Add (FixMenuEntry.Separator); first = false; } // if (inspector.CanSuppressWithAttribute) { // var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with attribute"), // delegate { // // inspector.SuppressWithAttribute (Editor, DocumentContext, GetTextSpan (fix.Item2)); // }); // subMenu.Add (menuItem); // } if (descriptor.CanDisableWithPragma) { var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with #pragma"), delegate { descriptor.DisableWithPragma (Editor, DocumentContext, fix); }); subMenu.Add (menuItem); menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with file"), delegate { descriptor.DisableWithFile (Editor, DocumentContext, fix); }); subMenu.Add (menuItem); } var optionsMenuItem = new FixMenuEntry (GettextCatalog.GetString ("_Configure Rule"), delegate { IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "C#", dialog => { var panel = dialog.GetPanel<CodeIssuePanel> ("C#"); if (panel == null) return; panel.Widget.SelectCodeIssue (descriptor.IdString); }); }); subMenu.Add (optionsMenuItem); foreach (var fix2 in GetCurrentFixes ().CodeFixActions.OrderByDescending (i => Tuple.Create (IsAnalysisOrErrorFix (i.CodeAction), (int)0, GetUsage (i.CodeAction.EquivalenceKey)))) { var provider = fix2.Diagnostic.GetCodeFixProvider ().GetFixAllProvider (); if (provider == null) continue; if (!provider.GetSupportedFixAllScopes ().Contains (FixAllScope.Document)) continue; var subMenu2 = new FixMenuDescriptor (GettextCatalog.GetString ("Fix all")); var diagnosticAnalyzer = fix2.Diagnostic.GetCodeDiagnosticDescriptor (LanguageNames.CSharp).GetProvider (); if (!diagnosticAnalyzer.SupportedDiagnostics.Contains (fix.Descriptor)) continue; var menuItem = new FixMenuEntry ( GettextCatalog.GetString ("In _Document"), async delegate { var fixAllDiagnosticProvider = new FixAllDiagnosticProvider (diagnosticAnalyzer.SupportedDiagnostics.Select (d => d.Id).ToImmutableHashSet (), async (Microsoft.CodeAnalysis.Document doc, ImmutableHashSet<string> diagnostics, CancellationToken token) => { var model = await doc.GetSemanticModelAsync (token); var compilationWithAnalyzer = model.Compilation.WithAnalyzers (new [] { diagnosticAnalyzer }.ToImmutableArray (), null, token); return await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync (model, null, token); }, (Project arg1, bool arg2, ImmutableHashSet<string> arg3, CancellationToken arg4) => { return Task.FromResult ((IEnumerable<Diagnostic>)new Diagnostic[] { }); }); var ctx = new FixAllContext ( this.DocumentContext.AnalysisDocument, fix2.Diagnostic.GetCodeFixProvider (), FixAllScope.Document, fix2.CodeAction.EquivalenceKey, diagnosticAnalyzer.SupportedDiagnostics.Select (d => d.Id), fixAllDiagnosticProvider, default (CancellationToken) ); var fixAll = await provider.GetFixAsync (ctx); using (var undo = Editor.OpenUndoGroup ()) { CodeDiagnosticDescriptor.RunAction (DocumentContext, fixAll, default (CancellationToken)); } }); subMenu2.Add (menuItem); subMenu.Add (FixMenuEntry.Separator); subMenu.Add (subMenu2); } menu.Add (subMenu); items++; } }
void PopulateFixes(FixMenuDescriptor menu, ref int items) { int mnemonic = 1; bool gotImportantFix = false, addedSeparator = false; foreach (var fix_ in GetCurrentFixes().CodeFixActions.OrderByDescending(i => Tuple.Create(IsAnalysisOrErrorFix(i.CodeAction), (int)0, GetUsage(i.CodeAction.EquivalenceKey)))) { // filter out code actions that are already resolutions of a code issue if (IsAnalysisOrErrorFix(fix_.CodeAction)) { gotImportantFix = true; } if (!addedSeparator && gotImportantFix && !IsAnalysisOrErrorFix(fix_.CodeAction)) { menu.Add(FixMenuEntry.Separator); addedSeparator = true; } var fix = fix_; var label = CreateLabel(fix.CodeAction.Title, ref mnemonic); var thisInstanceMenuItem = new FixMenuEntry(label, async delegate { await new ContextActionRunner(fix.CodeAction, Editor, DocumentContext).Run(); ConfirmUsage(fix.CodeAction.EquivalenceKey); }); menu.Add(thisInstanceMenuItem); items++; } bool first = true; foreach (var fix in GetCurrentFixes().CodeRefactoringActions) { if (first) { if (items > 0) { menu.Add(FixMenuEntry.Separator); } first = false; } var label = CreateLabel(fix.CodeAction.Title, ref mnemonic); var thisInstanceMenuItem = new FixMenuEntry(label, async delegate { await new ContextActionRunner(fix.CodeAction, Editor, DocumentContext).Run(); ConfirmUsage(fix.CodeAction.EquivalenceKey); }); menu.Add(thisInstanceMenuItem); items++; } first = false; var warningsAtCaret = (DocumentContext.AnalysisDocument.GetSemanticModelAsync().Result) .GetDiagnostics(new TextSpan(Editor.CaretOffset, 0)) .Where(diag => diag.Severity == DiagnosticSeverity.Warning).ToList(); foreach (var warning in warningsAtCaret) { var label = GettextCatalog.GetString("_Options for \"{0}\"", warning.Descriptor.Title); var subMenu = new FixMenuDescriptor(label); if (first) { menu.Add(FixMenuEntry.Separator); first = false; } var menuItem = new FixMenuEntry(GettextCatalog.GetString("_Suppress with #pragma"), async delegate { var fixes = await CSharpSuppressionFixProvider.Instance.GetSuppressionsAsync(DocumentContext.AnalysisDocument, new TextSpan(Editor.CaretOffset, 0), new [] { warning }, default(CancellationToken)).ConfigureAwait(false); foreach (var f in fixes) { CodeDiagnosticDescriptor.RunAction(DocumentContext, f.Action, default(CancellationToken)); } } ); subMenu.Add(menuItem); menu.Add(subMenu); items++; } foreach (var fix_ in GetCurrentFixes().DiagnosticsAtCaret) { var fix = fix_; var label = GettextCatalog.GetString("_Options for \"{0}\"", fix.GetMessage()); var subMenu = new FixMenuDescriptor(label); CodeDiagnosticDescriptor descriptor = BuiltInCodeDiagnosticProvider.GetCodeDiagnosticDescriptor(fix.Id); if (descriptor == null) { continue; } if (first) { menu.Add(FixMenuEntry.Separator); first = false; } // if (inspector.CanSuppressWithAttribute) { // var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with attribute"), // delegate { // // inspector.SuppressWithAttribute (Editor, DocumentContext, GetTextSpan (fix.Item2)); // }); // subMenu.Add (menuItem); // } if (descriptor.CanDisableWithPragma) { var menuItem = new FixMenuEntry(GettextCatalog.GetString("_Suppress with #pragma"), delegate { descriptor.DisableWithPragma(Editor, DocumentContext, fix); }); subMenu.Add(menuItem); menuItem = new FixMenuEntry(GettextCatalog.GetString("_Suppress with file"), delegate { descriptor.DisableWithFile(Editor, DocumentContext, fix); }); subMenu.Add(menuItem); } var optionsMenuItem = new FixMenuEntry(GettextCatalog.GetString("_Configure Rule"), delegate { IdeApp.Workbench.ShowGlobalPreferencesDialog(null, "C#", dialog => { var panel = dialog.GetPanel <CodeIssuePanel> ("C#"); if (panel == null) { return; } panel.Widget.SelectCodeIssue(descriptor.IdString); }); }); subMenu.Add(optionsMenuItem); foreach (var fix2 in GetCurrentFixes().CodeFixActions.OrderByDescending(i => Tuple.Create(IsAnalysisOrErrorFix(i.CodeAction), (int)0, GetUsage(i.CodeAction.EquivalenceKey)))) { var provider = fix2.Diagnostic.GetCodeFixProvider().GetFixAllProvider(); if (provider == null) { continue; } if (!provider.GetSupportedFixAllScopes().Contains(FixAllScope.Document)) { continue; } var subMenu2 = new FixMenuDescriptor(GettextCatalog.GetString("Fix all")); var diagnosticAnalyzer = fix2.Diagnostic.GetCodeDiagnosticDescriptor(LanguageNames.CSharp).GetProvider(); if (!diagnosticAnalyzer.SupportedDiagnostics.Contains(fix.Descriptor)) { continue; } var menuItem = new FixMenuEntry( GettextCatalog.GetString("In _Document"), async delegate { var fixAllDiagnosticProvider = new FixAllDiagnosticProvider(diagnosticAnalyzer.SupportedDiagnostics.Select(d => d.Id).ToImmutableHashSet(), async(Microsoft.CodeAnalysis.Document doc, ImmutableHashSet <string> diagnostics, CancellationToken token) => { var model = await doc.GetSemanticModelAsync(token); var compilationWithAnalyzer = model.Compilation.WithAnalyzers(new [] { diagnosticAnalyzer }.ToImmutableArray(), null, token); return(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, token)); }, (Project arg1, bool arg2, ImmutableHashSet <string> arg3, CancellationToken arg4) => { return(Task.FromResult((IEnumerable <Diagnostic>) new Diagnostic [] { })); }); var ctx = new FixAllContext( this.DocumentContext.AnalysisDocument, fix2.Diagnostic.GetCodeFixProvider(), FixAllScope.Document, fix2.CodeAction.EquivalenceKey, diagnosticAnalyzer.SupportedDiagnostics.Select(d => d.Id), fixAllDiagnosticProvider, default(CancellationToken) ); var fixAll = await provider.GetFixAsync(ctx); using (var undo = Editor.OpenUndoGroup()) { CodeDiagnosticDescriptor.RunAction(DocumentContext, fixAll, default(CancellationToken)); } }); subMenu2.Add(menuItem); subMenu.Add(FixMenuEntry.Separator); subMenu.Add(subMenu2); } menu.Add(subMenu); items++; } }
internal static FixAllState Create( FixAllProvider fixAllProvider, Project project, FixAllProviderInfo fixAllProviderInfo, CodeFixProvider originalFixProvider, IEnumerable<Diagnostic> originalFixDiagnostics, Func<Document, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getDocumentDiagnosticsAsync, Func<Project, bool, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getProjectDiagnosticsAsync) { var diagnosticIds = GetFixAllDiagnosticIds(fixAllProviderInfo, originalFixDiagnostics).ToImmutableHashSet(); var diagnosticProvider = new FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); return new FixAllState( fixAllProvider: fixAllProvider, project: project, codeFixProvider: originalFixProvider, scope: FixAllScope.Project, codeActionEquivalenceKey: null, diagnosticIds: diagnosticIds, fixAllDiagnosticProvider: diagnosticProvider); }
private async Task AppendFixesOrSuppressionsAsync( Document document, TextSpan span, IEnumerable <DiagnosticData> diagnosticsWithSameSpan, IList <CodeFixCollection> result, object fixer, Func <Diagnostic, bool> hasFix, Func <ImmutableArray <Diagnostic>, Task <ImmutableArray <CodeFix> > > getFixes, CancellationToken cancellationToken) { var allDiagnostics = await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity) .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false); var diagnostics = allDiagnostics.Where(hasFix).AsImmutable(); if (diagnostics.Length <= 0) { // this can happen for suppression case where all diagnostics can't be suppressed return; } var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>(); var fixes = await extensionManager.PerformFunctionAsync(fixer, () => getFixes(diagnostics), defaultValue : ImmutableArray <CodeFix> .Empty).ConfigureAwait(false); if (fixes.IsDefaultOrEmpty) { return; } // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context. var fixAllProviderInfo = extensionManager.PerformFunction(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null); FixAllState fixAllState = null; var supportedScopes = ImmutableArray <FixAllScope> .Empty; var diagnosticIds = GetFixAllDiagnosticIds(fixAllProviderInfo, diagnostics).ToImmutableHashSet(); var diagnosticProvider = new FixAllDiagnosticProvider(diagnosticIds, GetDocumentDiagnosticsAsync, GetProjectDiagnosticsAsync); if (fixAllProviderInfo != null) { var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionFixProvider)fixer, diagnosticIds); fixAllState = new FixAllState( fixAllProviderInfo.FixAllProvider, document, codeFixProvider, FixAllScope.Document, null, diagnosticIds, diagnosticProvider); supportedScopes = fixAllProviderInfo.SupportedScopes.AsImmutable(); } var codeFix = new CodeFixCollection( fixer, span, fixes, fixAllState, supportedScopes, diagnostics.First()); result.Add(codeFix); }
public Solution ApplyFixAll( Solution solution, FixAllScope fixAllScope, bool allowNewCompilerDiagnostics, int codeFixIndex, IEnumerable <TestAdditionalDocument> additionalFiles = null) { additionalFiles = additionalFiles ?? ImmutableArray <TestAdditionalDocument> .Empty; Document triggerDocument = null; Diagnostic triggerDiagnostic = null; var allFixableDiagnostics = new List <Diagnostic>(); var compilerDiagnosticMap = new Dictionary <ProjectId, ImmutableArray <Diagnostic> >(); foreach (var projectId in solution.ProjectIds) { var project = solution.GetProject(projectId); var compilation = project.GetCompilationAsync().Result; var analyzerDiagnostics = GetSortedDiagnostics(compilation, additionalFiles); var compilerDiagnostics = compilation.GetDiagnostics(); compilerDiagnosticMap.Add(project.Id, compilerDiagnostics); var fixableDiagnostics = _getFixableDiagnostics(analyzerDiagnostics.Concat(compilerDiagnostics)); allFixableDiagnostics.AddRange(fixableDiagnostics); if (triggerDiagnostic == null) { triggerDiagnostic = fixableDiagnostics.FirstOrDefault(d => _fixableDiagnosticIds.Contains(d.Id)); if (triggerDiagnostic != null) { triggerDocument = FindDocument(triggerDiagnostic, project); } } } if (triggerDiagnostic == null || triggerDocument == null) { return(solution); } List <CodeAction> actions = RegisterCodeFixes(triggerDocument, triggerDiagnostic); if (!actions.Any()) { return(solution); } if (codeFixIndex >= actions.Count) { throw new Exception($"Unable to invoke code fix at index '{codeFixIndex}', only '{actions.Count}' code fixes were registered."); } var fixAllProvider = _codeFixProvider.GetFixAllProvider(); if (fixAllProvider == null) { throw new Exception($"Requested 'testFixAll' but the underlying CodeFixProvider returned 'null' for 'GetFixAllProvider' API."); } var diagnosticProvider = new FixAllDiagnosticProvider(allFixableDiagnostics); var equivalenceKey = actions[codeFixIndex].EquivalenceKey; var fixAllContext = new FixAllContext(triggerDocument, _codeFixProvider, fixAllScope, equivalenceKey, _fixableDiagnosticIds, diagnosticProvider, CancellationToken.None); var codeAction = fixAllProvider.GetFixAsync(fixAllContext).Result; if (codeAction != null) { solution = DiagnosticFixerTestsExtensions.Apply(codeAction); foreach (var kvp in compilerDiagnosticMap) { var projectId = kvp.Key; var compilerDiagnostics = kvp.Value; var project = solution.GetProject(projectId); var updatedCompilerDiagnostics = project.GetCompilationAsync().Result.GetDiagnostics(); if (!allowNewCompilerDiagnostics) { CheckNewCompilerDiagnostics(project, compilerDiagnostics, updatedCompilerDiagnostics); } } } return(solution); }