Skip navigation links

Oracle Fusion Middleware Java API Reference for Oracle Extension SDK
11g Release 2 (11.1.2.2.0)

E17493-03


Package javax.ide.model.java.source.tree

The Java AST.

See:
          Description

Interface Summary
AnnotationExpressionT An expression wrapping an annotation.
AnnotationT An annotation (not to be confused with annotation type).
ArrayAccessExpressionT An array access expression.
AssertStatementT An assert statement.
AssignmentExpressionT An expression performing an assignment operation.
BlockElementT Common supertype for elements that may be a child of a code block.
BlockStatementT A statement wrapping a block.
BlockT A code block.
BreakStatementT A break statement.
CatchClauseT A catch clause of a try statement.
ClassBodyT A class body, sometimes called a class block.
ClassInitializerT A static or instance initializer block for a class.
ClassT A type declaration.
CompoundStatementT Common supertype for statements that have children statements.
ConditionalStatementT Common supertype for compound statements having (requiring) a conditional expression.
ContinueStatementT A continue statement.
DereferenceExpressionT Common supertype for expressions performing dereference operations.
DocCommentT A doc comment (short for "documentation comment").
DoStatementT A do statement.
DotExpressionT A expression representing an identifier selector.
ElseClauseT An else clause.
EmptyStatementT An empty statement.
EnumConstantT A field (or enum constant) variable.
ExpressionStatementT An expression statement.
ExpressionT Common supertypes for all expressions.
FieldDeclT A field (or enum constant) declaration.
FieldVariableT A field (or enum constant) variable.
FileT The root of a source file, also called a compilation unit.
FinallyClauseT A finally clause.
FormalParameterListT A formal parameter list.
FormalParameterT A formal parameter, also known as just "parameter".
ForStatementT A for statement.
HasModifiersT Common supertype for elements that may have modifiers.
HasNameT Common supertype for elements have have a NameT.
IdentifierExpressionT An expression representing an unqualified name.
IfStatementT An if statement.
ImportT An import declaration.
InfixExpressionT An expression involving an infix operation (but not an assignment operation).
InterfacesT An interfaces clause of a type declaration.
InvokeExpressionT Common supertype for an expression that invokes a method.
ListExpressionT An expression wrapping a list of expressions.
LiteralExpressionT An expression representing a lexer literal.
LocalVariableDeclT A local variable declaration.
LocalVariableT A local variable, not a parameter.
MemberT Common supertype for elements that may be a member of a type declaration.
MemberVariableT A field (or enum constant) variable.
MethodCallExpressionT An expression performing a method invocation or an explicit constructor invocation.
MethodT A method or constructor declaration.
NameT A name, simple or qualified.
NewArrayExpressionT An expression creating a new array.
NewClassExpressionT An expression creating a new instance of a class.
OperatorExpressionT Common supertype for multi-operand operations.
PackageT A package declaration.
QuestionExpressionT An expression with the ?: operator, formally known as the "conditional operator".
ReturnStatementT A return statement.
SimpleStatementT Common supertype for statements that have no child statement but may optionally have expressions.
StatementLabelT A label on a labeled statement.
StatementT Common supertype of all statements.
SuperclassT A superclass clause of a type declaration.
SwitchLabelT A switch label, default or case.
SwitchStatementT A switch statement.
SynchStatementT A synchronized statement.
ThrowsT A throws clause of a method or constructor declaration.
ThrowStatementT A throw statement.
Tree Base supertype of all AST nodes in the parse tree.
TryStatementT A try statement.
TypeArgumentT A type argument for a type reference.
TypecastExpressionT An expression performing a typecast operation.
TypeExpressionT An expression wrapping a type reference.
TypeParameterT A type parameter declaration.
TypeReferenceT A type reference.
UnaryExpressionT An expression performing a prefix or postfix operation, but not a typecast operation.
VariableDeclT Common supertype for field declarations and local variable declarations.
VariableT Common supertype for field variables (and enum constant variables), local variables, and parameters.
WhileStatementT A while statement.
WrapperExpressionT An expression wrapping another one, either with parentheses or brackets.

 

Class Summary
ClassT.ClassKind An enumeration identifying which kind of type declaration this is.
ExpressionT.ExpressionKind An enumeration identifying which kind of expression this is.
ForStatementT.ForKind In this version, this class is 1.4 compatible.
LiteralExpressionT.LiteralKind In this version, this class is 1.4 compatible.
TreeKind The TreeKind enumeration identifies each individual kind of Tree.
TypeArgumentT.BoundKind In this version, this class is 1.4 compatible.

 

Package javax.ide.model.java.source.tree Description

The Java AST.

General Design

This section identifies the assumptions and design choices underlying the entire API.

Tree decorations: Properties

The Tree framework provides a facility for decorating nodes that should intentionally remind callers of properties in java.lang.System: getProperty(S), setProperty(SO), clearProperty(S). All Tree subtypes allow the caller to store an arbitrary Object value with a specific Tree instance under a String key.

Tree, not a DAG

The source model must strictly be a tree. It may not be a dag (directed-acyclic graph).

The consequence is that no element may have a "parent" relationship to more than one element. Also, element A may not have a "sibling" relationship with element B unless A and B share the same parent.

Consider element C and element P. If P.getChildren().contains(C), then C.getParent().equals(P) must be true.

Furthermore, sibling order is defined by source file location. If sibling C occurs before D in the source representation, then C should occur before D in the sibling list.

No outside side effects

Here, an "outside side effect" means an operation upon another file's contents. The typical example is compilation. Resolving the type of a type declaration's superclass almost always requires loading other classes, usually java.lang.Object. Therefore, the Tree API may not have a method that resolves a type declaration's superclass.

The main reason for this choice is to avoid having Tree method calls block on file I/O.

Cloning trees

A Tree object may not be moved from one FileT to another. That is, a Tree object is tied to a FileT object for its entire lifetime. We do this to prevent the undo problems that arise when a Tree object is unlinked from one FileT and linked to another and then the unlink operation is undone.

In place of a traditional move operation, we provide a cloning facility for Tree objects. A client calls cloneSelf(FileT) on a Tree object to clone its entire subtree into the provided FileT. The cloned subtree is unattached, i.e. has no parent, and the client must then add it to the tree in the desired location.

Write operations

The FileT presents a parsed view into the contents of a source file. Changing the FileT causes the contents of underlying source file to be changed. For example, if a caller adds an ImportT to a FileT's List of import declarations, then, on commit, an import declaration is added to the underlying source file.

Mutating a FileT that is not writable results in an IllegalStateException. A FileT is marked as read-only or writable by its owning TreeManager. Please see javax.ide.model.java.source.write.TreeManager for more detail.

Final Tree subtypes

Here, a "final Tree subtype" refers to a Tree interface with no further public subinterfaces. To illustrate, let's consider method and constructor declarations. According to this design choice, there are two solutions.

If we were to have the two types where ConstructorT extends MethodT, then this would not meet the design choice because then method declarations that are not constructor declarations would not be an instance of a "final Tree subtype".

The benefit is that clients are able to dispatch according to the run-time (and sometimes the compile-time) type of a Tree object via method overloading and instanceof checks.

The downside is two-fold. One, this choice generates that many more types in the API, thus producing clutter. Two, an implementation is required to have a separate implementation for each Tree subtype (in order for instanceof checks to work correctly).

Minimal multiple inheritance

There should be no multiple inheritance except for the following: HasBlockT, HasModifiersT, HasNameT, MemberT, BlockElementT, and VariableT. This produces a very rigid tree structure.

The benefit is that the tree structure becomes highly predictable, predictable enough that the client and implementation gets that extra type checking from the compiler. For example, a ListExpressionT has only ExpressionTs as its children (as do most other ExpressionT subtypes).

One downside is that we get classes like AnnotationExpressionT. An AnnotationExpressionT represents both an AnnotationT and an ExpressionT but is in a position where an ExpressionT is expected (it is an child of a ListExpressionT). The "Final Tree subtype" rule dictates that we can't have a generic Tree instance that is both an AnnotationT and an ExpressionT. The other notable examples are: BlockStatementT and TypeExpressionT.

Another downside is that this rule introduces more nodes than is strictly dictated by the grammar thereby increasing the memory footprint of a Tree representation.

Specific Design

This section identifies the assumptions and design choices underlying specific classes in this API.

TypeArgumentT

Consider the following type reference:

  p.OuterType<T1>.InnerType<T2>

A TypeReferenceT represents the entire type reference. It has a TypeReferenceT for the qualifying type "p.OuterType<T1>", NameT for "InnerType", and a TypeArgumentT for "T2". We cannot use TypeArgumentT for "T2" because then there would be two TypeReferenceT children and the above type reference is indistinguishable from:

  InnerType<p.OuterType<T1>, T2>

Hence, we have more general class TypeArgumentT instead of WildcardTypeT.

InfixExpressionT

Some InfixExpressionT can have multiple ExpressionT operands even though the operator itself is a binary infix operator. In particular, because most traversals are written recursively, long String concatenations (>1000 addends) would cause stack overflows, such as the one found in java.text.Normalizer in one of the 1.4.* releases.

Consider a subtree of 1000 ADD operations. Parsing generates a tree with depth ~1000. One possible solution is to balance (or approximately) balance the generated tree. This approarch is problematic because then the resolved type of ADD operators in one subtree depends on the resolved type of ADD operators in a different subtree which goes against the vein of the rule of this being strictly a tree not a DAG.

Therefore, the solution we've come up with is to have a single ADD Tree with 1000 addends. For consistency, all binary infix operators that are both associative and commutative are treated this way. These include:

  + * && & || | ^

Though this causes a problem when refactoring of "b + c" in the expression "a + b + c + d", the same problem is present in a balanced tree.


Miscellaneous

Code conventions

We ask that all source text should respect the 79-character line width so that lines do not wrap when displayed on an 80-character wide terminal. All Tree subtypes shall be suffixed with "T", short for Tree.
All ExpressionT subtypes shall be suffixed with "ExpressionT".
All StatementT subtypes shall be suffixed with "StatementT" or "ClauseT".
With these conventions, a client can differentiate between different Tree subhierarchies at a glance.

Collections and Lists

The following rules apply wherever Collections and Lists are returned by Tree subclasses.

The Collections and Lists are themselves mutable if and only if the Tree instance(s) they are based on is/are mutable. For example, consider non-null Tree elements C and P. The following two calls are equivalent: C.addSelf(P) and P.getChildren().add(C). Iterators are likewise mutable if the owning Collections or Lists are themselves mutable.

In addition, all methods in the java.util.Collections class should perform correctly. For example, a client should be able to call Collections.sort(file.getImports(), comparator) and expected the file's list of imports to become sorted according to the input comparator.

The same Collection/List instance does not need to be returned each time. That is, for FileT instance f, f.getImports() == f.getImports() does not necessarily have to be true.

Note: Should a guarantee of Collection/List equality be made? Consider file1.getImports().equals(file2.getImports()) for different FileT instances, file1 and file2. If file1 and file2 have different import names, then equals(O) should clearly return false. But, if they have equivalent import names, should equals(O) return true? How about f.getImports().equals(f.getImports())?

Dummy (synthetic) instances

Certain constructs must always be present in the Tree, even if there is no matching source representations. Consider, for example, the interfaces declaration of a type declaration. It is permissible to omit the interfaces declaration (implicitly "java.lang.Object"). ClassT.getInterfacesClause() must always return a non-null InterfacesT object. If no interfaces are declared in the source file, then a synthetic one should be generated and returned by ClassT.getInterfacesClause(). This synthetic InterfacesT is mutable if and only if the owning ClassT is mutable. Adding a TypeReferenceT to this InterfacesT element should automatically "promote" the InterfacesT element to be a real element instead of just a synthetic one.

No guarantee of equality is made of these synthetic elements. If there is no interfaces declaration and a client calls ClassT.getInterfacesClause() twice (receiving instances A and B), then A.equals(B) does not necessarily have to be true. However, A.getParent().equals(B.getParent()) must be true.

Note: Consider parent P with a synthetic child C. Clearly, C.getParent().equals(P) must be true. However, should C be considered to be a part of P's children list? That is, should P.getChildren().contains(C) be true? package javax.ide.model.java.source.tree;


Skip navigation links

Oracle Fusion Middleware Java API Reference for Oracle Extension SDK
11g Release 2 (11.1.2.2.0)

E17493-03


Copyright © 1997, 2012, Oracle. All rights reserved.