Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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);
            }
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
 public void Add(CodeFixMenuEntry entry)
 {
     items.Add(entry);
 }
Ejemplo n.º 7
0
        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);
        }