Search code examples
rascal

Filtering set by classes information


Suppose I want to get all fields from some OFG g while ignoring fields like |java+field:///java/lang/System/err|. How do I check whether the resulting field actually refers to some class from the imported project?

My attempt is this. Here the compiler lights up at <- classes. So it doesn't allow from.path. Which I think should be possible.

g = buildGraph(createOFG(|project://eLib|));
m = createM3FromEclipseProject(|project://eLib|);
set[str] classes = { cl.path | cl <- classes(m) };
set[loc] fields = { from | <from,_> <- g, 
                       from.scheme == "java+field", from.path <- classes };

How could I make this work?


Solution

  • Simple answer: from.path is not a pattern syntax, so you can use a variable instead:

     set[loc] fields = { from | <from,_> <- g, 
                       from.scheme == "java+field", x <- classes, x == from.path };
    

    or

     set[loc] fields = { from | <from,_> <- g, 
                       from.scheme == "java+field", x := from.path, x <- classes };
    

    A nice solution to the problem could be to use the containment relation m@containment, if you transitively close it m@containment* and query from the top you know if something is in the project, like myField in m@containment*[ |java+package:///elib|].

    It's good to keep the m@containment*[ |java+package:///elib|] around in a variable since it is an expensive computation.

    You can find out what the top of the containment relation is like so:

    rascal> import analysis::graphs::Graph; // or import Graphs; in older versions
    ok
    rascal> top(m@containment)
    set[loc]: {
       |java+package:///org|,
       |java+package:///vinju|
    }