未验证 提交 62b0d83c 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #42246 from CyrusNajmabadi/renameRefactoring

Convert 'rename' to be a refactoring, instead of an analyzer+fixer.
......@@ -57,7 +57,6 @@ internal static class PredefinedCodeFixProviderNames
public const string RemoveUnusedLocalFunction = nameof(RemoveUnusedLocalFunction);
public const string RemoveUnusedMembers = nameof(RemoveUnusedMembers);
public const string RemoveUnusedVariable = nameof(RemoveUnusedVariable);
public const string RenameTracking = nameof(RenameTracking);
public const string SimplifyNames = nameof(SimplifyNames);
public const string SimplifyThisOrMe = nameof(SimplifyThisOrMe);
public const string SpellCheck = nameof(SpellCheck);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking;
using Microsoft.VisualStudio.Text.Operations;
namespace Microsoft.CodeAnalysis.Editor.CSharp.RenameTracking
{
// TODO: Remove the ExtensionOrder attributes once a better ordering mechanism is available
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RenameTracking), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.AddImport)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.AddMissingReference)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.FullyQualify)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.FixIncorrectExitContinue)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateConstructor)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateEndConstruct)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateEnumMember)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateEvent)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateVariable)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateMethod)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.GenerateType)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.ImplementAbstractClass)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.ImplementInterface)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.MoveToTopOfFile)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.RemoveUnnecessaryCast)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.RemoveUnnecessaryImports)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.SimplifyNames)]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.SpellCheck)]
internal sealed class CSharpRenameTrackingCodeFixProvider : AbstractRenameTrackingCodeFixProvider
{
[ImportingConstructor]
public CSharpRenameTrackingCodeFixProvider(
ITextUndoHistoryRegistry undoHistoryRegistry,
[ImportMany] IEnumerable<IRefactorNotifyService> refactorNotifyServices)
: base(undoHistoryRegistry, refactorNotifyServices)
{
}
}
}
......@@ -235,9 +235,9 @@ public bool TryGetTelemetryId(out Guid telemetryId)
private ImmutableArray<SuggestedActionSet> GetInitiallyOrderedActionSets(
TextSpan? selectionOpt, ImmutableArray<SuggestedActionSet> fixes, ImmutableArray<SuggestedActionSet> refactorings)
{
// First, order refactorings based on the order the providers actually gave for their actions.
// This way, a low pri refactoring always shows after a medium pri refactoring, no matter what
// we do below.
// First, order refactorings based on the order the providers actually gave for
// their actions. This way, a low pri refactoring always shows after a medium pri
// refactoring, no matter what we do below.
refactorings = OrderActionSets(refactorings, selectionOpt);
// If there's a selection, it's likely the user is trying to perform some operation
......@@ -247,22 +247,34 @@ public bool TryGetTelemetryId(out Guid telemetryId)
if (selectionOpt?.Length > 0)
{
// There was a selection. Treat refactorings as more important than
// fixes. Note: we still will sort after this. So any high pri fixes
// will come to the front. Any low-pri refactorings will go to the end.
// There was a selection. Treat refactorings as more important than fixes.
// Note: we still will sort after this. So any high pri fixes will come to the
// front. Any low-pri refactorings will go to the end.
return refactorings.Concat(fixes);
}
else
{
// No selection. Treat all refactorings as low priority, and place
// after fixes. Even a low pri fixes will be above what was *originally*
// No selection. Treat all medium and low pri refactorings as low priority, and
// place after fixes. Even a low pri fixes will be above what was *originally*
// a medium pri refactoring.
refactorings = refactorings.SelectAsArray(r => new SuggestedActionSet(
r.CategoryName, r.Actions, r.Title, SuggestedActionSetPriority.Low, r.ApplicableToSpan));
return fixes.Concat(refactorings);
//
// Note: we do not do this for *high* pri refactorings (like 'rename'). These
// are still very important and need to stay at the top (though still after high
// pri fixes).
var highPriRefactorings = refactorings.WhereAsArray(s => s.Priority == SuggestedActionSetPriority.High);
var nonHighPriRefactorings = refactorings.WhereAsArray(s => s.Priority != SuggestedActionSetPriority.High)
.SelectAsArray(s => WithPriority(s, SuggestedActionSetPriority.Low));
var highPriFixes = fixes.WhereAsArray(s => s.Priority == SuggestedActionSetPriority.High);
var nonHighPriFixes = fixes.WhereAsArray(s => s.Priority != SuggestedActionSetPriority.High);
return highPriFixes.Concat(highPriRefactorings).Concat(nonHighPriFixes).Concat(nonHighPriRefactorings);
}
}
private SuggestedActionSet WithPriority(SuggestedActionSet set, SuggestedActionSetPriority priority)
=> new SuggestedActionSet(set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan);
private ImmutableArray<SuggestedActionSet> OrderActionSets(
ImmutableArray<SuggestedActionSet> actionSets, TextSpan? selectionOpt)
{
......@@ -842,7 +854,7 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
// - gets the the same priority as the highest priority action within in.
// - gets `applicableToSpan` of the first action:
// - E.g. the `applicableToSpan` closest to current selection might be a more correct
// choice. All actions creted by one Refactoring have usually the same `applicableSpan`
// choice. All actions created by one Refactoring have usually the same `applicableSpan`
// and therefore the complexity of determining the closest one isn't worth the benefit
// of slightly more correct orderings in certain edge cases.
return new SuggestedActionSet(
......
......@@ -2,54 +2,77 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.Text.Operations;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking
{
internal abstract class AbstractRenameTrackingCodeFixProvider : CodeFixProvider
[ExportCodeRefactoringProvider(LanguageNames.CSharp, LanguageNames.VisualBasic,
Name = nameof(RenameTrackingCodeRefactoringProvider)), Shared]
internal class RenameTrackingCodeRefactoringProvider : CodeRefactoringProvider
{
public const string DiagnosticId = "RenameTracking";
public static DiagnosticDescriptor DiagnosticDescriptor = new DiagnosticDescriptor(
DiagnosticId, title: "", messageFormat: "", category: "",
defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Microsoft.Append(WellKnownDiagnosticTags.NotConfigurable));
public const string RenameFromPropertyKey = "RenameFrom";
public const string RenameToPropertyKey = "RenameTo";
private readonly ITextUndoHistoryRegistry _undoHistoryRegistry;
private readonly IEnumerable<IRefactorNotifyService> _refactorNotifyServices;
protected AbstractRenameTrackingCodeFixProvider(
[ImportingConstructor]
public RenameTrackingCodeRefactoringProvider(
ITextUndoHistoryRegistry undoHistoryRegistry,
IEnumerable<IRefactorNotifyService> refactorNotifyServices)
[ImportMany] IEnumerable<IRefactorNotifyService> refactorNotifyServices)
{
_undoHistoryRegistry = undoHistoryRegistry;
_refactorNotifyServices = refactorNotifyServices;
}
public sealed override ImmutableArray<string> FixableDiagnosticIds
// Internal for testing purposes
internal async Task<Diagnostic?> TryGetDiagnosticAsync(Document document, CancellationToken cancellationToken)
{
get { return ImmutableArray.Create(RenameTrackingDiagnosticAnalyzer.DiagnosticId); }
var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
return RenameTrackingTaggerProvider.TryGetDiagnostic(
syntaxTree, DiagnosticDescriptor, cancellationToken);
}
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var document = context.Document;
var diagnostic = context.Diagnostics.Single();
var (document, span, cancellationToken) = context;
// Ensure rename can still be invoked in this document. We reanalyze the document for
// diagnostics when rename tracking is manually dismissed, but the existence of our
// diagnostic may still be cached, so we have to double check before actually providing
// any fixes.
if (RenameTrackingTaggerProvider.CanInvokeRename(document))
{
var action = RenameTrackingTaggerProvider.CreateCodeAction(document, diagnostic, _refactorNotifyServices, _undoHistoryRegistry);
context.RegisterCodeFix(action, diagnostic);
}
if (!RenameTrackingTaggerProvider.CanInvokeRename(document))
return;
return Task.CompletedTask;
}
var diagnostic = await TryGetDiagnosticAsync(document, cancellationToken).ConfigureAwait(false);
if (diagnostic == null)
return;
public override FixAllProvider GetFixAllProvider()
{
return null;
// user needs to be on the same line as the diagnostic location.
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
if (!text.AreOnSameLine(span.Start, diagnostic.Location.SourceSpan.Start))
return;
var action = RenameTrackingTaggerProvider.CreateCodeAction(
document, diagnostic, _refactorNotifyServices, _undoHistoryRegistry);
context.RegisterRefactoring(action);
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking
{
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
internal sealed class RenameTrackingDiagnosticAnalyzer : DocumentDiagnosticAnalyzer
{
public const string DiagnosticId = "RenameTracking";
public static DiagnosticDescriptor DiagnosticDescriptor = new DiagnosticDescriptor(
DiagnosticId, title: "", messageFormat: "", category: "",
defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Microsoft.Append(WellKnownDiagnosticTags.NotConfigurable));
internal const string RenameFromPropertyKey = "RenameFrom";
internal const string RenameToPropertyKey = "RenameTo";
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptor);
public override async Task<ImmutableArray<Diagnostic>> AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken)
{
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var diagnostic = RenameTrackingTaggerProvider.TryGetDiagnostic(syntaxTree, DiagnosticDescriptor, cancellationToken);
if (diagnostic is null)
{
return ImmutableArray<Diagnostic>.Empty;
}
return ImmutableArray.Create(diagnostic);
}
public override Task<ImmutableArray<Diagnostic>> AnalyzeSemanticsAsync(Document document, CancellationToken cancellationToken)
=> SpecializedTasks.EmptyImmutableArray<Diagnostic>();
}
}
......@@ -33,6 +33,7 @@ public RenameTrackingCodeAction(Document document, string title, IEnumerable<IRe
}
public override string Title => _title;
internal override CodeActionPriority Priority => CodeActionPriority.High;
protected override Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
{
......
......@@ -7,7 +7,6 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
......@@ -300,8 +299,8 @@ internal Diagnostic TryGetDiagnostic(SyntaxTree tree, DiagnosticDescriptor diagn
var textSpan = snapshotSpan.Span.ToTextSpan();
var builder = ImmutableDictionary.CreateBuilder<string, string>();
builder.Add(RenameTrackingDiagnosticAnalyzer.RenameFromPropertyKey, trackingSession.OriginalName);
builder.Add(RenameTrackingDiagnosticAnalyzer.RenameToPropertyKey, snapshotSpan.GetText());
builder.Add(RenameTrackingCodeRefactoringProvider.RenameFromPropertyKey, trackingSession.OriginalName);
builder.Add(RenameTrackingCodeRefactoringProvider.RenameToPropertyKey, snapshotSpan.GetText());
var properties = builder.ToImmutable();
var diagnostic = Diagnostic.Create(diagnosticDescriptor,
......
......@@ -145,8 +145,8 @@ internal static Diagnostic TryGetDiagnostic(SyntaxTree tree, DiagnosticDescripto
var message = string.Format(
EditorFeaturesResources.Rename_0_to_1,
diagnostic.Properties[RenameTrackingDiagnosticAnalyzer.RenameFromPropertyKey],
diagnostic.Properties[RenameTrackingDiagnosticAnalyzer.RenameToPropertyKey]);
diagnostic.Properties[RenameTrackingCodeRefactoringProvider.RenameFromPropertyKey],
diagnostic.Properties[RenameTrackingCodeRefactoringProvider.RenameToPropertyKey]);
return new RenameTrackingCodeAction(document, message, refactorNotifyServices, undoHistoryRegistry);
}
......
......@@ -40,14 +40,14 @@ public void TestNoCyclesInFixProviders()
var actualOrder = ExtensionOrderer.Order(csharpProviders).ToArray();
Assert.True(actualOrder.Length > 0);
Assert.True(actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.AddImport) <
actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.RenameTracking));
actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.FullyQualify));
var vbProviders = providersPerLanguage[LanguageNames.VisualBasic];
ExtensionOrderer.TestAccessor.CheckForCycles(vbProviders);
actualOrder = ExtensionOrderer.Order(vbProviders).ToArray();
Assert.True(actualOrder.Length > 0);
Assert.True(actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.AddImport) <
actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.RenameTracking));
actualOrder.IndexOf(p => p.Metadata.Name == PredefinedCodeFixProviderNames.FullyQualify));
}
[Fact]
......
......@@ -970,12 +970,12 @@ class C$$
state.EditorOperations.InsertText("at");
await state.AssertTag("C", "Cat");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
state.SendEscape();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1139,15 +1139,15 @@ void M()
state.EditorOperations.InsertText("va");
await state.AssertTag("C", "va");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
state.EditorOperations.InsertText("r");
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
state.EditorOperations.InsertText("p");
await state.AssertTag("C", "varp");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1166,7 +1166,7 @@ void M()
using var state = RenameTrackingTestState.Create(code, LanguageNames.CSharp);
state.EditorOperations.Backspace();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1185,7 +1185,7 @@ End Sub
state.EditorOperations.InsertText("var");
await state.AssertTag("C", "var");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1206,15 +1206,15 @@ void M()
state.EditorOperations.InsertText("dynami");
await state.AssertTag("C", "dynami");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
state.EditorOperations.InsertText("c");
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
state.EditorOperations.InsertText("s");
await state.AssertTag("C", "dynamics");
Assert.NotEmpty(await state.GetDocumentDiagnosticsAsync());
Assert.NotNull(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1234,7 +1234,7 @@ void M()
state.EditorOperations.Backspace();
state.EditorOperations.Backspace();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1253,7 +1253,7 @@ End Class
state.EditorOperations.Backspace();
state.EditorOperations.Backspace();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1274,7 +1274,7 @@ void M()
state.EditorOperations.Backspace();
state.EditorOperations.Backspace();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......@@ -1293,7 +1293,7 @@ End Class
state.EditorOperations.Backspace();
state.EditorOperations.Backspace();
await state.AssertNoTag();
Assert.Empty(await state.GetDocumentDiagnosticsAsync());
Assert.Null(await state.TryGetDocumentDiagnosticAsync());
}
[WpfFact]
......
......@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.RenameTracking;
using Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking;
......@@ -50,7 +51,7 @@ internal sealed class RenameTrackingTestState : IDisposable
private readonly MockRefactorNotifyService _mockRefactorNotifyService;
public MockRefactorNotifyService RefactorNotifyService { get { return _mockRefactorNotifyService; } }
private readonly CodeFixProvider _codeFixProvider;
private readonly RenameTrackingCodeRefactoringProvider _codeRefactoringProvider;
private readonly RenameTrackingCancellationCommandHandler _commandHandler = new RenameTrackingCancellationCommandHandler();
public static RenameTrackingTestState Create(
......@@ -111,15 +112,10 @@ internal sealed class RenameTrackingTestState : IDisposable
_tagger = tracker.CreateTagger<RenameTrackingTag>(_hostDocument.GetTextBuffer());
if (languageName == LanguageNames.CSharp)
if (languageName == LanguageNames.CSharp ||
languageName == LanguageNames.VisualBasic)
{
_codeFixProvider = new CSharpRenameTrackingCodeFixProvider(
_historyRegistry,
SpecializedCollections.SingletonEnumerable(_mockRefactorNotifyService));
}
else if (languageName == LanguageNames.VisualBasic)
{
_codeFixProvider = new VisualBasicRenameTrackingCodeFixProvider(
_codeRefactoringProvider = new RenameTrackingCodeRefactoringProvider(
_historyRegistry,
SpecializedCollections.SingletonEnumerable(_mockRefactorNotifyService));
}
......@@ -173,12 +169,10 @@ public async Task AssertNoTag()
Assert.Equal(0, tags.Count());
}
public async Task<IList<Diagnostic>> GetDocumentDiagnosticsAsync(Document document = null)
public Task<Diagnostic> TryGetDocumentDiagnosticAsync(Document document = null)
{
document ??= this.Workspace.CurrentSolution.GetDocument(_hostDocument.Id);
var analyzer = new RenameTrackingDiagnosticAnalyzer();
return (await DiagnosticProviderTestUtilities.GetDocumentDiagnosticsAsync(analyzer, document,
(await document.GetSyntaxRootAsync()).FullSpan)).ToList();
return _codeRefactoringProvider.TryGetDiagnosticAsync(document, CancellationToken.None);
}
public async Task AssertTag(string expectedFromName, string expectedToName, bool invokeAction = false)
......@@ -193,15 +187,16 @@ public async Task AssertTag(string expectedFromName, string expectedToName, bool
var tag = tags.Single();
var document = this.Workspace.CurrentSolution.GetDocument(_hostDocument.Id);
var diagnostics = await GetDocumentDiagnosticsAsync(document);
var diagnostic = await TryGetDocumentDiagnosticAsync(document);
// There should be a single rename tracking diagnostic
Assert.Equal(1, diagnostics.Count);
Assert.Equal(RenameTrackingDiagnosticAnalyzer.DiagnosticId, diagnostics[0].Id);
Assert.NotNull(diagnostic);
Assert.Equal(RenameTrackingCodeRefactoringProvider.DiagnosticId, diagnostic.Id);
var actions = new List<CodeAction>();
var context = new CodeFixContext(document, diagnostics[0], (a, d) => actions.Add(a), CancellationToken.None);
await _codeFixProvider.RegisterCodeFixesAsync(context);
var context = new CodeRefactoringContext(
document, diagnostic.Location.SourceSpan, actions.Add, CancellationToken.None);
await _codeRefactoringProvider.ComputeRefactoringsAsync(context);
// There should only be one code action
Assert.Equal(1, actions.Count);
......
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Editor.Host
Imports Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking
Imports Microsoft.VisualStudio.Text.Operations
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.RenameTracking
' TODO: Remove the ExtensionOrder attributes once a better ordering mechanism is available
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.RenameTracking), [Shared]>
<ExtensionOrder(After:=PredefinedCodeFixProviderNames.AddImport)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.AddMissingReference)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.FullyQualify)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.FixIncorrectExitContinue)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateConstructor)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateEndConstruct)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateEnumMember)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateEvent)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateVariable)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateMethod)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.GenerateType)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.ImplementAbstractClass)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.ImplementInterface)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.MoveToTopOfFile)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.RemoveUnnecessaryCast)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.RemoveUnnecessaryImports)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.SimplifyNames)>
<ExtensionOrder(Before:=PredefinedCodeFixProviderNames.SpellCheck)>
Friend NotInheritable Class VisualBasicRenameTrackingCodeFixProvider
Inherits AbstractRenameTrackingCodeFixProvider
<ImportingConstructor>
Public Sub New(undoHistoryRegistry As ITextUndoHistoryRegistry, <ImportMany> refactorNotifyServices As IEnumerable(Of IRefactorNotifyService))
MyBase.New(undoHistoryRegistry, refactorNotifyServices)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册