Exemplo n.º 1
0
            private IEnumerable <SuggestedActionSet> GetRefactorings(
                ISuggestedActionCategorySet requestedActionCategories,
                Document document,
                ITextSnapshot snapshot,
                Workspace workspace,
                IOptionService optionService,
                CancellationToken cancellationToken)
            {
                // For Dev14 Preview, we also want to show refactorings in the CodeFix list when users press Ctrl+.
                if (requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring) ||
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    var refactoringsOn = optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings);
                    if (!refactoringsOn)
                    {
                        return(null);
                    }

                    // Get the selection while on the UI thread.
                    var selection = GetCodeRefactoringSelection(snapshot);
                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        System.Diagnostics.Trace.WriteLine("given range is not current");
                        return(null);
                    }

                    var refactorings = Task.Run(
                        async() => await _owner._codeRefactoringService.GetRefactoringsAsync(document, selection.Value, cancellationToken).ConfigureAwait(false), cancellationToken).WaitAndGetResult(cancellationToken);

                    return(refactorings.Select(r => OrganizeRefactorings(workspace, r)));
                }

                return(null);
            }
Exemplo n.º 2
0
            private ImmutableArray <SuggestedActionSet> GetCodeFixes(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                this.AssertIsForeground();

                if (_owner._codeFixService != null &&
                    supportsFeatureService.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only include suppressions if light bulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't include suppressions.
                    var includeSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);

                    var fixes = Task.Run(
                        () => _owner._codeFixService.GetFixesAsync(
                            document, range.Span.ToTextSpan(), includeSuppressionFixes, cancellationToken),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    var filteredFixes = FilterOnUIThread(fixes, workspace);

                    return(OrganizeFixes(workspace, filteredFixes, includeSuppressionFixes));
                }

                return(ImmutableArray <SuggestedActionSet> .Empty);
            }
            private IEnumerable <SuggestedActionSet> GetCodeFixes(
                IDocumentSupportsSuggestionService supportSuggestion,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (_owner._codeFixService != null && supportSuggestion.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only include suppressions if lightbulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't include suppressions.
                    var includeSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);

                    var fixes = Task.Run(
                        async() => await _owner._codeFixService.GetFixesAsync(
                            document, range.Span.ToTextSpan(), includeSuppressionFixes, cancellationToken).ConfigureAwait(false),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    return(OrganizeFixes(workspace, fixes, hasSuppressionFixes: includeSuppressionFixes));
                }

                return(null);
            }
            private async Task <bool> HasFixesAsync(
                IDocumentSupportsSuggestionService supportSuggestion,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document, SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (provider._codeFixService != null && supportSuggestion.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only consider suppressions if lightbulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't consider suppressions.
                    var considerSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);
                    var result = await Task.Run(
                        async() => await provider._codeFixService.GetFirstDiagnosticWithFixAsync(
                            document, range.Span.ToTextSpan(), considerSuppressionFixes, cancellationToken).ConfigureAwait(false),
                        cancellationToken).ConfigureAwait(false);

                    if (result.HasFix)
                    {
                        Logger.Log(FunctionId.SuggestedActions_HasSuggestedActionsAsync);
                        return(true);
                    }

                    if (result.PartialResult)
                    {
                        // reset solution version number so that we can raise suggested action changed event
                        Volatile.Write(ref _lastSolutionVersionReported, InvalidSolutionVersion);
                        return(false);
                    }
                }

                return(false);
            }
        static MSBuildDiagnosticSeverity CategoriesToSeverity(ISuggestedActionCategorySet categories)
        {
            var severity = MSBuildDiagnosticSeverity.None;

            if (categories.Contains(PredefinedSuggestedActionCategoryNames.ErrorFix))
            {
                severity |= MSBuildDiagnosticSeverity.Error;
            }
            if (categories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
            {
                severity |= MSBuildDiagnosticSeverity.Suggestion | MSBuildDiagnosticSeverity.Warning;
            }
            return(severity);
        }
            private async Task <bool> HasRefactoringsAsync(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document,
                ITextBuffer buffer,
                ITextView view,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (!requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // See if we should still show the light bulb, even if we weren't explicitly
                    // asked for refactorings.  We'll show the lightbulb if we're currently
                    // flighting the "Refactoring" A/B test, or if a special option is set
                    // enabling this internally.

                    var workspace = document.Project.Solution.Workspace;
                    var experimentationService = workspace.Services.GetService <IExperimentationService>();
                    if (!experimentationService.IsExperimentEnabled("Refactoring") &&
                        !workspace.Options.GetOption(EditorComponentOnOffOptions.ShowCodeRefactoringsWhenQueriedForCodeFixes))
                    {
                        return(false);
                    }
                }

                if (document.Project.Solution.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    provider._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document))
                {
                    TextSpan?selection = null;
                    if (IsForeground())
                    {
                        // This operation needs to happen on UI thread because it needs to access textView.Selection.
                        selection = TryGetCodeRefactoringSelection(buffer, view, range);
                    }
                    else
                    {
                        await InvokeBelowInputPriority(() =>
                        {
                            // This operation needs to happen on UI thread because it needs to access textView.Selection.
                            selection = TryGetCodeRefactoringSelection(buffer, view, range);
                        }).ConfigureAwait(false);
                    }

                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return(false);
                    }

                    return(await Task.Run(
                               () => provider._codeRefactoringService.HasRefactoringsAsync(
                                   document, selection.Value, cancellationToken),
                               cancellationToken).ConfigureAwait(false));
                }

                return(false);
            }
Exemplo n.º 7
0
            public async Task <ISuggestedActionCategorySet> GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
            {
                var provider = _owner;

                using (var asyncToken = _owner.OperationListener.BeginAsyncOperation(nameof(GetSuggestedActionCategoriesAsync)))
                {
                    var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
                    using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
                    {
                        var linkedToken = linkedTokenSource.Token;

                        var errorTask = Task.Run(
                            () => GetFixLevelAsync(provider, document, range, linkedToken), linkedToken);

                        var selection = await GetSpanAsync(range).ConfigureAwait(false);

                        Task <string> refactoringTask = Task.FromResult((string)null);
                        if (selection != null && requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                        {
                            refactoringTask = Task.Run(
                                () => TryGetRefactoringSuggestedActionCategoryAsync(provider, document, selection, linkedToken),
                                linkedToken);
                        }

                        // If we happen to get the result of the error task before the refactoring task,
                        // and that result is non-null, we can just cancel the refactoring task.
                        var result = await errorTask.ConfigureAwait(false) ?? await refactoringTask.ConfigureAwait(false);

                        linkedTokenSource.Cancel();
                        return(result == null
                            ? null
                            : _suggestedActionCategoryRegistry.CreateSuggestedActionCategorySet(result));
                    }
                }
            }
            private IEnumerable <SuggestedActionSet> GetRefactorings(
                IDocumentSupportsSuggestionService supportSuggestion,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                var optionService = workspace.Services.GetService <IOptionService>();

                if (optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    _owner._codeRefactoringService != null &&
                    supportSuggestion.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // Get the selection while on the UI thread.
                    var selection = TryGetCodeRefactoringSelection(_subjectBuffer, _textView, range);
                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return(null);
                    }

                    var refactorings = Task.Run(
                        async() => await _owner._codeRefactoringService.GetRefactoringsAsync(
                            document, selection.Value, cancellationToken).ConfigureAwait(false),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    return(refactorings.Select(r => OrganizeRefactorings(workspace, r)));
                }

                return(null);
            }
Exemplo n.º 9
0
            private ImmutableArray <SuggestedActionSet> GetRefactorings(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                TextSpan?selectionOpt,
                CancellationToken cancellationToken)
            {
                this.AssertIsForeground();

                if (!selectionOpt.HasValue)
                {
                    // this is here to fail test and see why it is failed.
                    Trace.WriteLine("given range is not current");
                    return(ImmutableArray <SuggestedActionSet> .Empty);
                }

                var selection = selectionOpt.Value;

                if (workspace.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    _owner._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // It may seem strange that we kick off a task, but then immediately 'Wait' on
                    // it. However, it's deliberate.  We want to make sure that the code runs on
                    // the background so that no one takes an accidentally dependency on running on
                    // the UI thread.
                    var refactorings = Task.Run(
                        () => _owner._codeRefactoringService.GetRefactoringsAsync(
                            document, selection, cancellationToken),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    var filteredRefactorings = FilterOnUIThread(refactorings, workspace);

                    // Refactorings are given the span the user currently has selected.  That
                    // way they can be accurately sorted against other refactorings/fixes that
                    // are of the same priority.  i.e. refactorings are LowPriority by default.
                    // But we still want them to come first over a low-pri code fix that is
                    // further away.  A good example of this is "Add null parameter check" which
                    // should be higher in the list when the caret is on a parameter, vs the
                    // code-fix for "use expression body" which is given the entire span of a
                    // method.

                    var priority = selection.Length > 0
                        ? SuggestedActionSetPriority.Medium
                        : SuggestedActionSetPriority.Low;

                    return(filteredRefactorings.SelectAsArray(
                               r => OrganizeRefactorings(workspace, r, priority, selection.ToSpan())));
                }

                return(ImmutableArray <SuggestedActionSet> .Empty);
            }
        async Task <List <MSBuildCodeFix> > GetSuggestedActionsAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
        {
            // grab selection first as we are on the UI thread at this point, and can avoid switching to it later
            var possibleSelection = TryGetSelectedSpan();

            var result = await parser.GetOrProcessAsync(range.Snapshot, cancellationToken);

            List <MSBuildCodeFix> actions = null;

            var severities = CategoriesToSeverity(requestedActionCategories);

            if (severities != 0)
            {
                actions = await provider.CodeFixService.GetFixes(textBuffer, result, range, severities, cancellationToken);

                for (int i = 0; i < actions.Count; i++)
                {
                    if (!requestedActionCategories.Contains(actions[i].Category))
                    {
                        actions.RemoveAt(i);
                        i--;
                    }
                }
            }

            if (possibleSelection is SnapshotSpan selection && requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
            {
                var refactorings = await provider.RefactoringService.GetRefactorings(result, selection, cancellationToken);

                if (actions != null)
                {
                    actions.AddRange(refactorings);
                }
                else
                {
                    actions = refactorings;
                }
            }

            return(actions);
        }
Exemplo n.º 11
0
            public IEnumerable <SuggestedActionSet> GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
            {
                AssertIsForeground();

                using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActions, cancellationToken))
                {
                    if (range.IsEmpty)
                    {
                        return(null);
                    }

                    var documentAndSnapshot = GetMatchingDocumentAndSnapshotAsync(range.Snapshot, cancellationToken).WaitAndGetResult(cancellationToken);
                    if (!documentAndSnapshot.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        System.Diagnostics.Trace.WriteLine("given range is not current");
                        return(null);
                    }

                    var document = documentAndSnapshot.Value.Item1;
                    var snapshot = documentAndSnapshot.Value.Item2;

                    var workspace         = document.Project.Solution.Workspace;
                    var optionService     = workspace.Services.GetService <IOptionService>();
                    var supportSuggestion = workspace.Services.GetService <IDocumentSupportsSuggestionService>();

                    IEnumerable <SuggestedActionSet> result = null;
                    if (supportSuggestion.SupportsCodeFixes(document) && requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                    {
                        var suggestions = Task.Run(
                            async() => await _owner._codeFixService.GetFixesAsync(document, range.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false), cancellationToken).WaitAndGetResult(cancellationToken);

                        result = OrganizeFixes(workspace, suggestions);
                    }

                    if (supportSuggestion.SupportsRefactorings(document))
                    {
                        var refactoringResult = GetRefactorings(requestedActionCategories, document, snapshot, workspace, optionService, cancellationToken);

                        result = result == null ? refactoringResult :
                                 refactoringResult == null ? result :
                                 result.Concat(refactoringResult);
                    }

                    return(result);
                }
            }
            private async Task <bool> HasRefactoringsAsync(
                IDocumentSupportsSuggestionService supportSuggestion,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document,
                ITextBuffer buffer,
                ITextView view,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                var optionService = document.Project.Solution.Workspace.Services.GetService <IOptionService>();

                if (optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    provider._codeRefactoringService != null &&
                    supportSuggestion.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    TextSpan?selection = null;
                    if (IsForeground())
                    {
                        // This operation needs to happen on UI thread because it needs to access textView.Selection.
                        selection = TryGetCodeRefactoringSelection(buffer, view, range);
                    }
                    else
                    {
                        await InvokeBelowInputPriority(() =>
                        {
                            // This operation needs to happen on UI thread because it needs to access textView.Selection.
                            selection = TryGetCodeRefactoringSelection(buffer, view, range);
                        }).ConfigureAwait(false);
                    }

                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return(false);
                    }

                    return(await Task.Run(
                               async() => await provider._codeRefactoringService.HasRefactoringsAsync(
                                   document, selection.Value, cancellationToken).ConfigureAwait(false),
                               cancellationToken).ConfigureAwait(false));
                }

                return(false);
            }
Exemplo n.º 13
0
            public async Task <ISuggestedActionCategorySet> GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
            {
                if (_workspaceStatusService != null && !await _workspaceStatusService.IsFullyLoadedAsync(cancellationToken).ConfigureAwait(false))
                {
                    // never show light bulb if solution is not fully loaded yet
                    return(null);
                }

                var provider = _owner;

                using (var asyncToken = _owner.OperationListener.BeginAsyncOperation(nameof(GetSuggestedActionCategoriesAsync)))
                {
                    var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
                    if (document == null)
                    {
                        return(null);
                    }

                    using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
                    {
                        var linkedToken = linkedTokenSource.Token;

                        var errorTask = Task.Run(
                            () => GetFixLevelAsync(provider, document, range, linkedToken), linkedToken);

                        var selection = await GetSpanAsync(range, linkedToken).ConfigureAwait(false);

                        var refactoringTask = SpecializedTasks.Default <string>();
                        if (selection != null && requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                        {
                            refactoringTask = Task.Run(
                                () => TryGetRefactoringSuggestedActionCategoryAsync(provider, document, selection, linkedToken), linkedToken);
                        }

                        // If we happen to get the result of the error task before the refactoring task,
                        // and that result is non-null, we can just cancel the refactoring task.
                        var result = await errorTask.ConfigureAwait(false) ?? await refactoringTask.ConfigureAwait(false);

                        linkedTokenSource.Cancel();

                        return(result == null
                            ? null
                            : _suggestedActionCategoryRegistry.CreateSuggestedActionCategorySet(result));
                    }
                }
            }
Exemplo n.º 14
0
            private ImmutableArray <SuggestedActionSet> GetRefactorings(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                TextSpan?selectionOpt,
                CancellationToken cancellationToken)
            {
                this.AssertIsForeground();

                if (!selectionOpt.HasValue)
                {
                    // this is here to fail test and see why it is failed.
                    Trace.WriteLine("given range is not current");
                    return(ImmutableArray <SuggestedActionSet> .Empty);
                }

                var selection = selectionOpt.Value;

                if (workspace.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    _owner._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // It may seem strange that we kick off a task, but then immediately 'Wait' on
                    // it. However, it's deliberate.  We want to make sure that the code runs on
                    // the background so that no one takes an accidentally dependency on running on
                    // the UI thread.
                    var refactorings = Task.Run(
                        () => _owner._codeRefactoringService.GetRefactoringsAsync(
                            document, selection, cancellationToken),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    var filteredRefactorings = FilterOnUIThread(refactorings, workspace);

                    return(filteredRefactorings.SelectAsArray(
                               r => OrganizeRefactorings(workspace, r, selection.ToSpan())));
                }

                return(ImmutableArray <SuggestedActionSet> .Empty);
            }
        public async Task <ISuggestedActionCategorySet> GetSuggestedActionCategoriesAsync(
            ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
        {
            SnapshotSpan?possibleSelection = provider.JoinableTaskContext.IsOnMainThread ? TryGetSelectedSpan() : null;

            var result = await parser.GetOrProcessAsync(range.Snapshot, cancellationToken);

            var categories = new List <string> ();

            var requestedSeverities = CategoriesToSeverity(requestedActionCategories);

            if (requestedSeverities != 0)
            {
                var severities = await provider.CodeFixService.GetFixSeverity(textBuffer, result, range, requestedSeverities, cancellationToken);

                if ((severities & MSBuildDiagnosticSeverity.Error) != 0)
                {
                    categories.Add(PredefinedSuggestedActionCategoryNames.ErrorFix);
                }
                if ((severities & (MSBuildDiagnosticSeverity.Warning | MSBuildDiagnosticSeverity.Suggestion)) != 0)
                {
                    categories.Add(PredefinedSuggestedActionCategoryNames.CodeFix);
                }
            }

            if (requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
            {
                possibleSelection ??= await GetSelectedSpanAsync(cancellationToken);

                if (possibleSelection is SnapshotSpan selection && await provider.RefactoringService.HasRefactorings(result, selection, cancellationToken))
                {
                    categories.Add(PredefinedSuggestedActionCategoryNames.Refactoring);
                }
            }

            return(provider.CategoryRegistry.CreateSuggestedActionCategorySet(categories));
        }
            private async Task<bool> HasRefactoringsAsync(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document,
                ITextBuffer buffer,
                ITextView view,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                var optionService = document.Project.Solution.Workspace.Services.GetService<IOptionService>();

                if (optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    provider._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    TextSpan? selection = null;
                    if (IsForeground())
                    {
                        // This operation needs to happen on UI thread because it needs to access textView.Selection.
                        selection = TryGetCodeRefactoringSelection(buffer, view, range);
                    }
                    else
                    {
                        await InvokeBelowInputPriority(() =>
                        {
                            // This operation needs to happen on UI thread because it needs to access textView.Selection.
                            selection = TryGetCodeRefactoringSelection(buffer, view, range);
                        }).ConfigureAwait(false);
                    }

                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return false;
                    }

                    return await Task.Run(
                        async () => await provider._codeRefactoringService.HasRefactoringsAsync(
                            document, selection.Value, cancellationToken).ConfigureAwait(false),
                        cancellationToken).ConfigureAwait(false);
                }

                return false;
            }
            private async Task<bool> HasFixesAsync(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document, SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (provider._codeFixService != null && supportsFeatureService.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only consider suppressions if lightbulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't consider suppressions.
                    var considerSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);
                    var result = await Task.Run(
                        async () => await provider._codeFixService.GetFirstDiagnosticWithFixAsync(
                            document, range.Span.ToTextSpan(), considerSuppressionFixes, cancellationToken).ConfigureAwait(false),
                        cancellationToken).ConfigureAwait(false);

                    if (result.HasFix)
                    {
                        Logger.Log(FunctionId.SuggestedActions_HasSuggestedActionsAsync);
                        return true;
                    }

                    if (result.PartialResult)
                    {
                        // reset solution version number so that we can raise suggested action changed event
                        Volatile.Write(ref _lastSolutionVersionReported, InvalidSolutionVersion);
                        return false;
                    }
                }

                return false;
            }
            private IEnumerable<SuggestedActionSet> GetRefactorings(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                var optionService = workspace.Services.GetService<IOptionService>();

                if (optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    _owner._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // Get the selection while on the UI thread.
                    var selection = TryGetCodeRefactoringSelection(_subjectBuffer, _textView, range);
                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return null;
                    }

                    var refactorings = Task.Run(
                        async () => await _owner._codeRefactoringService.GetRefactoringsAsync(
                            document, selection.Value, cancellationToken).ConfigureAwait(false),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    return refactorings.Select(r => OrganizeRefactorings(workspace, r));
                }

                return null;
            }
            private IEnumerable<SuggestedActionSet> GetCodeFixes(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (_owner._codeFixService != null && supportsFeatureService.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only include suppressions if lightbulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't include suppressions.
                    var includeSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);

                    var fixes = Task.Run(
                        async () => await _owner._codeFixService.GetFixesAsync(
                            document, range.Span.ToTextSpan(), includeSuppressionFixes, cancellationToken).ConfigureAwait(false),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    return OrganizeFixes(workspace, fixes, hasSuppressionFixes: includeSuppressionFixes);
                }

                return null;
            }
            private async Task<bool> HasRefactoringsAsync(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                SuggestedActionsSourceProvider provider,
                Document document,
                ITextBuffer buffer,
                ITextView view,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                if (!requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // See if we should still show the light bulb, even if we weren't explicitly 
                    // asked for refactorings.  We'll show the lightbulb if we're currently
                    // flighting the "Refactoring" A/B test, or if a special option is set
                    // enabling this internally.

                    var workspace = document.Project.Solution.Workspace;
                    var experimentationService = workspace.Services.GetService<IExperimentationService>();
                    if (!experimentationService.IsExperimentEnabled("Refactoring") &&
                        !workspace.Options.GetOption(EditorComponentOnOffOptions.ShowCodeRefactoringsWhenQueriedForCodeFixes))
                    {
                        return false;
                    }
                }

                if (document.Project.Solution.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    provider._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document))
                {
                    TextSpan? selection = null;
                    if (IsForeground())
                    {
                        // This operation needs to happen on UI thread because it needs to access textView.Selection.
                        selection = TryGetCodeRefactoringSelection(buffer, view, range);
                    }
                    else
                    {
                        await InvokeBelowInputPriority(() =>
                        {
                            // This operation needs to happen on UI thread because it needs to access textView.Selection.
                            selection = TryGetCodeRefactoringSelection(buffer, view, range);
                        }).ConfigureAwait(false);
                    }

                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return false;
                    }

                    return await Task.Run(
                        () => provider._codeRefactoringService.HasRefactoringsAsync(
                            document, selection.Value, cancellationToken),
                        cancellationToken).ConfigureAwait(false);
                }

                return false;
            }
            private ImmutableArray<SuggestedActionSet> GetRefactorings(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                this.AssertIsForeground();


                if (workspace.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
                    _owner._codeRefactoringService != null &&
                    supportsFeatureService.SupportsRefactorings(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring))
                {
                    // Get the selection while on the UI thread.
                    var selection = TryGetCodeRefactoringSelection(_subjectBuffer, _textView, range);
                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return ImmutableArray<SuggestedActionSet>.Empty;
                    }

                    // It may seem strange that we kick off a task, but then immediately 'Wait' on 
                    // it. However, it's deliberate.  We want to make sure that the code runs on 
                    // the background so that no one takes an accidently dependency on running on 
                    // the UI thread.
                    var refactorings = Task.Run(
                        () => _owner._codeRefactoringService.GetRefactoringsAsync(
                            document, selection.Value, cancellationToken),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    var filteredRefactorings = FilterOnUIThread(refactorings, workspace);

                    return filteredRefactorings.SelectAsArray(r => OrganizeRefactorings(workspace, r));
                }

                return ImmutableArray<SuggestedActionSet>.Empty;
            }
            private IEnumerable<SuggestedActionSet> GetRefactorings(
                ISuggestedActionCategorySet requestedActionCategories,
                Document document,
                ITextSnapshot snapshot,
                Workspace workspace,
                IOptionService optionService,
                CancellationToken cancellationToken)
            {
                // For Dev14 Preview, we also want to show refactorings in the CodeFix list when users press Ctrl+.
                if (requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring) ||
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    var refactoringsOn = optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings);
                    if (!refactoringsOn)
                    {
                        return null;
                    }

                    // Get the selection while on the UI thread.
                    var selection = GetCodeRefactoringSelection(snapshot);
                    if (!selection.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        System.Diagnostics.Trace.WriteLine("given range is not current");
                        return null;
                    }

                    var refactorings = Task.Run(
                        async () => await _owner._codeRefactoringService.GetRefactoringsAsync(document, selection.Value, cancellationToken).ConfigureAwait(false), cancellationToken).WaitAndGetResult(cancellationToken);

                    return refactorings.Select(r => OrganizeRefactorings(workspace, r));
                }

                return null;
            }
            private ImmutableArray<SuggestedActionSet> GetCodeFixes(
                IDocumentSupportsFeatureService supportsFeatureService,
                ISuggestedActionCategorySet requestedActionCategories,
                Workspace workspace,
                Document document,
                SnapshotSpan range,
                CancellationToken cancellationToken)
            {
                this.AssertIsForeground();

                if (_owner._codeFixService != null &&
                    supportsFeatureService.SupportsCodeFixes(document) &&
                    requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                {
                    // We only include suppressions if lightbulb is asking for everything.
                    // If the light bulb is only asking for code fixes, then we don't include suppressions.
                    var includeSuppressionFixes = requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Any);

                    var fixes = Task.Run(
                        () => _owner._codeFixService.GetFixesAsync(
                                document, range.Span.ToTextSpan(), includeSuppressionFixes, cancellationToken),
                        cancellationToken).WaitAndGetResult(cancellationToken);

                    var filteredFixes = FilterOnUIThread(fixes, workspace);

                    return OrganizeFixes(workspace, filteredFixes, includeSuppressionFixes);
                }

                return ImmutableArray<SuggestedActionSet>.Empty;
            }
            public IEnumerable<SuggestedActionSet> GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
            {
                AssertIsForeground();

                using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActions, cancellationToken))
                {
                    if (range.IsEmpty)
                    {
                        return null;
                    }

                    var documentAndSnapshot = GetMatchingDocumentAndSnapshotAsync(range.Snapshot, cancellationToken).WaitAndGetResult(cancellationToken);
                    if (!documentAndSnapshot.HasValue)
                    {
                        // this is here to fail test and see why it is failed.
                        System.Diagnostics.Trace.WriteLine("given range is not current");
                        return null;
                    }

                    var document = documentAndSnapshot.Value.Item1;
                    var snapshot = documentAndSnapshot.Value.Item2;

                    var workspace = document.Project.Solution.Workspace;
                    var optionService = workspace.Services.GetService<IOptionService>();
                    var supportSuggestion = workspace.Services.GetService<IDocumentSupportsSuggestionService>();

                    IEnumerable<SuggestedActionSet> result = null;
                    if (supportSuggestion.SupportsCodeFixes(document) && requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
                    {
                        var suggestions = Task.Run(
                            async () => await _owner._codeFixService.GetFixesAsync(document, range.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false), cancellationToken).WaitAndGetResult(cancellationToken);

                        result = OrganizeFixes(workspace, suggestions);
                    }

                    if (supportSuggestion.SupportsRefactorings(document))
                    {
                        var refactoringResult = GetRefactorings(requestedActionCategories, document, snapshot, workspace, optionService, cancellationToken);

                        result = result == null ? refactoringResult :
                                    refactoringResult == null ? result :
                                        result.Concat(refactoringResult);
                    }

                    return result;
                }
            }