Welcome Guest!
Create Account | Login
Locator+ Code:

Search:
FTPOnline
Channels Conferences Resources Hot Topics Partner Sites Magazines About FTP RSS 2.0 Feed

Free Subscription to Java Pro


JSIS and Source Code Dependencies (Continued)

Operating on a CompilationUnit is done through the ParserHandler, which is a process quite similar to the SAX event model. ParserHandler requires you to implement two methods: startElement() and endElement(). We'll visit how you do this later in our implementation. You can create a Parser object and pass it your ParserHandler as the only constructor argument and call the parse() method with a reference to a CompilationUnit. The parse() method takes an optional second argument that is set to 'true' if you want to process all tokens and 'false' if you want to skip comments, keywords, and punctuation.

ADVERTISEMENT

Nodes and Leaves
You can also treat parse trees as more DOM-like structures if you want, operating on a set of nested Element instances. Classes like CompilationUnit, Declaration, Expression, Name, Statement, and Token all extend the Element class. Like DOM, you can use the children() method to get child objects, which are returned as an array of Element objects. The CompilationUnit class provides convenient methods for accessing specific sections of the class, such as the packageDeclaration(), importDeclarations(), and typeDeclarations() methods. JSIS uses Element objects to represent parts of a Java program. You may find the separation of node and leaf Elements confusing at first. For example, the Token subclass represents terminal leaf nodes, but the Expression subclass may represent literals, identifiers, or operators, which are terminal symbols, while method or constructor invocations and mathematical expressions are not. There are five types of Element objects, including the CompilationUnit, which is effectively the root of any class. A Token instance may represent a comment, modifier or other reserved word, or punctuation. A Declaration contains only compound (nonleaf) elements, such as package, import, variable, method, and constructor declarations. An Expression includes keywords like void or this; literals such as boolean, numerical, character, or string values; array initializers; and so on.

A Statement includes control-flow statements like switch, case, while, for, throw, catch, finally, and so on. These are all compound, nonterminal nodes. Name elements are all terminals and allow you to access qualified names, including array, constructor, interface, method, parameter, variable, and other names. You can use the Name class to resolve qualified names, such as String, which gets resolved to java.lang.String. Keep in mind that you need to have the right classes on the classpath for this resolution to work.

One of the more interesting aspects of an Element is the ability to retrieve a Span object that represents a location in the source code file, including the start and stop line number and offset—a powerful mechanism for operating on specific ranges of the source code, depending on the tools you need. Another interesting feature of JSIS is the ability to retrieve preceding, embedded, and trailing comments, relative to a given element. This feature makes it possible to develop tools that are sensitive to certain comments and their position in the source code.

Aside from the Element subclasses, Parser and ParserHandler, a couple of Exception classes, and the Span class, there is also the Package class that contains references to the compilation units in a given package, as well as the ability to navigate the package hierarchy. You can use the static Environment.packages() method to collect all the packages in the current environment, or call the static Environment.packageForName() method to fetch a specific Package object.

If you prefer the containment model to event processing, you can start with a Package object, collect its children, and for each Package collect the CompilationUnit instances available in that package. In each case, you can either get the children as an array or by name. Because each Element instance provides access to its children, you can traverse the parse tree and ask which type of element you are working with. The elementKind() method returns an integer value associated with one of the DECLARATION, EXPRESSION, STATEMENT, NAME, and TOKEN constant declarations in the Element class. Given this information, you can cast the Element to its proper type and access more specific information. The kind() method provides a more granular classification within each of the five elements types.

Back to top

Printer-Friendly Version












Java Pro | Visual Studio Magazine | Windows Server System Magazine
.NET Magazine | Enterprise Architect | XML & Web Services Magazine
VSLive! | Thunder Lizard Events | Discussions | Newsletters | FTP Home