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_old:jt_analysis_new [2013/12/04 14:01]
Günter Kniesel
research:jtransformer:tutorial_old:jt_analysis_new [2018/05/09 01:59] (current)
Line 1: Line 1:
 +====== Adding Analyses and Transformeations to the JT GUI ======
 +Once you have written a predicate (e.g. the [[stepbystep#​example_--_design_pattern_mining|Singleton Pattern 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,​ QuickFix) // 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]].
 +  * **QuickFixAvailable** is a boolean value. It should be //true// if this analysis finds some kind of problem in Java code and if there is a possible fix for the problem. Otherwise the value should be //false//.
 +The following listing shows the definition of the //Depth of inheritance//​ analysis from our Tutorial project ((New -> Example -> JTransformer Example Projects -> JTransformer Tutorial - Prolog Files)).
 +% The predicate analysis_definition/​6 logically belongs to the  ​
 +% analysis_api module but clauses can be defined in many files:  ​
 +:- multifile(analysis_api:​analysis_definition/​6).  ​
 +% The clause defining the Stinky_DOI analysis:
 +     '​Stinky_DOI', ​                     % Name
 +     ​onSave, ​                           % Trigger
 +     ​warning, ​                          % Severity
 +     '​Metrics', ​                        % Category
 +     '​Depth of Inheritance is too big', % Description
 +     ​false ​                             % QuickfixAvailable
 +===== 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 [[stepbystep#​jtransformer_tutorial_project|tutorial project]] contains several more examples. ​
 +==== Example: Analysis Returning Individual Results ====
 +The Depth of Inheritance (DOI) analysis implemented in the stinky_doi/​3 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('​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 that the call to format/3 in line 6 is only needed because the Description is created dynamically,​ depending on the value of the DOI variable. A statically known value could be passed directly as the Description argument of the call in line 9.
 +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 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]].
 +==== 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)
 +===== Declaring Transformations for Analysis Results =====
 +Transformations of program elements returned as analysis results are declared using the multifile predicate //​transformation_api:​transformation/​5//​. Its arguments are:
 +  * **Group** is a Group term returned from an analysis (see -> [[#wrapping analysis results for the gui]]).
 +  * **Role** is a Role term returned from an analysis (see -> [[#​generating a result term]]).
 +  * **CTHead** is the head of a CT that implements this transformation. It may also be a list of CT heads that should be executed sequentially.
 +  * **Description** is a text shown in the GUI when suggesting the transformation.
 +  * **Options** is a list. Possible options are:
 +    * //​preview//:​ Show a preview even when applying this transformation to just one result.
 +    * //global//: Apply this transformation to all results that play the same role.
 +This predicate is called by JTransformer with the mode (+, +, -, -, -), i.e. //Group// and //​RoleTerm//​ are bound.
 +The following listing shows the transformation defined for the "​Singleton Constructor not private"​ analysis from our ++Tutorial project|. You find it in JTransformer via the menues: New -> Example -> JTransformer Example Projects -> JTransformer Tutorial - Prolog Files++.
 +<Code linenums:​1>​
 +:- multifile(transformation_api:​transformation/​5). ​    % Don't forget the declaration!
 +    _,                                                 % Individual result (No group)
 +    singleton_constructor_not_private(Id), ​            % RoleTerm
 +    make_constructor_private(Id), ​                     % CTHead
 +    '​Change visibilty of constructor to private', ​     % Description
 +    [preview]). ​                                       % Option: Show Preview
 +==== Presentation of Declared Transformations ====
 +The declared transformations for a particular analysis result are shown in the Java editor. The screenshot below shows the transformations for a result of the "​Singleton Constructor not private"​ analysis. The first two offered transformations result from the transformation definition shown above. ​
 +  * The first one simply executes the specified CT and applies the changes to the Java source code without further user interaction. ​
 +    This suggestion is always generated, independent of the options set in the transformation declaration. ​
 +  * The second one opens a wizard that shows the changes of the Java source code before applying them.
 +    This suggestion is generated if the '​preview'​ or the '​global'​ option is set in the transformation declaration (for analyses that apply globally, a preview is always generated). ​
 +The last four transformations are always offered, for each result:
 +  * The //accept// and //reject// suggestions can be used to assess the analysis results as correct or incorrect. They trigger transformations that add a special comment to the respective code element.
 +  * The //​suppress//​ suggestion deactivates reporting this particular result. This also boils down to adding a special comment to the respective code element.
 +  * The //​deactivate//​ suggestion deactivates running this analysis. It is equivalent to deactivating the analysis by unchecking it in the [[control center|Control Center]].
research/jtransformer/tutorial_old/jt_analysis_new.txt · Last modified: 2018/05/09 01:59 (external edit)

SEWiki, © 2019