static CodeFixMenuEntry CreateFixMenuEntry(Ide.Editor.TextEditor editor, CodeAction fix, ref int mnemonic) { var label = mnemonic < 0 ? fix.Title : CreateLabel(fix.Title, ref mnemonic); var item = new CodeFixMenuEntry(label, async delegate { await new ContextActionRunner(editor, fix).Run(); }); item.ShowPreviewTooltip = delegate(Xwt.Rectangle rect) { RefactoringPreviewTooltipWindow.ShowPreviewTooltip(editor, fix, rect); }; return(item); }
static CodeFixMenuEntry CreateFixAllMenuEntry(Ide.Editor.TextEditor editor, FixAllState fixState, ref int mnemonic, CancellationToken token) { var provider = fixState?.FixAllProvider; if (provider == null) { return(null); } var doc = editor.DocumentContext; var workspace = doc?.RoslynWorkspace; if (workspace == null) { return(null); } var title = fixState.GetDefaultFixAllTitle(); var label = mnemonic < 0 ? title : CreateLabel(title, ref mnemonic); var item = new CodeFixMenuEntry(label, async delegate { // Task.Run here so we don't end up binding the whole document on popping the menu, also there is no cancellation token support Microsoft.CodeAnalysis.Text.TextChange[] result = await Task.Run(async() => { var context = fixState.CreateFixAllContext(new RoslynProgressTracker(), token); var fix = await provider.GetFixAsync(context); var previewOperations = await fix.GetPreviewOperationsAsync(token); return(await Runtime.RunInMainThread(() => { var engine = Xwt.Toolkit.CurrentEngine; // NativeEngine return engine.Invoke(async() => { using (var dialog = new FixAllPreviewDialog(string.Join(", ", fixState.DiagnosticIds), doc.Name, fixState.Scope, previewOperations, editor)) { await dialog.InitializeEditor(); var parent = Xwt.Toolkit.CurrentEngine.WrapWindow(IdeApp.Workbench.RootWindow); var changes = dialog.Run(parent) == Xwt.Command.Apply ? dialog.GetApplicableChanges().ToArray() : Array.Empty <Microsoft.CodeAnalysis.Text.TextChange> (); return changes; } }); })); }); if (result.Length == 0) { return; } editor.ApplyTextChanges(result); }); return(item); }
static void AddConfigurationMenuEntry(Diagnostic diag, CodeDiagnosticDescriptor descriptor, Microsoft.CodeAnalysis.CodeFixes.CodeFix fix, CodeFixMenu configureMenu) { var configurable = !DescriptorHasTag(diag.Descriptor, WellKnownDiagnosticTags.NotConfigurable); if (descriptor != null && configurable) { var optionsMenuItem = new CodeFixMenuEntry(GettextCatalog.GetString("_Configure Rule \u2018{0}\u2019", diag.Descriptor.Title), delegate { IdeApp.Workbench.ShowGlobalPreferencesDialog(null, "C#", dialog => { var panel = dialog.GetPanel <CodeIssuePanel> ("C#"); if (panel == null) { return; } panel.Widget.SelectCodeIssue(fix.PrimaryDiagnostic.Descriptor.Id); }); }); configureMenu.Add(optionsMenuItem); } }
static CodeFixMenuEntry CreateFixAllMenuEntry(TextEditor editor, FixAllState fixState, ref int mnemonic, CancellationToken token) { var provider = fixState?.FixAllProvider; if (provider == null) { return(null); } var context = fixState.CreateFixAllContext(new RoslynProgressTracker(), token); var title = fixState.GetDefaultFixAllTitle(); var label = mnemonic < 0 ? title : CreateLabel(title, ref mnemonic); var item = new CodeFixMenuEntry(label, async delegate { // Task.Run here so we don't end up binding the whole document on popping the menu, also there is no cancellation token support var fix = Task.Run(() => provider.GetFixAsync(context)); await new ContextActionRunner(editor, await fix).Run(); }); return(item); }
public static async Task <CodeFixMenu> CreateFixMenu(TextEditor editor, CodeActionContainer fixes, CancellationToken cancellationToken = default(CancellationToken)) { var menu = new CodeFixMenu(); if (editor.DocumentContext.AnalysisDocument == null) { return(menu); } int mnemonic = 1; foreach (var fix in fixes.CodeFixActions.OrderByDescending(i => GetUsage(i.CodeAction.EquivalenceKey))) { AddFixMenuItem(editor, menu, ref mnemonic, fix.CodeAction); } bool first = true; foreach (var fix in fixes.CodeRefactoringActions) { if (first) { if (menu.Items.Count > 0) { menu.Add(CodeFixMenuEntry.Separator); } first = false; } AddFixMenuItem(editor, menu, ref mnemonic, fix.CodeAction); } var warningsAtCaret = (await editor.DocumentContext.AnalysisDocument.GetSemanticModelAsync(cancellationToken)) .GetDiagnostics(new TextSpan(editor.CaretOffset, 0)) .Where(diag => diag.Severity == DiagnosticSeverity.Warning).ToList(); var caretSpan = new TextSpan(editor.CaretOffset, 0); first = true; foreach (var warning in warningsAtCaret) { if (string.IsNullOrWhiteSpace(warning.Descriptor.Title.ToString())) { continue; } var label = GettextCatalog.GetString("_Options for \u2018{0}\u2019", warning.Descriptor.Title); var subMenu = new CodeFixMenu(label); await AddSuppressionMenuItems(subMenu, editor, warning, caretSpan); if (subMenu.Items.Count > 0) { if (first) { menu.Add(CodeFixMenuEntry.Separator); first = false; } menu.Add(subMenu); } } first = true; foreach (var diag in fixes.DiagnosticsAtCaret) { if (string.IsNullOrWhiteSpace(diag.Descriptor.Title.ToString())) { continue; } var notConfigurable = DescriptorHasTag(diag.Descriptor, WellKnownDiagnosticTags.NotConfigurable); var label = GettextCatalog.GetString("_Options for \u2018{0}\u2019", diag.Descriptor.Title); var subMenu = new CodeFixMenu(label); if (first) { menu.Add(CodeFixMenuEntry.Separator); first = false; } await AddSuppressionMenuItems(subMenu, editor, diag, caretSpan); var descriptor = BuiltInCodeDiagnosticProvider.GetCodeDiagnosticDescriptor(diag.Id); if (descriptor != null && IsConfigurable(diag.Descriptor)) { var optionsMenuItem = new CodeFixMenuEntry(GettextCatalog.GetString("_Configure Rule"), delegate { IdeApp.Workbench.ShowGlobalPreferencesDialog(null, "C#", dialog => { var panel = dialog.GetPanel <CodeIssuePanel> ("C#"); if (panel == null) { return; } panel.Widget.SelectCodeIssue(diag.Descriptor.Id); }); }); subMenu.Add(optionsMenuItem); } foreach (var fix in fixes.CodeFixActions.OrderByDescending(i => GetUsage(i.CodeAction.EquivalenceKey))) { if (cancellationToken.IsCancellationRequested) { return(null); } var provider = fix.Diagnostic.GetCodeFixProvider().GetFixAllProvider(); if (provider == null) { continue; } if (!provider.GetSupportedFixAllScopes().Contains(FixAllScope.Document)) { continue; } var language = editor.DocumentContext.AnalysisDocument.Project.Language; var diagnosticdDescriptor = fix.Diagnostic?.GetCodeDiagnosticDescriptor(language); if (diagnosticdDescriptor == null) { continue; } var subMenu2 = new CodeFixMenu(GettextCatalog.GetString("Fix all")); var diagnosticAnalyzer = diagnosticdDescriptor.GetProvider(); if (!diagnosticAnalyzer.SupportedDiagnostics.Contains(diag.Descriptor)) { continue; } var menuItem = new CodeFixMenuEntry( GettextCatalog.GetString("In _Document"), async delegate { await FixAll(editor, fix, provider, diagnosticAnalyzer); } ); subMenu2.Add(menuItem); subMenu.Add(CodeFixMenuEntry.Separator); subMenu.Add(subMenu2); } menu.Add(subMenu); } return(menu); }
public void Add(CodeFixMenuEntry entry) { items.Add(entry); }
public static async Task <CodeFixMenu> CreateFixMenu(TextEditor editor, CodeActionContainer fixes, CancellationToken cancellationToken = default(CancellationToken)) { var menu = new CodeFixMenu(); if (editor.DocumentContext.AnalysisDocument == null) { return(menu); } int mnemonic = 1; var suppressLabel = GettextCatalog.GetString("_Suppress"); var suppressMenu = new CodeFixMenu(suppressLabel); var fixAllLabel = GettextCatalog.GetString("_Fix all"); var fixAllMenu = new CodeFixMenu(fixAllLabel); var configureLabel = GettextCatalog.GetString("_Options"); var configureMenu = new CodeFixMenu(configureLabel); var fixAllTasks = new List <Task <CodeAction> > (); foreach (var cfa in fixes.CodeFixActions) { var state = cfa.FixAllState; var scopes = cfa.SupportedScopes; foreach (var fix in cfa.Fixes) { var diag = fix.PrimaryDiagnostic; if (options.TryGetDiagnosticDescriptor(diag.Id, out var descriptor) && !descriptor.GetIsEnabled(diag.Descriptor)) { continue; } bool isSuppress = fix.Action is TopLevelSuppressionCodeAction; if (isSuppress) { AddFixMenuItem(editor, suppressMenu, ref mnemonic, fix.Action); continue; } AddFixMenuItem(editor, menu, ref mnemonic, fix.Action); var configurable = !DescriptorHasTag(diag.Descriptor, WellKnownDiagnosticTags.NotConfigurable); if (descriptor != null && configurable) { var optionsMenuItem = new CodeFixMenuEntry(GettextCatalog.GetString("_Configure Rule \u2018{0}\u2019", diag.Descriptor.Title), delegate { IdeApp.Workbench.ShowGlobalPreferencesDialog(null, "C#", dialog => { var panel = dialog.GetPanel <CodeIssuePanel> ("C#"); if (panel == null) { return; } panel.Widget.SelectCodeIssue(fix.PrimaryDiagnostic.Descriptor.Id); }); }); configureMenu.Add(optionsMenuItem); } if (!scopes.Contains(FixAllScope.Document)) { continue; } // FIXME: No global undo yet to support fixall in project/solution var fixState = state.WithScopeAndEquivalenceKey(FixAllScope.Document, fix.Action.EquivalenceKey); var provider = state.FixAllProvider; if (provider == null) { continue; } // FIXME: Use a real progress tracker. var fixAll = Task.Run(() => provider.GetFixAsync(fixState.CreateFixAllContext(new RoslynProgressTracker(), cancellationToken))); fixAllTasks.Add(fixAll); } } var fixAllActions = await Task.WhenAll(fixAllTasks); foreach (var fixAllAction in fixAllActions) { AddFixMenuItem(editor, fixAllMenu, ref mnemonic, fixAllAction); } bool first = true; foreach (var refactoring in fixes.CodeRefactoringActions) { if (options.TryGetRefactoringDescriptor(refactoring.GetType(), out var descriptor) && !descriptor.IsEnabled) { continue; } if (first) { if (menu.Items.Count > 0) { menu.Add(CodeFixMenuEntry.Separator); } first = false; } foreach (var action in refactoring.Actions) { AddFixMenuItem(editor, menu, ref mnemonic, action); } } first = true; if (fixAllMenu.Items.Count != 0) { if (first) { menu.Add(CodeFixMenuEntry.Separator); } menu.Add(fixAllMenu); first = false; } if (suppressMenu.Items.Count != 0) { if (first) { menu.Add(CodeFixMenuEntry.Separator); } menu.Add(suppressMenu); first = false; } if (configureMenu.Items.Count != 0) { if (first) { menu.Add(CodeFixMenuEntry.Separator); } menu.Add(configureMenu); first = false; } return(menu); }