Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering

User Tools

Site Tools


This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
research:jtransformer:tutorial:analysis_cc [2014/09/09 09:50]
research:jtransformer:tutorial:analysis_cc [2018/05/09 01:59] (current)
Line 1: Line 1:
 +====== Adding Analyses to the JT GUI ======
 +Once you have written a predicate (e.g. the [[analysis|System.out.println detector]]) you can query it interactively in the Prolog Console. However, that is not really nice since it means a lot of typing and the results are just text with lots of element IDs that are hard to interpret by a human.
 +This section tells you how to let JTransformer know that your predicate should be 
 +  * shown as an analysis in the '​[[control_center|Control Center]]'​
 +  * run at the click of a button or even automatically ​
 +and that its results should be
 +  * indicated by markers in Java source code 
 +  * displayed in the [[viewing_results|result overview table]].
 +The visual effects of these declarations are shown in the [[control_center|Control Center]] section.
 +===== Declaring Analyses for the GUI =====
 +The predicate //​analysis_api:​analysis_definition(Name,​ Trigger, Severity, Category, Description) // tells the JT [[control_center|Control Center]] about an analysis that it should display. Its six arguments define properties of the analysis:
 +  * **Name** is the name of the analysis. It is used when providing results for this analysis. This can be any atom.
 +  * **Trigger** specifies if this analysis is executed automatically or manually. There are two possible values:
 +    * //onSave//: This analysis is executed after each update of the factbase caused by modification of any files contained in the factbase.
 +    * //​manually//:​ This analysis is only executed explicitly using the [[control_center|Control Center]].
 +  * **Severity** defines the kind of the marker created in Eclipse for each result. Possible values are //info//, //warning// and //error//.
 +  * **Category** is the category of this analysis. Analysis are grouped by category in the [[control_center|Control Center]].
 +  * **Description** is the description of this analysis. It is shown in the [[control_center|Control Center]].
 +The following listing shows the definition of the //​System.out.println//​ detector from our this tutorial.
 +% The predicate analysis_definition/​5 logically belongs to the  ​
 +% analysis_api module but clauses can be defined in many files:  ​
 +:- multifile(analysis_api:​analysis_definition/​5).  ​
 +% The clause defining the System.out.println detector:
 +     '​sysout_call', ​                    % Name
 +     ​onSave, ​                           % Trigger
 +     ​warning, ​                          % Severity
 +     '​Logging', ​                        % Category
 +     '​Call to System.out.println' ​      % Description
 +===== Wrapping Analysis Results for the GUI =====
 +Implementing a clause for the multifile predicate **analysis_api:​analysis_result/​3** makes the
 +results of you analysis predicate accessible to the GUI of JT. The predicate to implement has three arguments:
 +  * **Name** is the name of the analysis for which results should be provided. It must be the same name that was provided in the related ''​analysis_api:​analysis_definition''​ clause. ​
 +  * **Group** is an arbitrary Prolog term that is used to identify analysis results that logically belong together. An analysis (e.g. the //Singleton Pattern Detection//​) may find multiple results that are connected. In such a case we say that the connected results belong to the same group. This is indicated by the same identifying term. Other analyses (e.g. //Depth of inheritance (DOI)//) find only individual results (conceptually each group has only one element). In this case the Group argument must be a free variable (typically, the anonymous variable _).
 +  * **Result** is a term describing a result. It is generated using the predicate //​make_result_term/​3//​ and contains ​
 +    * the ID of the result PEF, 
 +    * the role of this PEF (if the result is part of a group), ​
 +    * a description to be displayed (a natural language explanation of the role) and 
 +    * the location in the Java source code that should be highlighted.
 +The first thing to do is to include the following declaration into your file: 
 +<code >
 +:- multifile(analysis_api:​analysis_result/​3). % (Name, Group, Result)
 +Then you implement a clause for the predicate. Two examples are shown below. ​
 +Our [[getting_started#​load example projects|tutorial project]] contains several more examples. ​
 +==== Example: Analysis Returning Individual Results ====
 +The System.out.println detector implemented in the sysout_call/​6 predicate finds //​individual//​ results. This is indicated by the anonymous variable "​_"​ in the second argument of the related clause for //​analysis_result/​3//:​
 +<code 1 >
 +analysis_api:​analysis_result('​sysout_call',​ _, Result) :​-  ​
 +    % Call the System.out.println detector that you implemented:​
 +    sysout_call(CallId,​ _, _, _, _, _) ,
 +    ​
 +    % Create a description
 +    Description = 'Call to System.out.println',​
 +    ​
 +    % Wrap everything into a result term for the GUI: 
 +    make_result_term(sysout_call(CallId),​ Description,​ Result).
 +Note also that the functor of the first argument in the call to make make_result_term/​3 can be anything, it does not need to be
 +the predicate name. In our example, the decision to use the predicate name (compare lines 3 and 9) was a matter of personal taste.
 +See also -> [[#​Generating a Result Term]].
 +==== Example: Analysis Returning Multiple Results ====
 +The Singleton Pattern Detection analysis from our Tutorial project ((New -> Example -> JTransformer Example Projects -> JTransformer Tutorial - Prolog Files)) finds //groups of related results//. Each occurrence of a singleton pattern consists of three elements: ​
 +  * a class, ​
 +  * a getInstance() method in that class and 
 +  * a field of that class that stores the unique instance of the class. ​
 +Each element is represented by one result term.
 +The terms are returned to the calling site (the GUI of JT) one by one, via backtracking. ​
 +To tell the GUI that all result that are related to the same class belong together ​
 +the predicate uses the group identifier //​singleton(Class)//​ in the second argument.
 +So the GUI knows that is should present elements that share this identifier together, ​
 +as parts of one result for the //Singleton Pattern Detection// analysis.
 +<Code linenums:​1>​
 +analysis_api:​analysis_result('​mine_singleton',​ singleton(Class),​ Result) :-
 +    % Call the Singleton Pattern detector predicate:
 +     ​classMethodReturnsOwnInstance(Class,​ Method, Field),
 +    % Wrap each element into a result term for the GUI, indicating which 
 +    % element plays which role in the detected pattern occurrence.
 +    % The disjunction forces returning the results one by one, via backtracking: ​
 +    ( make_result_term(class(Class), ​
 +                            'This is a singleton', ​
 +                            Result)
 +    ; make_result_term(getInstance(Method), ​
 +                            'This is the getInstance method of a singleton', ​
 +                            Result)
 +    ; make_result_term(instance_field(Field), ​
 +                            'This is the instance field of a singleton', ​
 +                             ​Result)
 +    ).
 +See also -> [[#​Generating a Result Term]].
 +==== Example: Description refers to dynamically computed values ====
 +Sometimes a generic description in your marker is not enough and you want to add dynamically computed values (e.g. names of referenced elements, results of metrics ...). For the "Depth of Inheritance (DOI)" metric from our Tutorial project ((New -> Example -> JTransformer Example Projects -> JTransformer Tutorial - Prolog Files)) it is helpful to add the computed value to the marker.
 +<code 1 >
 +analysis_api:​analysis_result('​Stinky_DOI',​ _, Result) :​-  ​
 +    % Call the DOI analysis predicate that you implemented:​
 +    stinky_doi(DOI,​ Id, _), 
 +    ​
 +    % Create a description that refers to the dynamically computed DOI value: ​
 +    format(atom(Description), ​ 'The Depth of Inheritance of this class is ~w', [DOI]),
 +    ​
 +    % Wrap everything into a result term for the GUI: 
 +    make_result_term(stinky_doi(Id),​ Description,​ Result).
 +Note the call to format/3 in line 6 that creates the description dynamically,​ depending on the value of the DOI variable.
 +There is also a way to create the description in the make_result_term call. Just delete line 6 and replace line 9 by:
 +    make_result_term(stinky_doi(Id),​ 'The Depth of Inheritance of this class is ~w'​-[DOI],​ Result).
 +==== Generating a Result Term ====
 +The predicate //​make_result_term/​3//​ is used to generate a term describing a result. ​
 +It has three arguments. The first two are required input, the third is bound to the generated term:
 +  * **RoleTerm** is a term with the following properties:
 +    * The functor is the name of the //role// played by this result.
 +    * The first argument is the //ID// of a PEF returned as a result by your analysis predicate. ​
 +    * It may also have further arguments.
 +  * **Description** is a description of this result.
 +  * **Result** is the term representing this result for the JT GUI.
 +The predicate ''​make_result_term(RoleTerm,​ Description,​ Result)''​ is predefined. To use it you have to import it:
 +<code >
 +:- use_module(jt_analysis(make_result_terms),​ [
 +    make_result_term/​3 % (RoleTerm, Description,​ Result)
research/jtransformer/tutorial/analysis_cc.txt · Last modified: 2018/05/09 01:59 (external edit)

SEWiki, © 2019