我正在尝试使用自定义自动完成功能为 VS (2022) 编写扩展,但我遇到了一些问题。我想做两件事:
来源:
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Completion;
using System.Composition;
using Microsoft.IO;
namespace Fruits_VS
{
[ExportCompletionProvider(nameof(ColorCompletionProvider), LanguageNames.CSharp)]
[Shared]
internal sealed class ColorCompletionProvider : CompletionProvider
{
public override async Task ProvideCompletionsAsync(CompletionContext context)
{
var document = context.Document;
var position = context.Position;
var cancellationToken = context.CancellationToken;
var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken);
var token = syntaxRoot.FindToken(position);
var triviaList = token.LeadingTrivia;
string currentLine = await GetCurrentLineTextAsync(context);
int indexOfAt = currentLine.LastIndexOf('@');
int indexOfColon = currentLine.LastIndexOf(':');
if (indexOfAt >= 0 && indexOfColon < 0)
{
context.AddItem(CompletionItem.Create("@fruits:"));
}
else if (indexOfAt >= 0 && indexOfColon > indexOfAt)
{
foreach (var trivia in triviaList)
{
if (!trivia.ToString().Contains("@fruits:")) continue;
var colors = new[] { "apple", "cherry", "banana" };
foreach (var fruit in fruits)
{
context.AddItem(CompletionItem.Create(fruit));
}
break;
}
}
}
private async Task<string> GetCurrentLineTextAsync(CompletionContext context)
{
var text = await context.Document.GetTextAsync();
var position = context.Position;
var line = text.Lines.GetLineFromPosition(position);
return text.ToString(line.Span);
}
public override bool ShouldTriggerCompletion(SourceText text, int caretPosition, CompletionTrigger trigger, OptionSet options)
{
if (trigger.Kind == CompletionTriggerKind.Invoke)
{
return true;
}
if (trigger.Kind == CompletionTriggerKind.Insertion && caretPosition > 0)
{
var currentCharacter = text[caretPosition - 1];
var previousCharacter = caretPosition > 1 ? text[caretPosition - 2] : '\0';
//here i tried all possible combination to trigger :(
return (currentCharacter == '@' && char.IsWhiteSpace(previousCharacter))
|| (currentCharacter == ':' && text.ToString().Contains('@'));
}
return false;
}
}
}