我已经实现了一个自定义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);
}
...
}
一切都像预期的那样发挥作用。
现在我想添加一些额外的功能:应用代码修复后,应将插入符号移到空摘要标记内。
我发现了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尚未应用此方法中创建的新解决方案。
有人知道在应用代码修复后移动插入符号的解决方案吗?
答案 0 :(得分:0)
好的,与此同时我找到了解决方案。
要使其正常运行,需要使用自定义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);
}
...
}