The Java Developer's Guide to EclipseThe Java Developer's Guide to Eclipse

In Chapter 27, Extending the Java Development Tools, 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 example demonstrates how you can implement such extensions.

Running the Example

To run the example, import the project com.ibm.jdg2e.jdt; then launch the runtime instance of Eclipse (Run > Run As > Eclipse Application).

  1. Analyzing Java source code using abstract syntax trees (ASTs) and ASTVisitor.

    Add this example's actions to your run-time Workbench by selecting Window > Customize Perspective... > Commands > JDG2E: JDT Actions. Then select JDG2E > Run Hello JDT AST. The output will be displayed to in the Console view of the development environment (not the runtime instance). This simple menu choice displays the structure of an AST. The ASTs are created from a hardcoded string representing a simple Java program.

    Hello AST

    For a more sophisticated display of ASTs, the org.eclipse.jdt.astview plug-in is included on this CD-ROM for your convenience in the plug-in_development\eclipse_tools directory. Install it by copying it to Eclipse's plugins directory and restarting with the -clean command line option (one time only). If you want to examine the source, import it into your workspace, but note it does have some deprecation warnings because it is a pre-version 3.0 plug-in.

    AST view

    Open it by selecting Window > Show View > Other... > Java > ASTView. Open a Java file and then select Show AST of active editor from the context menu of ASTView.

    The second menu choice, JDG2E > Run Hello JDT Scanner, shows the terminal symbol names returned for the tokens of a line of Java source code, similar to Figure 27.4, Tokens Returned by IScanner.

  2. Extending the JDT user interface by adding a new view.

    The Java Metrics view shows the number of methods, fields, and literals within the selected .java source file. Select Window > Show View > Java > JDG2E: Java Metrics to open, then select or open a Java source file.

    Java Metrics view

    The view automatically updates when modifications are saved or new methods / fields are added.

  3. Extending the JDT user interface by adding new actions to the Java editor.

    The example contributes 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.

    Add trace statements choice

    A similar menu choice is available for one or more selected methods in views like the Package Explorer.

    Add trace statement to method(s) choice

    Open a Java source file and select Source > JDG2E: Add Trace Statements from the editor's context menu, from the editor toolbar (), or the Source > JDG2E: Add Trace Statement choice of one or more selected methods shown in the Package Explorer, Outline view, or Hierarchy view.

  4. Extending the JDT user interface by adding new actions to a Java element.

    The example contributes a new JDG2E: Modifiers menu cascade for 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. These changes are recognized without opening an editor.

    Change modifiers choice

    Open a Java source file and select the JDG2E: Modifiers cascaded menu choice from method(s) or field(s) to modify the corresponding keyword: Default (package), public, protected, private, or final.

  5. How to extend the JDT user interface by adding new actions to a Java view. The "smart expand" button Smart expand of the Package Explorer is the converse of the standard collapse all button; that is, it shows you more about a Java project by expanding all its contained packages in a single click.

    Smart expand

    Select one or more project(s) or JAR file(s), and then the expand all button.

Roadmap of the Example

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

Hello AST

This part of the example 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 output: 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 a simple "Hello, World" Java source.

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 keep it simple.

Class (All) Description
JavaMetrics Encapsulates the Java metrics for a given ICompilationUnit. The Java Metrics view contributes 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 example contains a fair amount of code that you have already seen in prior examples 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 example contributes a new editor menu choice that adds trace statements to each method in a Java source file or a trace statement to one or more selected methods. 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 three classes, but this example introduces the notion of a compilation unit's working copy, and how to effect changes with its associated buffer.

Class (All) Description
AddTraceStatementsAction (abstract), AddTraceStatementsEditorAction, and AddTraceStatementToMemberAction Using the JavaMethodsCollector to get the method name and parameters of the editor's compilation unit, the AddTraceStatementsEditorAction inserts trace statements based on them into the editor's working copy (an implementor of ICompilationUnit). The implementation demonstrates two ways of calculating the necessary source code modification. The first calculates the new source string directly; the second uses an AST rewriter, which calculates the necessary source code modifications corresponding to changes in the AST.

For the convenience of adding trace statements to only selected methods, the AddTraceStatementToMemberAction class adds an extension to implementors of IMethod.

JavaMethodsCollector Similar to our prior use of JavaMetricsAccumulator, this is an inner class of AddTraceStatementsAction 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 AddTraceStatementsEditorAction 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.

Change IMember Modifiers and Smart Expand

This part of the example demonstrates object contributions to IMember, how to use IScanner to perform fine-grain parsing, and how to use ASTRewrite to calculate source code modifications based on AST manipulations. The "smart expand" button demonstrates how to contribute to a JDT view, the Package Explorer.

Note: These classes are located in the com.ibm.jdg2e.jdt.extras package.

Class (All) Description
AbstractChangeMemberModifierAction This Action extension is responsible for adding/removing IMember modifiers. Like the AddTraceStatementsAction, the implementation includes two ways of accomplishing the same modification. One subclass, MakeIMemberPrivateAction, demonstrates the use of ASTRewrite.

The other MakeIMemberXxxAction subclasses rely on direct source manipulations methods defined in their superclass, AbstractChangeMemberModifierAction. These subclasses are fairly trivial, since they 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 AbstractChangeMemberModifierAction, this action sets the IMember(s) modifiers to default (package).
MakeIMemberPrivateAction (*) Subclass of AbstractChangeMemberModifierAction, this action uses an ASTRewrite to set the IMember modifier to private.
MakeIMemberProtectedAction Subclass of AbstractChangeMemberModifierAction, this action sets the IMember(s) modifiers to protected.
MakeIMemberPublicAction Subclass of AbstractChangeMemberModifierAction, this action sets the IMember(s) modifiers to public.
ToggleIMemberFinalAction Subclass of AbstractChangeMemberModifierAction, this action toggles the IMember(s) final modifiers.
SmartPackageExplorerExpandAction Interacts with the Package Explorer, an implementor of IPackagesViewPart.

© Copyright International Business Machines Corporation, 2003, 2004, 2006. All Rights Reserved.
Code or samples provided herein are provided without warranty of any kind.