[英]Roslyn CodeFixProvider: Move caret after applying code fix
我實現了一個自定義CodeFixProvider,它向成員添加了一些XML文檔。
例:
public void MyMethod() { }
將被轉換為
/// <summary></summary>
public void MyMethod() { }
CodeFixProvider的實現如下:
public class MyCodeFixProvider : CodeFixProvider
{
...
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
await Task.Run(() =>
{
Diagnostics diagnostics = context.Diagnostics.First();
CodeAction codeFix = CodeAction.Create("Title", c => CreateXmlDocs(...));
context.RegisterCodeFix(codeFix, diagnostics);
}
).ConfigureAwait(false);
}
...
}
一切都按預期進行。
現在,我想添加一些額外的功能:應用代碼修復后,插入符號應移至空的Summary標簽內。
我發現Microsoft.CodeAnalysis.Features NuGet包中包含的DocumentNavigationOperation類。 此類應能夠將插入符號移動到指定位置。 但是我找不到任何有關如何使用此類的說明。 如果我從CreateXmlDocs方法內部調用它,則會引發異常:
Navigation must be performed on the foreground thread.
碼:
private static async Task<Solution> CreateXmlDocs()
{
...
new DocumentNavigationOperation(newDocument.Id, 42)
.Apply(newDocument.Project.Solution.Workspace, cancellationToken);
...
}
我不確定在CreateXmlDocs方法中使用此類是否有意義,因為在調用DocumentNavigationOperation時,Visual Studio尚未應用在此方法中創建的新解決方案。
有人知道在應用代碼修復后移動插入符號的解決方案嗎?
好的,與此同時我找到了解決方案。
需要自定義CodeAction
才能使其正常工作:
internal class NavigateAfterCodeChangeAction : CodeAction
{
private readonly Func<CancellationToken, Task<Solution>> codeChangeOperation;
private readonly Func<Solution, CancellationToken, Task<NavigationTarget>> navigationTargetCalculation;
public NavigateAfterCodeChangeAction(
string title,
Func<CancellationToken, Task<Solution>> codeChangeOperation,
Func<Solution, CancellationToken, Task<NavigationTarget>> navigationTargetCalculation)
{
this.Title = title;
this.codeChangeOperation = codeChangeOperation;
this.navigationTargetCalculation = navigationTargetCalculation;
}
public override string Title { get; }
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
{
var operations = new List<CodeActionOperation>();
Solution changedSolution = await this.codeChangeOperation(cancellationToken);
NavigationTarget navigationTarget = await this.navigationTargetCalculation(changedSolution, cancellationToken);
operations.Add(new ApplyChangesOperation(changedSolution));
if (navigationTarget != null)
{
operations.Add(new DocumentNavigationOperation(navigationTarget.DocumentId, navigationTarget.Position));
}
return operations;
}
}
internal class NavigationTarget
{
public NavigationTarget(DocumentId documentId, int position)
{
this.DocumentId = documentId;
this.Position = position;
}
public DocumentId DocumentId { get; }
public int Position { get; }
}
新CodeAction
可以在使用CodeFixProvider
代替CodeAction.Create()
public class MyCodeFixProvider : CodeFixProvider
{
...
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
await Task.Run(() =>
{
Diagnostics diagnostics = context.Diagnostics.First();
CodeAction codeFix = new NavigateAfterCodeChangeAction(
"Title",
c => CreateXmlDocs(...)
(s, c) => CalculateNavigationTarget(context.Document));
context.RegisterCodeFix(codeFix, diagnostics);
}
).ConfigureAwait(false);
}
private static NavigationTarget CalculateNavigationTarget(Document doc)
{
// Calculate the navigation target here...
// Example: Navigate to position 42 of the document
return new NavigationTarget(doc.Id, 42);
}
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.