Navigation
Synopsis A few steps using the M3 model to compute basic metrics for a Java project in Eclipse
Description This is a recipe for computing basic or more advanced metrics from a Java project in Eclipse. We assume:
  • You have Rascal installed in an Eclipse instance.
  • You have a Java project in your Eclipse workspace that compiles without errors. Let's call it HelloWorld.
Now we will follow the EASY paradigm: These are a number of recipes for measuring different things about Java:
Examples First we import the basic data types for representing Java. The model is called M3, and its definition is split acros a generic language independent module called Rascal:analysis/m3/Core and a Java specific part called Rascal:lang/java/m3/Core. Have a look at the documentation of these modules later. For now we will go through using them in a few examples.
rascal>import lang::java::m3::Core;
ok
Then we import the API for extracting an M3 model from an Eclipse project.
rascal>import lang::java::jdt::m3::Core;
ok
Calling the following function generates an enormous value representing everything the Eclipse Java compiler knows about this project:
rascal>myModel = createM3FromEclipseProject(|project://example-project|);
M3: m3(|project://example-project|)[
  @annotations={
    <|java+method:///Apple/edible()|,|java+interface:///java/lang/Override|>,
    <|java+method:///Fruit/edible()|,|java+interface:///java/lang/Override|>
  },
  @typeDependency={
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+class:///java/io/PrintStream|>,
    <|java+method:///Apple/edible()|,|java+primitiveType:///boolean|>,
    <|java+method:///Apple/edible()|,|java+interface:///java/lang/Override|>,
    <|java+method:///Fruit/edible()|,|java+primitiveType:///boolean|>,
    <|java+method:///Fruit/edible()|,|java+interface:///java/lang/Override|>,
    <|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|,|java+array:///java/lang/String%5B%5D|>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+class:///java/lang/System|>,
    <|java+class:///Apple|,|java+class:///Fruit|>,
    <|java+method:///IFruit/edible()|,|java+primitiveType:///boolean|>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+primitiveType:///void|>,
    <|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|,|java+class:///java/lang/String|>,
    <|java+class:///Fruit|,|java+interface:///IFruit|>
  },
  @methodOverrides={
    <|java+method:///Apple/edible()|,|java+method:///IFruit/edible()|>,
    <|java+method:///Fruit/edible()|,|java+method:///IFruit/edible()|>,
    <|java+method:///Apple/edible()|,|java+method:///Fruit/edible()|>
  },
  @names={
    <"IFruit",|java+interface:///IFruit|>,
    <"HelloWorld",|java+class:///HelloWorld|>,
    <"args",|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|>,
    <"edible",|java+method:///Fruit/edible()|>,
    <"out",|java+field:///java/lang/System/out|>,
    <"edible",|java+method:///Apple/edible()|>,
    <"main",|java+method:///HelloWorld/main(java.lang.String%5B%5D)|>,
    <"String",|java+class:///java/lang/String|>,
    <"edible",|java+method:///IFruit/edible()|>,
    <"println",|java+method:///java/io/PrintStream/println(java.lang.String)|>,
    <"Override",|java+interface:///java/lang/Override|>,
    <"System",|java+class:///java/lang/System|>,
    <"Apple",|java+class:///Apple|>,
    <"Fruit",|java+class:///Fruit|>
  },
  @implements={<|java+class:///Fruit|,|java+interface:///IFruit|>},
  @methodInvocation={<|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+method:///java/io/PrintStream/println(java.lang.String)|>},
  @containment={
    <|java+compilationUnit:///src/IFruit.java|,|java+interface:///IFruit|>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|>,
    <|java+class:///Fruit|,|java+method:///Fruit/edible()|>,
    <|java+class:///HelloWorld|,|java+method:///HelloWorld/main(java.lang.String%5B%5D)|>,
    <|java+compilationUnit:///src/Fruit.java|,|java+class:///Fruit|>,
    <|java+compilationUnit:///src/HelloWorld.java|,|java+class:///HelloWorld|>,
    <|java+class:///Apple|,|java+method:///Apple/edible()|>,
    <|java+interface:///IFruit|,|java+method:///IFruit/edible()|>,
    <|java+compilationUnit:///src/Apple.java|,|java+class:///Apple|>
  },
  @documentation={},
  @modifiers={
    <|java+interface:///IFruit|,public()>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,static()>,
    <|java+class:///Fruit|,abstract()>,
    <|java+method:///Apple/edible()|,public()>,
    <|java+method:///Fruit/edible()|,public()>,
    <|java+class:///Apple|,public()>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,public()>,
    <|java+class:///HelloWorld|,public()>,
    <|java+method:///Fruit/edible()|,abstract()>,
    <|java+class:///Fruit|,public()>
  },
  @fieldAccess={<|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|java+field:///java/lang/System/out|>},
  @messages=[],
  @uses={
    <|project://example-project/src/Apple.java|(28,5,<2,27>,<2,32>),|java+class:///Fruit|>,
    <|project://example-project/src/HelloWorld.java|(71,6,<4,2>,<4,8>),|java+class:///java/lang/System|>,
    <|project://example-project/src/HelloWorld.java|(82,7,<4,13>,<4,20>),|java+method:///java/io/PrintStream/println(java.lang.String)|>,
    <|project://example-project/src/Fruit.java|(51,8,<3,2>,<3,10>),|java+interface:///java/lang/Override|>,
    <|project://example-project/src/Apple.java|(39,8,<4,2>,<4,10>),|java+interface:///java/lang/Override|>,
    <|project://example-project/src/HelloWorld.java|(78,3,<4,9>,<4,12>),|java+field:///java/lang/System/out|>,
    <|project://example-project/src/Fruit.java|(40,6,<2,39>,<2,45>),|java+interface:///IFruit|>,
    <|project://example-project/src/HelloWorld.java|(52,6,<3,25>,<3,31>),|java+class:///java/lang/String|>
  },
  @types={
    <|java+class:///HelloWorld|,class(
      |java+class:///HelloWorld|,
      [])>,
    <|java+class:///Fruit|,class(
      |java+class:///Fruit|,
      [])>,
    <|java+class:///Apple|,class(
      |java+class:///Apple|,
      [])>,
    <|java+method:///IFruit/edible()|,method(
      |java+method:///IFruit/edible()|,
      [],
      boolean(),
      [])>,
    <|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|,array(
      class(
        |java+class:///java/lang/String|,
        []),
      1)>,
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,method(
      |java+method:///HelloWorld/main(java.lang.String%5B%5D)|,
      [],
      void(),
      [array(
          class(
            |java+class:///java/lang/String|,
            []),
          1)])>,
    <|java+method:///Apple/edible()|,method(
      |java+method:///Apple/edible()|,
      [],
      boolean(),
      [])>,
    <|java+method:///Fruit/edible()|,method(
      |java+method:///Fruit/edible()|,
      [],
      boolean(),
      [])>,
    <|java+interface:///IFruit|,interface(
      |java+interface:///IFruit|,
      [])>
  },
  @extends={<|java+class:///Apple|,|java+class:///Fruit|>},
  @declarations={
    <|java+method:///HelloWorld/main(java.lang.String%5B%5D)|,|project://example-project/src/HelloWorld.java|(28,82,<3,1>,<6,2>)>,
    <|java+compilationUnit:///src/IFruit.java|,|project://example-project/src/IFruit.java|(0,48,<1,0>,<4,2>)>,
    <|java+method:///Apple/edible()|,|project://example-project/src/Apple.java|(38,54,<4,1>,<7,2>)>,
    <|java+parameter:///HelloWorld/main(java.lang.String%5B%5D)/args|,|project://example-project/src/HelloWorld.java|(52,13,<3,25>,<3,38>)>,
    <|java+compilationUnit:///src/HelloWorld.java|,|project://example-project/src/HelloWorld.java|(0,113,<1,0>,<7,2>)>,
    <|java+class:///HelloWorld|,|project://example-project/src/HelloWorld.java|(1,111,<2,0>,<7,1>)>,
    <|java+compilationUnit:///src/Apple.java|,|project://example-project/src/Apple.java|(0,96,<1,0>,<9,2>)>,
    <|java+class:///Apple|,|project://example-project/src/Apple.java|(1,94,<2,0>,<9,1>)>,
    <|java+class:///Fruit|,|project://example-project/src/Fruit.java|(1,95,<2,0>,<5,1>)>,
    <|java+interface:///IFruit|,|project://example-project/src/IFruit.java|(1,46,<2,0>,<4,1>)>,
    <|java+compilationUnit:///src/Fruit.java|,|project://example-project/src/Fruit.java|(0,97,<1,0>,<5,2>)>,
    <|java+method:///IFruit/edible()|,|project://example-project/src/IFruit.java|(28,17,<3,1>,<3,18>)>,
    <|java+method:///Fruit/edible()|,|project://example-project/src/Fruit.java|(50,44,<3,1>,<4,34>)>
  }
]
Benefits
  • Notice that all these Rascal:Location literals are hyperlinks and you can click on them to go the source code that they point to. Try it!
Is this page unclear, or have you spotted an error? Please add a comment below and help us to improve it. For all other questions and remarks, visit ask.rascal-mpl.org.