Jump to: navigation, search

Recommenders/Attic/Templates

Introduction to Templates Completion

The Code Recommenders Template Completion plug-in aims to provide automatically generated Eclipse templates, extracted from a database of mined API usage patterns and fitted to the context of the completion request. This page contains in-detail information about the templates completion plug-in and how it can be used, maintained and extended by developers.

For the rest of this introduction we will present a short scenario which helps the developer to understand the major tasks of the plug-in and possible obstacles in generating templates. In the following we will present the general #Architecture of the plug-in by giving an overview of its components in #Components Overview and how they interact in #General Workflow. We will further explain the most #Important Concepts which further helps understanding the system and are vital to know for working on the plug-in.

Functionality

Eclipse has a built-in templates engine which allows the user to define frequently used code snippets and to insert them with just a few clicks. For a better adaption several variables can be included in order to make templates more dynamic and corresponding to the context in where they are inserted. An overview is given by the Eclipse help pages. However, as the following example for creating an SWT button object illustrates, designing templates can be difficult and time-consuming.

Default Eclipse SWT template for a new button
${buttonType:newType(org.eclipse.swt.widgets.Button)} ${button:newName(org.eclipse.swt.widgets.Button)}= new ${buttonType}(${parent:var(org.eclipse.swt.widgets.Composite)}, ${style:link(SWT.PUSH, SWT.TOGGLE, SWT.RADIO, SWT.CHECK, SWT.FLAT)});
${button}.setLayoutData(new ${type:newType(org.eclipse.swt.layout.GridData)}(SWT.${horizontal:link(BEGINNING, CENTER, END, FILL)}, SWT.${vertical:link(CENTER, TOP, BOTTOM, FILL)}, ${hex:link(false, true)}, ${vex:link(false, true)}));
${button}.setText(${word_selection}${});
${imp:import(org.eclipse.swt.SWT)}${cursor}

Therefore the Eclipse Recommenders Templates plug-in aims to automatically create such templates for (a) providing useful shortcuts to frequently written code and (b) to populate common practices which help new users to learn how frameworks are used. However, much from the context of the completion request can influence the decision about how to (further) progress with an object, which is why presenting appropriate and well-adaptive templates is non-trivial.

The following illustrates several obstacles in one example. First, the declaration of b is not within the direct scope of the completion request, it's defined outside the method. Second, there have already been methods called, so we shouldn't, for example, include a new constructor (it's not common for this scenario). Third, "b" has not been qualified with a dot ("b.") when triggering the request, which usually is required to identify the variable.

Example scenario for a templates completion request
private Button b;
 
private void doSomething(){
   b = new Button(null, 0);
   b.setText("...");
   b<^Space>
}

Architecture

Dependencies between components

This section contains a general overview about the whole plug-in architecture and how its components interact. First, a diagram describing the structure and the dependencies between the components is displayed on the right-hand side. Second, each component of the Plugin is given along with a short description of its role. Finally, the default sequence of components interaction for generating templates is displayed.

Components Overview

The following describes all classes introduced by this plug-in. Please note that it also depends on several components of the Recommenders framework, which won't be described, due to it's complexity.

Table of Plugin components and short description of their roles.
Package / Class Description
.templates Main components of the Plugins, control interaction.
CompletionProposalsBuilder Transforms PatternRecommendations into IJavaCompletionProposals which are applied on the editor content when the propoals is selected from the completion proposals menu.
CompletionTargetVariableBuilder Extracts the CompletionTargetVariable from an IIntelligentCompletionContext.
PatternRecommender Computes PatternRecommendations from the CallsModelStore.
TemplatesCompletionModule Prepares the Plugin by injecting dependencies.
TemplatesCompletionProposalComputer Controls the process of template recommendations.
.templates.code Components for transforming our information into Eclipse templates code.
CodeBuilder Builds Eclipse templates code from a list of method calls on a given variable name.
MethodCallFormatter Generates the String representation of a MethodCall.
MethodFormatter Generates the String representation of an IMethod.
.templates.types Encapsulates certain information. Only used by this Plugin.
CompletionTargetVariable Models the variable on which the completion was triggered.
JavaTemplateProposal Extends the TemplateProposal to customize the style of the template's entry in the completion popup.
MethodCall Models a call of a certain method on a given variable name.
PatternRecommendation Encapsulates one recommendation received from the models store.

General Workflow

The following sequence diagram illustrates the path from receiving a completion request to delivering appropriate template proposals. The TemplatesCompletionProposalComputer controls the sequence by delegating tasks, so it first requests a #Completion Target Variable holding information about the context, as described later. Second, it passes the target variable to the #Pattern Recommender, which is connected to the Code Recommenders' pattern store and selects the best patterns for the given variable. Third, a collection of patterns (mainly a list of method calls) is given to CompletionProposalsBuilder which transforms the patterns into Eclipse template codes and combines all relevant information about the template in a JavaTemplateProposal (which can be processed by Eclipse).

The task of transforming patterns (i.e. method call information) into template code is delegated to the #Code Builder. It combines the generation of the "environment" (e.g. "Text text = button." and the method call code (e.g. "getText();"). More information about this process is given later.

Regular computation of templates

Important Concepts

Since the following concepts are especially crucial to the design of the templates completion plug-in, we will have a further look at them.

Completion Target Variable

Regular information about the context from where the completion was requested is, for example, given by Eclipse's ContentAssistInvocationContext. The Code Recommenders' IntelligentCompletionContext provides additional information, e.g. obtained from own AST parsers. However, not all data required for context-sensitive templates are directly available, which is why we further create an encapsulation of data related to the variable on which the request was called (or which shall be created in case of a constructor call). The following listing gives all relevant attributes of a "Completion Target Variable" and required decisions.

  • Variable name: Given when the variable already exists, otherwise has to be extracted from the editor text (might also be an implicit "this").
  • Variable type: In case of an existing variable a fully qualified class (including package), might also be the class name only if the type is not imported yet (in case of a constructor call).
  • Position in text: Not always the position of the cursor, e.g. for "Button b<^Space>" also "Button" has to be replaced by the new code.
  • Needs Constructor: If the template has to contain a constructor, e.g. "Button b" obviously can't be extended to "Button b.getText()".
  • Receiver calls: Which method calls related to the variable already occurred in the user's code.

Pattern Recommender

The Recommenders project is based on data which has been mined from a large amount of source code. This information is provided by modules like the "CallsModelStore" which organize the loading of relevant models, where each model represents a specific java class. For those plug-ins that work on method calls (like the Templates plug-in), the models contain information about which of the class's methods were invoked by which other methods and how many times this was observed. Additionally, and of particular interest to the Templates plug-in, not only single methods, but also groups of the class's methods that appeared together in a specific context, are contained. Therefore, to provide relevant code templates, we just have to obtain the model we are interested in and extract the most common, i.e. most relevant groups of method calls.

1. Up to this situation it might not be clear which particular class the user is interested in. He might, for example, have started with "Button b<^Space>" without importing a specific class, so the package is unknown and the Button class could refer to several different implementations. What the Templates plug-in does is to query for a list of all models that belong to a class named Button, and as a result it might finally present templates for different classes to the user. Currently, it has not been observed yet, that the amount of matching models would be to high to display them all, but a future step could be to just consider the most frequently used model.

2. The Templates plug-in does not directly interfere with the model files; as their information is required by several components of the Recommenders project, accessing and filtering is generalized in methods that are out of our scope. Therefore the "network" has to be told for which scenario to present relevant patterns. This also includes the methods of the class that have already been invoked in the user's code: If they are contained in a pattern, they should be filtered out to not present them again, and at the same time this pattern gets more likely, even though the absolute number of occurrences might be higher for other patterns. Furthermore, the context of the completion request might explicitly require or forbid a constructor to be contained in the template.

3. Finally, the identifiers of the relevant patterns, along with their frequency scores, are returned by the model network. At the current version the 5 highest scoring patterns are selected and the associated method calls are finally fetched using the identifiers. Additionally, some further filtering of patterns and methods is done, but this is much more specific and best directly observed from the code of the pattern recommender.

Code Builder

As already stated at the beginning of this documentation, the Eclipse template system is quite powerful in allowing customization. For example, "${btn:newName(org.eclipse.swt.widgets.Button)}" will assign a new name that is extracted from the class name (e.g. "button2" if there already exists a "button" in the user's code), and replace every occurrence of the placeholder "${btn}" within the template. As another example, "${hex:link(false, true)" will write "hex" at the position where some value has to inserted by the user after the template was applied and furthermore present "true" and "false" in a dropdown-menu for this position to give the user a shortcut. In order to generate such code, the obtained method calls have to be analysed for what they represent, and then be transformed into Eclipse template code. For the sake of division of work, three components work are concerned with this task:

1. The CodeBuilder takes a list of method calls and delegates the transformation task for each method and then joins the code (e.g. handles line-separators and appends the "${cursor}" directive) and returns it to the final output.

2. The MethodCallFormatter cares for the "surrounding" of the method call and delegates the request for a formatted method. The surrounding usually just contains the identifier of the variable on which the method is invoked, e.g. the "b." in "b.getText();". But also more complex scenarios exist, for example, we store every returned value in a template, so the final outcome would be "Text text = b.getText();". This means we have to include the fully qualified name of the Text class (so it can automatically be imported) and also tell Eclipse to generate a proper new variable name (which would be "text" in this case). Also the placeholders are set by this component, i.e. if the template contains a constructor and the user-desired variable name is unknown, we have to use the "${btn:newName(org.eclipse.swt.widgets.Button)}"-style and put a "${btn}" in front of the ".getText()" method call.

3. The decisions made when writing the method call itself, can be complex as well. The two biggest issues are which information is provided along with a parameter (like in the "${hex:link(false, true)" example, but also the type could of the parameter could be declared instead) and how to name the parameter. When the source code of the method call is available in the class path, Eclipse is able to resolve this name. However, when it is not available, the variable will be named "arg0" where 0 indicates that it is the first argument to that method. The problem is, that if a template contains several "arg0"'s because it has several methods with unresolvable parameter names, it - for some reasons - is considered as invalid and not displayed in the completion proposals list by Eclipse. To solve this issue, we therefore use an internal counter on "arg"'s, so that each parameter is given a unique name, using subsequent enumeration.