2

My Program object from Java2OFG does not contain any hashmap put calls, but can find hashmap remove and containsValue calls.

p = createOFG(|project://eLib|);
println(p);

Shows:

call(|id:///|,|id:///|,|java+field:///Library/users|,|java+method:///java/util/Map/containsValue(java.lang.Object)|,[|java+parameter:///Library/addUser(User)/scope(user)/scope(0)/user|])

call(|id:///|,|id:///|,|java+field:///Library/users|,|java+method:///java/util/Map/remove(java.lang.Object)|,[|java+method:///Library/removeUser(int)/__param555_0|])

But no mention of any put calls, while put calls are present in the java code.

Kasper
  • 53
  • 7

1 Answers1

1

Indeed, some methods are there, but others are not:

rascal>p = createOFG(|project://eLib|);
... 
rascal>cv = |java+method:///java/util/Map/containsValue(java.lang.Object)|;
loc: |java+method:///java/util/Map/containsValue(java.lang.Object)|
rascal>/c:call(_,_,_,cv,_) := p ? c : "bla"
Stm: call(
  |id:///|,
  |id:///|,
  |java+field:///Library/users|,
  |java+method:///java/util/Map/containsValue(java.lang.Object)|,
  [|java+parameter:///Library/addUser(User)/scope(user)/scope(0)/user|])

rascal>cv = |java+method:///java/util/Map/put(java.lang.Object,java.lang.Object)|;
loc: |java+method:///java/util/Map/put(java.lang.Object,java.lang.Object)|
rascal>/c:call(_,_,_,cv,_) := p ? c : "bla"
value: "bla"

So, these queries shows that the flow program indeed contains a call to containsValue but not to put.

While reading the code of lang::ofg::ast::Java2OFG it seems something special is going on with some of the methods in container classes. Instead of calls to put ending up as a call in the flow language, these method calls are transformed into assignments! This means that Java2OFG models flow into a collection using a special abstract symbolic variable, i.e. map's put method is modeled as an variable assignment and get as a variable lookup.

That's a correct model, and useful otherwise data would flow into the container API, for which we have no model of the internals, and would never come out again.

The algorithm missed edges from the key of a map to the receiver though, and also skipped flow from primitive types. A new version is published here: https://gist.github.com/jurgenvinju/60645058b6d0b0ccce0fc6f856da6ea6

Jurgen Vinju
  • 6,393
  • 1
  • 15
  • 26
  • We can also find the `containsValue` call, but not a `put` call. – Kasper Mar 08 '17 at 15:51
  • 1
    I adapted the answer; so now we know what's going on. use the force, read the source :-) – Jurgen Vinju Mar 08 '17 at 18:37
  • We have found the assignment `assign(|java+field:///Library/users|,|id:///|,|java+parameter:///Library/addUser(User)/scope(user)/scope(0)/user|)` But this only gives us the assignment for the **value** and not the **key** of the map. When we checked the source code of Java2OFG.rsc we found that indeed no assignment is made for the key. How can we determine what the type of the key will be, without altering the Java2OFG.rsc? – Kasper Mar 08 '17 at 20:37
  • Good analysis, and question. Let's think about this before we make a rash decision. Alternatives: add an assignment for the key, or, remove the whole special treatment and leave it to the user of the library (adds need to analyze Java ASTs), or, leave the old call relation in AND add the assignment for the value. What do you think? – Jurgen Vinju Mar 09 '17 at 07:46
  • found some more issues. will rewrite Java2ObjectFlow a bit. – Jurgen Vinju Mar 09 '17 at 11:11
  • see https://gist.github.com/jurgenvinju/60645058b6d0b0ccce0fc6f856da6ea6 – Jurgen Vinju Mar 09 '17 at 11:18