Tutorial 1 : Basic Usage - SAlexandru/XCore GitHub Wiki

Turorial 1

Step 0 - Introduction

XCore is a tool helping in the development of software analysis tools (see the Why? wiki page). Thus, as a result of this tutorial, you are going to have a tool whose features will be the computation of two software metrics for object-oriented programs written in Java: i) the number of arguments of a method and ii) the average number of arguments in the methods of a class.

The tool we are going to construct will be an Eclipse plugin. We emphasize that this is not mandatory: in general, the tool can be independent of Eclipse. The single requirement is to develop the tool in the Eclipse IDE because XCore is deployed as an Eclipse plugin (at least at this moment).

Step 1 - Start

Clone the repository and install XCore in Eclipse. The installation is very easy to be performed - see the main XCore wiki page. For the purpose of this tutorial, please also create a new empty workspace (to avoid unanticipated dependencies) and import the ro.lrg.insider project into this workspace. The project contains an Eclipse plugin that we built for easy user interaction. Again, in general, it is not mandatory to be used. That is why we do not ask to install it in your Eclipse instance. Finally, since we build an Eclipse plugin, you must use an Eclipse instance that has all the required plugins for this purpose (e.g., install Eclipse RCP Plug-in Developer Resources, etc.).

NOTE - Do not import the ro.lrg.xcore project into the same workspace because you'll have conflicts with the installed plugin

Step 2 - General configurations

Create an Eclipse Plugin project named TutorialOne. Open the META-INF/MANIFEST.MF file, and go into the Dependences tab. Next, add as imported package the ro.lrg.xcore.metametamodel package.

figures/2.1.png

After that, make sure to disable the automatic project building (uncheck the Project/Build Automatically menu item). This is required because XCore does not permit incremental building of a project (you will see later why).

figures/2.2.png

Next, make sure that XCore annotation processor is enabled for TutorialOne project (via Project Properties/Java Compiler/Annotation Processing/Factory Path).

figures/2.3.png

For clarity, please also rename the generated source directory into metamodel (via Project Properties/Java Compiler/Annotation Processing).

figures/2.4.png

Step 3 - Tool specific configurations

XCore helps building tools but it does not provide any support for source code fact extraction (because it is not its purpose). Since we must compute some metrics for Java code we need a way to be able to analyze/parse Java source code. For this purpose we will use JDT subsystem of Eclipse as a back-end for our tool. In order to be able to access JDT from the tool, we must declare dependencies to it (more precisely to org.eclipse.jdt.core) via MANIFEST.MS/Dependencies. Additionally, our tool will also use the Insider plugin as a front-end (for user interactions). Thus, we must also declare a dependency to it in the same way as in the case of JDT.

figures/3.1.png

Step 4 - Implement the first metric

In project TutorialOne create a package methods. In this package create a class named NoOfArguments and annotate it with @PropertyComputer provided by XCore. Using the Eclipse suggestions, add the corresponding import. Next, each property computer must implement the IPropertyComputer interface that requires two type parameters: i) the first one specifies the type of the property (in this case Integer because our metric is an integer number) and ii) the second one specifies the type of the model entity to which this metric is associated. We will declare that this meta-type is MMethod. Of course, this type does not exist in your project and Eclipse will emphasize the error. But do not hurry to declare it!

figures/4.1.png

Simply clean the project and rebuild it entirely (you can select the Start a build immediately option from the Project/Clean dialog for faster development). As a result, XCore will automatically generate the code of the MMethod meta-type. You will only have to import it in the developed compilation unit and continue the implementation of the metric.

figures/4.2.png

As we already mentioned, XCore does not provide support for code parsing because it is not its purpose. However, it provides support to implement the metric on whatever source code manipulation library you want. In this tutorial, we will use JDT and we will specify that an MMethod wraps an IMethod entity from JDT. Simply go in Project Properties/XCore and specify that as in the figure below. Next, clean and rebuild the entire project.

figures/4.3.png

Next, we can access programmatically the underlying object of an MMethod via the getUnderlyingObject method. Thus, implementing the metric becomes a trivial task (IMethod provides a method to determine the number of arguments of the modeled method). Last, but not least, do not forget to document your metric via a document comment attached to the declared class. Clean and rebuild your project.

figures/4.4.png

Step 5 - Another property

A property is a generalization of the idea of metric. In other words, it is like a metric but it does not necessary return a number. For instance, in the figure below we show how we added the ToString property to our MMethod. It computes the simple name of the modeled method form the investigated system in the form of a String. Please note that this time Eclipse will find the MMethod meta-type :).

Note - Please preserve the name of the property exactly because, in this particular case, we want to also override the toString method in the MMethod meta-type. Since toString is the Java-way to "convert" an object in an user readable form, it should be clear that a tool front-end (in this case Insider) will want to use this method to display information to users.

figures/5.1.png

Step 6 - Your first relation builder

At this point, we can easily observe that we already implemented one of the metrics we intend to implement in this tutorial: the number of arguments for each method from the analyzed system. The metric has been attached to an MMethod meta-type, an object of this kind representing a method from the system under analysis.

It is easy to understand that in a similar manner, we need an MClass meta-type to represent each class from the system under investigation and to attach to it the second metric we planned to implement i.e., the average number of arguments declared in a class. However, let us imagine its implementation in a little bit more detail: to calculate it we will have to sum the number of arguments of each method in a class. Based on a previous property computer, we can already compute the number of arguments for an MMethod. However, we will not be able to obtain easily all the MMethod objects corresponding to the methods declared in a class (more precisely, in an MClass) .

For this purpose, we can use a relation builder. In essence, a group is used to model a containment relation between the elements of a meta-model (e.g., an MClass contains MMethods) and can be used for various purposes (e.g., navigate through the model elements of a system under investigation).

First, create a package named classes in the TutorialOne project. In this package create a class MethodGroup and annotate it with @RelationBuilder annotation provided by XCore. Each group will have to implement the IRelationBuilder interface that will also require two type arguments: i) the type of the elements in the group i.e., in this case, MMethod and ii) the type representing the elements to which the group is attached to i.e., in this case, MClass. After importing the required types you will notice that Eclipse will not be able to find any type having the name MClass. It is correct because this is the first time we introduce such a kind of elements in our tool. However, cleaning and rebuilding the project will enable XCore to also generate the code of the MClass meta-type.

figures/6.1.png

Next, go in Project Properties/XCore and define the type based on which we will implement the basic features of an MClass object. As in the previous case, our implementation will be based on JDT and, more precisely, on the IType type provided by JDT. After this configuration, clean and rebuild the project (to precisely generate the interface that enables a programmer to access the underlying object of an MClass).

figures/6.2.png

Next, we can start implementing the group. We simply get all the IMethod objects from the IType associated to the current MClass and we "transform" them into MMethod objects. To perform this "transformation", XCore automatically generates a singleton abstract factory. It can be accessed via the Factory.getInstance() reference and it provides a createMetaTypeName method for each XCore generated meta-type. Each of these create methods will take as argument a reference to the underlying object of the created entity.

In our concrete case, to get a reference to the MMethod object associated to an IMethod we call the createMMethod method of the factory and we pass to it as argument the reference to the IMethod object. Below we present the code of the MethodGroup group builder. Please also note that the actual result will be a Group object whose implementation is also available in the XCore api.

figures/6.3.png

NOTE - Additional dependencies may be required to be declared by the developed plugin in the Dependencies section of the manifest, depending on your particular implementation. In this case a dependency on "org.eclipse.core.runtime" must be added.

Step 7 - Implement the remaining metric

Now, we can implement the second metric we planed from the beginning. In the classes package create the AvgNoOfArgumentInMethods and annotate it with the @PropertyComputer annotation. It will also have to implement the IPropertyComputer interface. The type of the property will be Double while the property will be associated to the MClass meta-type.

It is important to mention that in order to implement this metric we can reuse the previously defined analyses. In other words please note that the interface of an MClass provides a method named methodGroup that returns the group of all MMethod entities associated to the MClass. The implementation of this operation is based on the previously implemented MethodGroup class.

Similarly, please note that the interface of an MMethod provides a method named noOfArguments. As can be seen in the following figure, Eclipse is also able to find that method and, additionally, it also displays to the developer the documentation associated to the implementation of the NoOfArguments property computer :).

figures/7.1.png

The final implementation of the metric is displayed in the following figure.

figures/7.2.png

For user interaction reasons, we also implement the ToString property for an MClass object. The corresponding code is presented below. After implementing this property, clean and rebuild the entire project.

figures/7.3.png

Step 8 - Interacting with the user via the Insider plug-in

At this moment the tool is almost ready to be used: it still needs a way to interact with the human user. We also provide Insider front-end, an Eclipse plugin that enables the interaction with an XCore tool via a dedicated Eclipse view. We emphasize again that Insider usage is not mandatory - it is only a ready-to-use front-end to interact with your tool. Moreover, after your tool is compiled, you do not need the XCore plugin to run your tool (you only need the Insider plugin or you need to extract in a separate jar the lib code defined by XCore, already present in Insider).

In order to use your tool via Insider, add an org.eclipse.ui.startup extension to the TutorialOne plugin. To perform this task, go to MANIFEST.MF/Extensions tab. The Add button helps in the selection of the extension. Next, declare the required class.

figures/8.1.png

The extension is used to automatically register TutorialOne tool in the Insider plugin when Eclipse starts. This registration is performed via the ToolRegistration.getInstance().registerXEntityConverter method.

You will have to implement and provide as argument an object of ToolRegistration.XEntityConverter type provided by Insider. In the implementation, you must define the convert method that is invoked by Insider when it has to "convert" an Object in the representation used by the tool e.g., to get the MMethod corresponding to a JDT IMethod. In general, if a tool does not have a dedicated representation for a particular kind of object, null is returned by the convert method. Otherwise, the object prepared by the tool factory is returned.

The code required to register TutotialOne to Insider is presented below.

figures/8.2.png

We mention that actions can be declared for meta-types as in the figure below, to enable the user to perform various activities over these types e.g., open the corresponding entity into the Eclipse editor

figures/8.3.png

Step 9 - Run your tool

Yes. You can now run the tool. Select the TutorialOne project, right-click and select Run As/Eclipse Application as in the following figure.

figures/9.1.png

A new Eclipse instance will start (probably with an empty workspace). In this "novel" Eclipse, create an Eval project as in the figure below. We added to it a class named SomeClass having one no-arg constructor and another method with one argument.

figures/9.2.png

In the Package Explorer view, select the visual element corresponding to the SomeClass class and right-click on it. The displayed pop-up menu must have an entry named Browse in Insider as in the next figure. Click on that menu entry.

figures/9.3.png

As an effect, the Insider view must open and its table will contain exactly one row in which the SomeClass entity is displayed (together with the value of its ToString property).

figures/9.4.png

Right-click on this row and a pop-up menu will open enabling you to navigate through the properties, groups and actions corresponding to the type of that entity. In particular, you will probably be interested in seeing the values of your AvgNoOfArgumentsInMethods metric / property. Select it as in the next figure.

figures/9.5.png

As a result, the value of the metric should be displayed. Using the pop-up menu you can navigate through the model by selecting groups associated to a particular entity. Enjoy! :)

figures/9.6.png

Step 10 - Understanding what happens in the background and the advantages

The actions performed by XCore can be observed in the following figure. During project compilation, XCore captures all the properties, groups, actions and meta-types representing entities involved in the analyses performed by the tool. Next, it generates a meta-model (i.e. types and classes for the modeled entities) and associates the corresponding properties and groups to these meta-types.

figures/10.1.png

Now, you can start seeing at least some of the advantages:

  • The meta-model is automatically generated, freeing the developer of such repetitive implementation actions

  • The meta-model is easy to extend e.g., simply add other classes representing groups or properties and XCore will automatically attached them as an operation available on the corresponding meta-type; by simply mentioning a new meta-type name in a property or group, XCore will also generate the required code for that novel type of entity from your model

  • Analyses can be reused easily. You can build other analyses involving a meta-type based on its interface operations e.g., we built the average number of parameters at the class level by reusing the number of arguments metric at the method level

  • XCore tries to preserve static typing, it tries to enable a compiler to detect errors in the usage of the meta-types, of their analyses, etc. e.g., i) by specifying the correspondence between the XCore meta-types and the underlying types used to parse/represent the source code, XCore generates a type-safe declaration for the return type of the getUnderlyingObject method ii) by attaching an analysis to a meta-type, it ensures that an analysis is performed on the targeted type of entity from the investigated program