Search code examples
dslxtextlanguage-server-protocol

Invoking Xtext Generator via Language Server Protocol explicitly


I have a DSL project using Xtext together with the Language Server Protocol.

Now I want to trigger a Generator from the client (in my case VS Code) to be executed on the server. Not automatically (I would know how to do that), but explicitly triggered by the user from a VS Code command.

I am aware of the IExecutableCommandService in Xtext and I know how to hook into it. But I don't know how to retrieve the corresponding Resource from a given file path:

@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";
    
}

The use-case is the same as described in this blog: https://dietrich-it.de/xtext/2011/10/15/xtext-calling-the-generator-from-a-context-menu/ But the description is for Eclipse only (not using lsp).


Solution

  • If you already have the correct URI, you should be able to use XtextResourceSet to get access to the resource:

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

    otherwise you can get access to the Xtext index and iterate over all resources searching for the resource of interest, by using 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);