是否可以在运行时将完成项添加到 Microsoft 语言服务器?

Is it possible to add completion items to a Microsoft Language Server in runtime?

我正在尝试开发一个 IntelliJ 插件,它在 ballerina 的 lsp4intellij 的帮助下提供语言服务器。

事情是,我有一个特殊条件:完成项列表应该在运行时是可编辑的。

但是我还没有找到任何方法将新的 completionItems 传送到 LanguageServer 进程 运行。

我目前的想法是向插件添加一个操作,该操作会构建一个新的 jar,然后使用 Java 编译器 API.

使用新的 jar 重新启动服务器

问题是,我需要从插件项目中获取源代码,包括可从 运行 插件访问的 gradle 依赖项...有什么想法吗?

如果您的要求是在 IntelliJ UI 中显示之前修改完成项(来自语言服务器),您可以通过实现 LSP4IntelliJ 的 LSPExtensionManager 在你的插件中。

目前,我们没有关于 LSP4IntelliJ 扩展点的适当文档,但您可以参考我们的 Ballerina IntelliJ 插件作为参考实现,它已经实现了 Ballerina LSP Extension manager to override/modify completion items at the client runtime in here

对于那些可能偶然发现这一点的人 - 确实可以更改 LanguageServer 在运行时可以提供的 CompletionItems 的数量。

我简单地编辑了TextDocumentService.java(我使用的库是LSP4J)。

它是这样工作的:

LanguageServer 的主要功能需要使用一个附加参数启动,该参数是您定义 CompletionItems 的配置文件的路径。 从 LSP4IntelliJ 调用它看起来像这样:

 String[] command = new String[]{"java", "-jar",
 "path\to\LangServer.jar", "path\to\config.json"};

 IntellijLanguageClient.addServerDefinition(new RawCommandServerDefinition("md,java", command));

然后,路径字符串将传递给 CustomTextDocumentServer.java 的构造函数,后者将在新的计时器线程中解析 config.json。

一个例子:

public class CustomTextDocumentService implements TextDocumentService {

private List<CompletionItem> providedItems;
private String pathToConfig;

public CustomTextDocumentService(String pathToConfig) {
    this.pathToConfig = pathToConfig;

    Timer timer = new Timer();
    timer.schedule(new ReloadCompletionItemsTask(), 0, 10000);

    loadCompletionItems();
}

@Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams completionParams) {
    return CompletableFuture.supplyAsync(() -> {
        List<CompletionItem> completionItems;

        completionItems = this.providedItems;

        // Return the list of completion items.
        return Either.forLeft(completionItems);
    });
}

@Override
public void didOpen(DidOpenTextDocumentParams didOpenTextDocumentParams) {

}

@Override
public void didChange(DidChangeTextDocumentParams didChangeTextDocumentParams) {

}

@Override
public void didClose(DidCloseTextDocumentParams didCloseTextDocumentParams) {

}

@Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {

}

private void loadCompletionItems() {
    providedItems = new ArrayList<>();

    CustomParser = new CustomParser(pathToConfig);  
    ArrayList<String> variables = customParser.getTheParsedItems();

    for(String variable : variables) {

        String itemTxt = "$" + variable + "$";

        CompletionItem completionItem = new CompletionItem();
        completionItem.setInsertText(itemTxt);
        completionItem.setLabel(itemTxt);
        completionItem.setKind(CompletionItemKind.Snippet);
        completionItem.setDetail("CompletionItem");

        providedItems.add(completionItem);
    }
}

class ReloadCompletionItemsTask extends TimerTask {
    @Override
    public void run() {
        loadCompletionItems();
    }
}
}