Search code examples
rascal

Custom Rascal location protocols for M3


The Java specific M3 has these pretty location protocols like java+method, java+enum, java+variable and many more. As far as I understand these pretty locations function as aliases for "real" locations like |project://example-project/src/HelloWorld.java|(0,1,<2,3>,<4,5>), referring to a specific piece of code within that file.

I would like to create those pretty locations for my own CSS specific M3. So they should look something like css+declaration or css+ruleset. I already have the actual "real" locations which I now directly pass on to the M3 Core. But this looks really messy and you cannot tell the locations apart.

So how do link my "real" locations to these pretty locations so that they actually function within the Rascal terminal? Can someone tell me the steps required to achieve this? Or maybe show me an example? I have already looked at the implementation for the Java specific M3 but I cannot seem to get my head around it.


Solution

  • Great question. To register the locations such that they are resolved on the REPL and in the IDE for opening files and such you have to register them with the "name server"

    import analysis::m3::Registry;
    registerProject(|project://myProject|, myM3Model); // side-effect alert!
    

    This code will use the @declarations table from your M3 model which should map your logical locs to your physical locs.

    It does that like so:

    void registerProject(loc project, M3 model) {
        rel[str scheme, loc name, loc src] perScheme 
          = {<name.scheme, name, src> | <name, src> <- model@declarations};
    
        for (str scheme <- perScheme<scheme>)
           registerLocations(scheme, project.authority, (name : src | <name, src> <- perScheme[scheme]));
    }
    

    From this code you can also learn that calling registerLocations directly is also possible. This basically adds a lookup map to the lookup registry, first indexed by scheme, then by authority and finally by path name.