|
Oracle Fusion Middleware Java API Reference for Oracle Extension SDK Reference 11g Release 1 (11.1.1.9.0) E52944-01 |
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
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. |
The Java AST.
This section identifies the assumptions and design choices underlying the entire API.
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.
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.
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.
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.
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.
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).
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.
This section identifies the assumptions and design choices underlying specific classes in this API.
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.
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.
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.
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())
?
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;
|
Oracle Fusion Middleware Java API Reference for Oracle Extension SDK Reference 11g Release 1 (11.1.1.9.0) E52944-01 |
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |