提交 d6671b06 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #16893 from CyrusNajmabadi/alwaysShowRefactorings

Show the lightbulb when there are available refactorings at the current location.
......@@ -279,8 +279,8 @@
<Compile Include="Implementation\Structure\AbstractStructureTaggerProvider.cs" />
<Compile Include="Implementation\Preview\DifferenceViewerPreview.cs" />
<Compile Include="Implementation\Preview\PreviewReferenceHighlightingTaggerProvider.cs" />
<Compile Include="Implementation\Suggestions\FixAllSuggestedAction.FixAllCodeAction.cs" />
<Compile Include="Implementation\Suggestions\FixMultipleOccurrencesService.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\FixAllSuggestedAction.FixAllCodeAction.cs" />
<Compile Include="Implementation\Suggestions\FixAll\FixMultipleOccurrencesService.cs" />
<Compile Include="GoToImplementation\GoToImplementationCommandHandler.cs" />
<Compile Include="Implementation\TodoComment\ITodoListProvider.cs" />
<Compile Include="Implementation\TodoComment\TodoItem.cs" />
......@@ -599,14 +599,14 @@
<Compile Include="Implementation\SmartIndent\IIndentationService.cs" />
<Compile Include="Implementation\SmartIndent\SmartIndent.cs" />
<Compile Include="Implementation\SmartIndent\SmartIndentProvider.cs" />
<Compile Include="Implementation\Suggestions\FixAllGetFixesService.cs" />
<Compile Include="Implementation\Suggestions\FixAllSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\CodeFixSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\CodeRefactoringSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\FixAll\FixAllGetFixesService.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\FixAllSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\CodeFixSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\CodeRefactoringSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\PreviewChanges\PreviewChangesCodeAction.cs" />
<Compile Include="Implementation\Suggestions\PreviewChanges\PreviewChangesSuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\SuggestedAction.CaretPositionRestorer.cs" />
<Compile Include="Implementation\Suggestions\SuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\SuggestedAction.CaretPositionRestorer.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActions\SuggestedAction.cs" />
<Compile Include="Implementation\Suggestions\SuggestedActionsSourceProvider.cs" />
<Compile Include="Implementation\TextBufferAssociatedViewService.cs" />
<Compile Include="Implementation\TextDiffing\EditorTextDifferencingService.cs" />
......
......@@ -73,7 +73,8 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
_fixAllProviderMap = ImmutableDictionary<object, FixAllProviderInfo>.Empty;
}
public async Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document document, TextSpan range, bool considerSuppressionFixes, CancellationToken cancellationToken)
public async Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(
Document document, TextSpan range, CancellationToken cancellationToken)
{
if (document == null || !document.IsOpen())
{
......@@ -99,7 +100,7 @@ public async Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document
//
// first approach is simpler, so I will implement that first. if the first approach turns out to be not good enough, then
// I will try the second approach which will be more complex but quicker
var hasFix = await ContainsAnyFix(document, diagnostic, considerSuppressionFixes, cancellationToken).ConfigureAwait(false);
var hasFix = await ContainsAnyFix(document, diagnostic, cancellationToken).ConfigureAwait(false);
if (hasFix)
{
return new FirstDiagnosticResult(!fullResult, hasFix, diagnostic);
......@@ -354,10 +355,11 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
}
}
private async Task<bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, bool considerSuppressionFixes, CancellationToken cancellationToken)
private async Task<bool> ContainsAnyFix(
Document document, DiagnosticData diagnostic, CancellationToken cancellationToken)
{
ImmutableArray<CodeFixProvider> workspaceFixers = ImmutableArray<CodeFixProvider>.Empty;
bool hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out var fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
var workspaceFixers = ImmutableArray<CodeFixProvider>.Empty;
var hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out var fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
var hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out var projectFixers);
// TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
......@@ -369,7 +371,6 @@ private async Task<bool> ContainsAnyFix(Document document, DiagnosticData diagno
Lazy<ISuppressionFixProvider> lazySuppressionProvider = null;
var hasSuppressionFixer =
considerSuppressionFixes &&
_suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) &&
lazySuppressionProvider.Value != null;
......
......@@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.CodeFixes
{
internal interface ICodeFixService
{
Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document document, TextSpan textSpan, bool considerSuppressionFixes, CancellationToken cancellationToken);
Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken);
Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document document, TextSpan textSpan, bool includeSuppressionFixes, CancellationToken cancellationToken);
CodeFixProvider GetSuppressionFixer(string language, IEnumerable<string> diagnosticIds);
......
......@@ -19,7 +19,6 @@
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.Tags;
using Microsoft.CodeAnalysis.Experiments;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Shared.Utilities;
......@@ -83,10 +82,10 @@ public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView,
Contract.ThrowIfNull(textView);
Contract.ThrowIfNull(textBuffer);
return new Source(this, textView, textBuffer);
return new SuggestedActionsSource(this, textView, textBuffer);
}
private class Source : ForegroundThreadAffinitizedObject, ISuggestedActionsSource
private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISuggestedActionsSource
{
// state that will be only reset when source is disposed.
private SuggestedActionsSourceProvider _owner;
......@@ -98,7 +97,7 @@ private class Source : ForegroundThreadAffinitizedObject, ISuggestedActionsSourc
private Workspace _workspace;
private int _lastSolutionVersionReported;
public Source(SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer)
public SuggestedActionsSource(SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer)
{
_owner = owner;
_textView = textView;
......@@ -277,9 +276,9 @@ private SuggestedActionSet InlineActions(SuggestedActionSet actionSet)
? null
: applicableFixes.Length == collection.Fixes.Length
? collection
: new CodeFixCollection(collection.Provider, collection.TextSpan, applicableFixes,
collection.FixAllState,
collection.SupportedScopes, collection.FirstDiagnostic);
: new CodeFixCollection(
collection.Provider, collection.TextSpan, applicableFixes,
collection.FixAllState, collection.SupportedScopes, collection.FirstDiagnostic);
}
private bool IsApplicable(CodeAction action, Workspace workspace)
......@@ -346,10 +345,10 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
}
private void ProcessFixCollection(
Workspace workspace,
IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order,
bool includeSuppressionFixes,
Workspace workspace,
IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order,
bool includeSuppressionFixes,
CodeFixCollection fixCollection)
{
var fixes = fixCollection.Fixes;
......@@ -364,7 +363,7 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
var nonSupressionCodeFixes = fixes.WhereAsArray(f => !(f.Action is TopLevelSuppressionCodeAction));
var supressionCodeFixes = fixes.WhereAsArray(f => f.Action is TopLevelSuppressionCodeAction);
AddCodeActions(workspace, map, order, fixCollection,
AddCodeActions(workspace, map, order, fixCollection,
getFixAllSuggestedActionSet, nonSupressionCodeFixes);
// Add suppression fixes to the end of a given SuggestedActionSet so that they
......@@ -377,8 +376,8 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
}
private void AddCodeActions(
Workspace workspace, IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order, CodeFixCollection fixCollection,
Workspace workspace, IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order, CodeFixCollection fixCollection,
Func<CodeAction, SuggestedActionSet> getFixAllSuggestedActionSet,
ImmutableArray<CodeFix> codeFixes)
{
......@@ -397,7 +396,7 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
fix.PrimaryDiagnostic.Location.SourceSpan.ToSpan());
suggestedAction = new SuggestedActionWithNestedActions(
_owner, workspace, _subjectBuffer,
_owner, workspace, _subjectBuffer,
fixCollection.Provider, fix.Action, set);
}
else
......@@ -456,7 +455,7 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
{
var fixAllStateForScope = fixAllState.WithScopeAndEquivalenceKey(scope, action.EquivalenceKey);
var fixAllSuggestedAction = new FixAllSuggestedAction(
_owner, workspace, _subjectBuffer, fixAllStateForScope,
_owner, workspace, _subjectBuffer, fixAllStateForScope,
firstDiagnostic, action);
fixAllSuggestedActions.Add(fixAllSuggestedAction);
......@@ -522,7 +521,6 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
{
this.AssertIsForeground();
if (workspace.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
_owner._codeRefactoringService != null &&
supportsFeatureService.SupportsRefactorings(document) &&
......@@ -600,36 +598,28 @@ public async Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet req
return false;
}
var workspace = document.Project.Solution.Workspace;
var supportsFeatureService = workspace.Services.GetService<IDocumentSupportsFeatureService>();
return
await HasFixesAsync(
supportsFeatureService, requestedActionCategories, provider, document, range,
cancellationToken).ConfigureAwait(false) ||
await HasRefactoringsAsync(
supportsFeatureService, requestedActionCategories, provider, document, buffer, view, range,
cancellationToken).ConfigureAwait(false);
await HasFixesAsync(provider, document, range, cancellationToken).ConfigureAwait(false) ||
await HasRefactoringsAsync(provider, document, buffer, view, range, cancellationToken).ConfigureAwait(false);
}
}
private async Task<bool> HasFixesAsync(
IDocumentSupportsFeatureService supportsFeatureService,
ISuggestedActionCategorySet requestedActionCategories,
SuggestedActionsSourceProvider provider,
Document document, SnapshotSpan range,
Document document,
SnapshotSpan range,
CancellationToken cancellationToken)
{
if (provider._codeFixService != null && supportsFeatureService.SupportsCodeFixes(document) &&
requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.CodeFix))
var workspace = document.Project.Solution.Workspace;
var supportsFeatureService = workspace.Services.GetService<IDocumentSupportsFeatureService>();
if (provider._codeFixService != null &&
supportsFeatureService.SupportsCodeFixes(document))
{
// 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(
() => provider._codeFixService.GetFirstDiagnosticWithFixAsync(
document, range.Span.ToTextSpan(), considerSuppressionFixes, cancellationToken),
cancellationToken).ConfigureAwait(false);
document, range.Span.ToTextSpan(), cancellationToken),
cancellationToken).ConfigureAwait(false);
if (result.HasFix)
{
......@@ -649,8 +639,6 @@ public async Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet req
}
private async Task<bool> HasRefactoringsAsync(
IDocumentSupportsFeatureService supportsFeatureService,
ISuggestedActionCategorySet requestedActionCategories,
SuggestedActionsSourceProvider provider,
Document document,
ITextBuffer buffer,
......@@ -658,21 +646,8 @@ public async Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet req
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;
}
}
var workspace = document.Project.Solution.Workspace;
var supportsFeatureService = workspace.Services.GetService<IDocumentSupportsFeatureService>();
if (document.Project.Solution.Options.GetOption(EditorComponentOnOffOptions.CodeRefactorings) &&
provider._codeRefactoringService != null &&
......@@ -688,8 +663,8 @@ public async Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet req
{
await InvokeBelowInputPriority(() =>
{
// This operation needs to happen on UI thread because it needs to access textView.Selection.
selection = TryGetCodeRefactoringSelection(buffer, view, range);
// This operation needs to happen on UI thread because it needs to access textView.Selection.
selection = TryGetCodeRefactoringSelection(buffer, view, range);
}).ConfigureAwait(false);
}
......
......@@ -46,7 +46,7 @@ public async Task TestGetFirstDiagnosticWithFixAsync()
var reference = new MockAnalyzerReference();
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
var document = project.Documents.Single();
var unused = await fixService.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), considerSuppressionFixes: false, cancellationToken: CancellationToken.None);
var unused = await fixService.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
var fixer1 = fixers.Single().Value as MockFixer;
var fixer2 = reference.Fixer as MockFixer;
......@@ -127,7 +127,7 @@ public async Task GetFirstDiagnosticWithFixAsync(CodeFixProvider codefix)
using (var workspace = tuple.Item1)
{
GetDocumentAndExtensionManager(tuple.Item2, workspace, out var document, out var extensionManager);
var unused = await tuple.Item3.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), considerSuppressionFixes: false, cancellationToken: CancellationToken.None);
var unused = await tuple.Item3.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
Assert.True(extensionManager.IsDisabled(codefix));
Assert.False(extensionManager.IsIgnored(codefix));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册