Eclipse icon

In the Extending the Java Development Tools lecture you learned how the JDT works and how it builds upon the foundation of the Eclipse Platform. Most importantly, you learned how to reuse its framework and extend its user interface with your specific productivity enhancements. The solution presents several practical examples that demonstrate how you can implement such extensions.

  1. How to analyze Java source code using ASTs and ASTVisitor. This simple Hello AST displays the structure of an AST. The ASTs are created from a hardcoded string representing a simple Java program and a user-provided Java source file.

  2. How to extend the JDT user interface by adding a new view, specifically a Java Metrics view that shows the number of methods, fields, and literals within the selected .java source file. The view automatically updates when modifications are saved or new methods / fields are added.


  3. How to extend the JDT user interface by adding new actions to the Java editor. The solution creates a new Add Trace Statements menu choice and toolbar button to analyze the source and insert trace statements that output the name and parameters of each method.


  4. How to extend the JDT user interface by adding new actions to a Java element. Specifically, the solution creates a new Modifiers menu choice for the Java fields and methods, allowing the user to set them to public, default, protected, private, or final, directly from the Package Explorer, Outline view or Hierarchy view.

Running the Solution

To run the example, launch the run-time instance of Eclipse (Run > Run As > Run-time Workbench).

  1. Hello AST

    Select Soln: JDT Exercise > Run Hello AST. The output will be displayed to in the Console view of the development environment (not the run-time instance). After the initial output of the "Hello, World" AST is shown in the Console, it will then prompt for a Java source file in the Console. Look for the message "Enter a fully qualified Java filespec:" and enter a Java source file. For example:

    C:\eclipse2.0\eclipse\workspace\com.ibm.lab.soln.jdt\src-extension\com\ibm\lab\soln\jdt\HelloWorld.java

    Don't choose a very large Java source file, the output will be very voluminous.

  2. Java Metrics view

    Select Window > Show View > Java > Soln: Java Metrics to open, then select or open a Java source file. The metrics will update as you modify the source file.

  3. Add Trace Statements

    Open a Java source file and select Soln: Add Trace Statements from the editor's context menu, or from the editor toolbar ().

  4. Change IMember Modifiers

    Open a Java source file and select the Soln: Modifiers cascaded menu choice from method(s) or field(s) shown in the Package Explorer, Outline view, or Hierarchy view; choose one of the menu choices to modify the corresponding keyword: public, default, protected, private, or final.

Roadmap of the Solution

As described above, this solution is partitioned into three parts, each covering a different part of the JDT and with increasing levels of complexity.

Hello AST

This part of the solution will print the basic structure of a given AST to System.out. The idea is to get a quick tour of the ASTVisitor class and see how it helps you easily analyze Java code. As a bonus, this class is both instructive and helpful when debugging more complex ASTs.

As the name "Hello AST" suggests, this code will be primitive in its choice of input and output: System.in and System.out. This demonstrates the fact that the JDT model in the org.eclipse.jdt.core package, which defines the various Java elements, has no dependency on the JDT user interface package org.eclipse.jdt.ui.

Class (All) Description
ASTNode2StringVisitor This ASTVisitor subclass is responsible for processing instances of the Abstract Syntax Tree (AST), all subtypes of ASTNode. In this particular case, we want to visit all nodes, including their children, so it overrides the preVisit(ASTNode) method and prints it to System.out.
HelloASTAction A contributed action to invoke the ASTNode2StringVisitor and display the content of an AST for two cases:
  • A simple "Hello, World" Java source
  • An arbitrary .java source file provided by the user.

Java Metrics view

This view displays code metrics for the selected .java source file (an instance of ICompilationUnit). The Java Metrics view includes the number of methods, defined fields, and string literals. We could certainly add more metrics (e.g., hierarchy depth, number of imports, etc.), but the focus is on integrating with the JDT user interface and better familiarizing yourself with ASTs, so let's keeps it simple.

Class (All) Description
JavaMetrics Encapsulates the Java metrics for a given ICompilationUnit. The Java Metrics view creates a new JavaMetrics instance as its model when it opens.
JavaMetricsAccumulator An inner class of JavaMetrics, this ASTVisitor subclass helps drive the metrics collection activity.
IJavaMetricsListener Defines the interface between a JavaMetrics instance and those, like JavaMetricsView, who wish to be notified of its state changes
JavaMetricsView View that displays the results of the JavaMetrics instance in simple text format. Listens for changes in its model and updates its display appropriately. Also listens for changes in the Workbench selection in order to set its model's ICompilationUnit.

You'll find that this solution contains a fair amount of code that you have already seen in prior solutions in one form or another. So the code commentary will focus on how to integrate with the JDT model with the help of an AST to produce a realistic and useful view.

Add Trace Statements

Reusing the AST techniques shown in the prior two sections, this part of the solution contributes a new editor menu choice that adds trace statements to each method in a Java source file. The new concepts in this section are principally the workings of the Java editor itself, especially the "working copy" that all JDT editors use to stage modifications before committing them to the in-memory Java model.

There isn't much code and only two classes, but this solution introduces the notion of a compilation unit's working copy, and how to effect changes with its associated buffer.

Class (All) Description
AddTraceStatementsEditorActionDelegate Using the JavaMethodsCollector to get the method name and parameters of the editor's compilation unit, this action inserts trace statements based on them into the editor's working copy (a subclass of CompilationUnit), specifically by modifying its buffer content (an instance of IBuffer). The working copy's buffer content is what is displayed in an editor.
JavaMethodsCollector Similar to our prior use of JavaMetricsAccumulator, this is an inner class of AddTraceStatementsEditorActionDelegate that defines an operation against an AST. It collects the compilation unit's method declarations (instances of MethodDeclaration, a subclass of ASTNode) that will be used to determine where the trace statements should be inserted in the source file and enumerate the parameters.

Note: The editor action, AddTraceStatementsEditorActionDelegate, is added in two contexts for demonstration purposes only. Realistically, you would likely choose one or the other (toolbar or pop-up menu) as the best place to add it. The "additions" location is the default, generally at the end of the toolbar or pop-up menu, and is sufficient for our purposes.

Change IMember Modifiers

This part of the solution demonstrates object contributions to IMember, and how to use IScanner to perform fine-grain parsing.

Note: This solution is located in the com.ibm.lab.soln.jdt.extras package.

Class (All) Description
ChangeIMemberFlagAction This Action extension is responsible for adding/removing IMember modifiers. The other MakeIMemberXxxAction subclasses simply choose which flags must be removed and/or added to produce the desired results. For example, adding a public keyword requires that private or protected be removed, if present. Similarly, changing to default visibility requires that public, protected, or private keywords are removed (since there is no "default" keyword, meaning package-level visibility). By concentrating the mechanics of the substitutions in this class, its subclasses only have to define the "rules" for making the appropriate change.
MakeIMemberDefaultAction Subclass of ChangeIMemberFlagAction, this action sets the IMember(s) modifiers to default.
MakeIMemberPrivateAction Subclass of ChangeIMemberFlagAction, this action sets the IMember(s) modifiers to private.
MakeIMemberProtectedAction Subclass of ChangeIMemberFlagAction, this action sets the IMember(s) modifiers to protected.
MakeIMemberPublicAction Subclass of ChangeIMemberFlagAction, this action sets the IMember(s) modifiers to public.
ToggleIMemberFinalAction Subclass of ChangeIMemberFlagAction, this action toggles the IMember(s) final modifiers.

© Copyright International Business Machines Corporation, 2003.
All rights reserved.