Вызов генератора Xtext через протокол языкового сервера явно

#dsl #xtext #language-server-protocol

Вопрос:

У меня есть проект DSL, использующий Xtext вместе с протоколом языкового сервера.

Теперь я хочу запустить генератор от клиента (в моем случае VS-код), который будет выполняться на сервере. Не автоматически (я бы знал, как это сделать), но явно запускается пользователем из команды VS Code.

Я знаю о IExecutableCommandService в Xtext и знаю, как подключиться к нему. Но я не знаю, как получить соответствующий ресурс из заданного пути к файлу:

 @Override
public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, CancelIndicator cancelIndicator) {

    
    if ("c4.generator.type".equals(params.getCommand())) {  
        
        // fileURI passed from client to the server
        String fileURI = ((JsonPrimitive)params.getArguments().get(0)).getAsString();
        
        // This is where I stuck
        Resource resource = whatAPItoCallToRetrieveResourceFromFile(fileURI);
        
        // Call the generator then
        doGenerate(resource);
    }
    
    return "Unknown Command";
    
}
 

Пример использования такой же, как описано в этом блоге: https://dietrich-it.de/xtext/2011/10/15/xtext-calling-the-generator-from-a-context-menu/
Но описание предназначено только для Eclipse (без использования lsp).

Ответ №1:

Если у вас уже есть правильный URI, вы должны иметь возможность использовать XtextResourceSet его для получения доступа к ресурсу:

 final XtextResourceSet rs = new XtextResourceSet();
final Resource r = rs.getResource(fileURI, true);

doGenerate(r);
 

в противном случае вы можете получить доступ к индексу Xtext и выполнить итерацию по всем ресурсам в поисках интересующего ресурса, используя access.doReadIndex :

 final XtextResourceSet rs = new XtextResourceSet();

final Function<ILanguageServerAccess.IndexContext, Boolean> func = (
        ILanguageServerAccess.IndexContext ctxt) -> {
    for (final IResourceDescription rd: ctxt.getIndex().getAllResourceDescriptions()) {     
        if(<check_rd>) {
            Resource r = rs.getResource(rd.getURI(), true);
            doGenerate(r);
        }
    }
    return true;
};
access.doReadIndex(func);