Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2010-04-01 19:56:59 +0000
committerStephan Herrmann2010-04-01 19:56:59 +0000
commit7b7062f3b12bba7ef33116efb94da1f54e069625 (patch)
tree953104b5ab329138aac4d340fb014e321cd658a2 /org.eclipse.jdt.core/dom/org/eclipse
parentb41f944c832b588bb998e321bf7fd9a4e1c62c08 (diff)
downloadorg.eclipse.objectteams-7b7062f3b12bba7ef33116efb94da1f54e069625.tar.gz
org.eclipse.objectteams-7b7062f3b12bba7ef33116efb94da1f54e069625.tar.xz
org.eclipse.objectteams-7b7062f3b12bba7ef33116efb94da1f54e069625.zip
initial commit in accordance with CQ 3784
Diffstat (limited to 'org.eclipse.jdt.core/dom/org/eclipse')
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java3154
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java6318
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java2843
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java2880
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java1252
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java449
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java118
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java148
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java3052
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractMethodMappingDeclaration.java205
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java281
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java181
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java249
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java272
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java417
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java190
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java271
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java320
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java161
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java241
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java262
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java441
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java273
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java184
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java346
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java1049
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java169
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java130
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java282
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java178
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java188
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CallinMappingDeclaration.java523
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CalloutMappingDeclaration.java427
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java264
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java267
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java389
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildListPropertyDescriptor.java98
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildPropertyDescriptor.java113
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java585
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Comment.java129
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java1091
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java1032
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java334
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java252
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java188
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java562
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java2030
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java644
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultValuePairBinding.java50
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java274
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java740
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java117
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java329
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java390
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java335
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java140
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java205
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java313
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccessSpec.java294
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java368
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java361
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardPredicateDeclaration.java199
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IAnnotationBinding.java64
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java340
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java22
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IExtendedModifier.java42
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMemberValuePairBinding.java59
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java334
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodMappingBinding.java60
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java69
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java1041
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java161
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java348
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java446
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java538
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java313
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java263
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java246
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java320
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java276
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LiftingType.java343
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java127
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java160
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java272
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java280
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePairBinding.java208
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Message.java134
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java473
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBindingOperator.java244
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java953
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java399
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingBinding.java290
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingElement.java162
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java317
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java358
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodSpec.java557
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java892
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java119
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeEventHandler.java188
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeFinder.java224
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java99
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java202
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java118
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java223
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java254
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java362
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterMapping.java385
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java273
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java200
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java330
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrecedenceDeclaration.java128
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java348
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java302
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java281
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java285
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java797
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredVariableBinding.java128
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java186
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RoleTypeDeclaration.java1029
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java315
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimplePropertyDescriptor.java83
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java198
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java226
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java636
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Statement.java210
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java345
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StructuralPropertyDescriptor.java143
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java317
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java277
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java397
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java222
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java250
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java266
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java185
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java335
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java400
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java198
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java188
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java201
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java299
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java171
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeAnchor.java199
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java1463
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java1106
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java359
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java199
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java325
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java408
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java196
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java435
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java334
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java437
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java276
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java279
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WithinStatement.java302
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/package.html24
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTNodeCreator.java468
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java717
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ITrackedNodePosition.java43
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java1227
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java440
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java135
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/package.html18
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java2102
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java4363
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java1754
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java595
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java1189
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineCommentEndOffsets.java85
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java59
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ListRewriteEvent.java215
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeInfoStore.java163
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeRewriteEvent.java114
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEvent.java79
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java872
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/SourceModifier.java48
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java238
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TrackedNodePosition.java60
178 files changed, 84307 insertions, 0 deletions
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
new file mode 100644
index 000000000..d834924a5
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -0,0 +1,3154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: AST.java 22567 2009-09-22 16:34:06Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Umbrella owner and abstract syntax tree node factory.
+ * An <code>AST</code> instance serves as the common owner of any number of
+ * AST nodes, and as the factory for creating new AST nodes owned by that
+ * instance.
+ * <p>
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * <code>new<i>TYPE</i></code> factory methods to create new nodes, and the
+ * various <code>set<i>CHILD</i></code> methods
+ * (see {@link org.eclipse.jdt.core.dom.ASTNode ASTNode} and its subclasses)
+ * to connect them together.
+ * </p>
+ * <p>
+ * Each AST node belongs to a unique AST instance, called the owning AST.
+ * The children of an AST node always have the same owner as their parent node.
+ * If a node from one AST is to be added to a different AST, the subtree must
+ * be cloned first to ensures that the added nodes have the correct owning AST.
+ * </p>
+ * <p>
+ * There can be any number of AST nodes owned by a single AST instance that are
+ * unparented. Each of these nodes is the root of a separate little tree of nodes.
+ * The method <code>ASTNode.getRoot()</code> navigates from any node to the root
+ * of the tree that it is contained in. Ordinarily, an AST instance has one main
+ * tree (rooted at a <code>CompilationUnit</code>), with newly-created nodes appearing
+ * as additional roots until they are parented somewhere under the main tree.
+ * One can navigate from any node to its AST instance, but not conversely.
+ * </p>
+ * <p>
+ * The class {@link ASTParser} parses a string
+ * containing a Java source code and returns an abstract syntax tree
+ * for it. The resulting nodes carry source ranges relating the node back to
+ * the original source characters.
+ * </p>
+ * <p>
+ * Compilation units created by <code>ASTParser</code> from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. Here is an example:
+ * <pre>
+ * Document doc = new Document("import java.util.List;\nclass X {}\n");
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);
+ * parser.setSource(doc.get().toCharArray());
+ * CompilationUnit cu = (CompilationUnit) parser.createAST(null);
+ * cu.recordModifications();
+ * AST ast = cu.getAST();
+ * ImportDeclaration id = ast.newImportDeclaration();
+ * id.setName(ast.newName(new String[] {"java", "util", "Set"});
+ * cu.imports().add(id); // add import declaration at end
+ * TextEdit edits = cu.rewrite(document, null);
+ * UndoEdit undo = edits.apply(document);
+ * </pre>
+ * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
+ * an alternative way to describe and serialize changes to a
+ * read-only AST.
+ * </p>
+ * <p>
+ * Clients may create instances of this class using {@link #newAST(int)},
+ * but this class is not intended to be subclassed.
+ * </p>
+ *
+ * @see ASTParser
+ * @see ASTNode
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings("unchecked")
+public final class AST {
+ /**
+ * Constant for indicating the AST API that handles JLS2.
+ * This API is capable of handling all constructs
+ * in the Java language as described in the Java Language
+ * Specification, Second Edition (JLS2).
+ * JLS2 is a superset of all earlier versions of the
+ * Java language, and the JLS2 API can be used to manipulate
+ * programs written in all versions of the Java language
+ * up to and including J2SE 1.4.
+ *
+ * @since 3.0
+ * @deprecated Clients should use the {@link #JLS3} AST API instead.
+ */
+ public static final int JLS2 = 2;
+
+ /**
+ * Internal synonym for {@link #JLS2}. Use to alleviate
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ static final int JLS2_INTERNAL = JLS2;
+
+ /**
+ * Constant for indicating the AST API that handles JLS3.
+ * This API is capable of handling all constructs in the
+ * Java language as described in the Java Language
+ * Specification, Third Edition (JLS3).
+ * JLS3 is a superset of all earlier versions of the
+ * Java language, and the JLS3 API can be used to manipulate
+ * programs written in all versions of the Java language
+ * up to and including J2SE 5 (aka JDK 1.5).
+ *
+ * @since 3.1
+ */
+ public static final int JLS3 = 3;
+
+ /**
+ * The binding resolver for this AST. Initially a binding resolver that
+ * does not resolve names at all.
+ */
+ private BindingResolver resolver = new BindingResolver();
+
+ /**
+ * The event handler for this AST.
+ * Initially an event handler that does not nothing.
+ * @since 3.0
+ */
+ private NodeEventHandler eventHandler = new NodeEventHandler();
+
+ /**
+ * Level of AST API supported by this AST.
+ * @since 3.0
+ */
+ int apiLevel;
+
+ /**
+ * Internal modification count; initially 0; increases monotonically
+ * <b>by one or more</b> as the AST is successively modified.
+ */
+ private long modificationCount = 0;
+
+ /**
+ * Internal original modification count; value is equals to <code>
+ * modificationCount</code> at the end of the parse (<code>ASTParser
+ * </code>). If this ast is not created with a parser then value is 0.
+ * @since 3.0
+ */
+ private long originalModificationCount = 0;
+
+ /**
+ * When disableEvents > 0, events are not reported and
+ * the modification count stays fixed.
+ * <p>
+ * This mechanism is used in lazy initialization of a node
+ * to prevent events from being reported for the modification
+ * of the node as well as for the creation of the missing child.
+ * </p>
+ * @since 3.0
+ */
+ private int disableEvents = 0;
+
+ /**
+ * Internal object unique to the AST instance. Readers must synchronize on
+ * this object when the modifying instance fields.
+ * @since 3.0
+ */
+ private final Object internalASTLock = new Object();
+
+ /**
+ * Java Scanner used to validate preconditions for the creation of specific nodes
+ * like CharacterLiteral, NumberLiteral, StringLiteral or SimpleName.
+ */
+ Scanner scanner;
+
+ /**
+ * Internal ast rewriter used to record ast modification when record mode is enabled.
+ */
+ InternalASTRewrite rewriter;
+
+ /**
+ * Default value of <code>flag<code> when a new node is created.
+ */
+ private int defaultNodeFlag = 0;
+
+ /**
+ * Creates a new Java abstract syntax tree
+ * (AST) following the specified set of API rules.
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @since 3.0
+ */
+ private AST(int level) {
+ if ((level != AST.JLS2)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ this.apiLevel = level;
+ // initialize a scanner
+ this.scanner = new Scanner(
+ true /*comment*/,
+ true /*whitespace*/,
+ false /*nls*/,
+ ClassFileConstants.JDK1_3 /*sourceLevel*/,
+ ClassFileConstants.JDK1_5 /*complianceLevel*/,
+ null/*taskTag*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ }
+
+ /**
+ * Creates a new, empty abstract syntax tree using default options.
+ *
+ * @see JavaCore#getDefaultOptions()
+ * @deprecated Clients should port their code to use the new JLS3 AST API and call
+ * {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+ */
+ public AST() {
+ this(JavaCore.getDefaultOptions());
+ }
+
+ /**
+ * Internal method.
+ * <p>
+ * This method converts the given internal compiler AST for the given source string
+ * into a compilation unit. This method is not intended to be called by clients.
+ * </p>
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @param compilationUnitDeclaration an internal AST node for a compilation unit declaration
+ * @param options compiler options
+ * @param workingCopy the working copy that the AST is created from
+ * @param monitor the progress monitor used to report progress and request cancellation,
+ * or <code>null</code> if none
+ * @param isResolved whether the given compilation unit declaration is resolved
+ * @return the compilation unit node
+ * @since 3.4
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public static CompilationUnit convertCompilationUnit(
+ int level,
+ org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration,
+ Map options,
+ boolean isResolved,
+ org.eclipse.jdt.internal.core.CompilationUnit workingCopy,
+ int reconcileFlags,
+ IProgressMonitor monitor) {
+
+ ASTConverter converter = new ASTConverter(options, isResolved, monitor);
+ AST ast = AST.newAST(level);
+ int savedDefaultNodeFlag = ast.getDefaultNodeFlag();
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ BindingResolver resolver = null;
+ if (isResolved) {
+ resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, workingCopy.owner, new DefaultBindingResolver.BindingTables(), false);
+ ((DefaultBindingResolver) resolver).isRecoveringBindings = (reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0;
+ ast.setFlag(AST.RESOLVED_BINDINGS);
+ } else {
+ resolver = new BindingResolver();
+ }
+ ast.setFlag(reconcileFlags);
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+
+ CompilationUnit unit = converter.convert(compilationUnitDeclaration, workingCopy.getContents());
+ unit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+ unit.setTypeRoot(workingCopy.originalFromClone());
+ ast.setDefaultNodeFlag(savedDefaultNodeFlag);
+ return unit;
+ }
+
+ /**
+ * Internal method.
+ * <p>
+ * This method converts the given internal compiler AST for the given source string
+ * into a compilation unit. This method is not intended to be called by clients.
+ * </p>
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @param compilationUnitDeclaration an internal AST node for a compilation unit declaration
+ * @param source the string of the Java compilation unit
+ * @param options compiler options
+ * @param workingCopy the working copy that the AST is created from
+ * @param monitor the progress monitor used to report progress and request cancellation,
+ * or <code>null</code> if none
+ * @param isResolved whether the given compilation unit declaration is resolved
+ * @return the compilation unit node
+ * @deprecated Use org.eclipse.jdt.core.dom.AST.convertCompilationUnit(int, CompilationUnitDeclaration, Map, boolean, CompilationUnit, int, IProgressMonitor) instead
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public static CompilationUnit convertCompilationUnit(
+ int level,
+ org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration,
+ char[] source,
+ Map options,
+ boolean isResolved,
+ org.eclipse.jdt.internal.core.CompilationUnit workingCopy,
+ int reconcileFlags,
+ IProgressMonitor monitor) {
+ return null;
+ }
+
+ /**
+ * Creates a new, empty abstract syntax tree using the given options.
+ * <p>
+ * Following option keys are significant:
+ * <ul>
+ * <li><code>"org.eclipse.jdt.core.compiler.source"</code> -
+ * indicates source compatibility mode (as per <code>JavaCore</code>);
+ * <code>"1.3"</code> means the source code is as per JDK 1.3;
+ * <code>"1.4"</code> means the source code is as per JDK 1.4
+ * (<code>"assert"</code> is now a keyword);
+ * <code>"1.5"</code> means the source code is as per JDK 1.5
+ * (<code>"enum"</code> is now a keyword);
+ * additional legal values may be added later. </li>
+ * </ul>
+ * Options other than the above are ignored.
+ * </p>
+ *
+ * @param options the table of options (key type: <code>String</code>;
+ * value type: <code>String</code>)
+ * @see JavaCore#getDefaultOptions()
+ * @deprecated Clients should port their code to use the new JLS3 AST API and call
+ * {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+ */
+ public AST(Map options) {
+ this(JLS2);
+ Object sourceLevelOption = options.get(JavaCore.COMPILER_SOURCE);
+ long sourceLevel = ClassFileConstants.JDK1_3;
+ if (JavaCore.VERSION_1_4.equals(sourceLevelOption)) {
+ sourceLevel = ClassFileConstants.JDK1_4;
+ } else if (JavaCore.VERSION_1_5.equals(sourceLevelOption)) {
+ sourceLevel = ClassFileConstants.JDK1_5;
+ }
+ Object complianceLevelOption = options.get(JavaCore.COMPILER_COMPLIANCE);
+ long complianceLevel = ClassFileConstants.JDK1_3;
+ if (JavaCore.VERSION_1_4.equals(complianceLevelOption)) {
+ complianceLevel = ClassFileConstants.JDK1_4;
+ } else if (JavaCore.VERSION_1_5.equals(complianceLevelOption)) {
+ complianceLevel = ClassFileConstants.JDK1_5;
+ }
+ // override scanner if 1.4 or 1.5 asked for
+ this.scanner = new Scanner(
+ true /*comment*/,
+ true /*whitespace*/,
+ false /*nls*/,
+ sourceLevel /*sourceLevel*/,
+ complianceLevel /*complianceLevel*/,
+ null/*taskTag*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ }
+
+ /**
+ * Creates a new Java abstract syntax tree
+ * (AST) following the specified set of API rules.
+ * <p>
+ * Clients should use this method specifing {@link #JLS3} as the
+ * AST level in all cases, even when dealing with JDK 1.3 or 1.4..
+ * </p>
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @return new AST instance following the specified set of API rules.
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the API level is not one of the LEVEL constants</li>
+ * </ul>
+ * @since 3.0
+ */
+ public static AST newAST(int level) {
+ if ((level != AST.JLS2)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ return new AST(level);
+ }
+
+ /**
+ * Returns the modification count for this AST. The modification count
+ * is a non-negative value that increases (by 1 or perhaps by more) as
+ * this AST or its nodes are changed. The initial value is unspecified.
+ * <p>
+ * The following things count as modifying an AST:
+ * <ul>
+ * <li>creating a new node owned by this AST,</li>
+ * <li>adding a child to a node owned by this AST,</li>
+ * <li>removing a child from a node owned by this AST,</li>
+ * <li>setting a non-node attribute of a node owned by this AST.</li>
+ * </ul>
+ * </p>
+ * Operations which do not entail creating or modifying existing nodes
+ * do not increase the modification count.
+ * <p>
+ * N.B. This method may be called several times in the course
+ * of a single client operation. The only promise is that the modification
+ * count increases monotonically as the AST or its nodes change; there is
+ * no promise that a modifying operation increases the count by exactly 1.
+ * </p>
+ *
+ * @return the current value (non-negative) of the modification counter of
+ * this AST
+ */
+ public long modificationCount() {
+ return this.modificationCount;
+ }
+
+ /**
+ * Return the API level supported by this AST.
+ *
+ * @return level the API level; one of the <code>JLS*</code>LEVEL
+ * declared on <code>AST</code>; assume this set is open-ended
+ * @since 3.0
+ */
+ public int apiLevel() {
+ return this.apiLevel;
+ }
+
+ /**
+ * Indicates that this AST is about to be modified.
+ * <p>
+ * The following things count as modifying an AST:
+ * <ul>
+ * <li>creating a new node owned by this AST</li>
+ * <li>adding a child to a node owned by this AST</li>
+ * <li>removing a child from a node owned by this AST</li>
+ * <li>setting a non-node attribute of a node owned by this AST</li>.
+ * </ul>
+ * </p>
+ * <p>
+ * N.B. This method may be called several times in the course
+ * of a single client operation.
+ * </p>
+ */
+ void modifying() {
+ // when this method is called during lazy init, events are disabled
+ // and the modification count will not be increased
+ if (this.disableEvents > 0) {
+ return;
+ }
+ // increase the modification count
+ this.modificationCount++;
+ }
+
+ /**
+ * Disable events.
+ * This method is thread-safe for AST readers.
+ *
+ * @see #reenableEvents()
+ * @since 3.0
+ */
+ final void disableEvents() {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by another reader
+ this.disableEvents++;
+ }
+ // while disableEvents > 0 no events will be reported, and mod count will stay fixed
+ }
+
+ /**
+ * Reenable events.
+ * This method is thread-safe for AST readers.
+ *
+ * @see #disableEvents()
+ * @since 3.0
+ */
+ final void reenableEvents() {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by another reader
+ this.disableEvents--;
+ }
+ }
+
+ /**
+ * Reports that the given node is about to lose a child.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be removed
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE DEL]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preRemoveChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node jsut lost a child.
+ *
+ * @param node the node that was modified
+ * @param child the child node that was removed
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE DEL]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postRemoveChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about have a child replaced.
+ *
+ * @param node the node about to be modified
+ * @param child the child node about to be removed
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE REP]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preReplaceChildEvent(node, child, newChild, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just had a child replaced.
+ *
+ * @param node the node modified
+ * @param child the child removed
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE REP]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postReplaceChildEvent(node, child, newChild, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to gain a child.
+ *
+ * @param node the node that to be modified
+ * @param child the node that to be added as a child
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE ADD]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preAddChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just gained a child.
+ *
+ * @param node the node that was modified
+ * @param child the node that was added as a child
+ * @param property the child or child list property descriptor
+ * @since 3.0
+ */
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE ADD]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postAddChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to change the value of a
+ * non-child property.
+ *
+ * @param node the node to be modified
+ * @param property the property descriptor
+ * @since 3.0
+ */
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CHANGE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preValueChangeEvent(node, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just changed the value of a
+ * non-child property.
+ *
+ * @param node the node that was modified
+ * @param property the property descriptor
+ * @since 3.0
+ */
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CHANGE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postValueChangeEvent(node, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to be cloned.
+ *
+ * @param node the node to be cloned
+ * @since 3.0
+ */
+ void preCloneNodeEvent(ASTNode node) {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CLONE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preCloneNodeEvent(node);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just been cloned.
+ *
+ * @param node the node that was cloned
+ * @param clone the clone of <code>node</code>
+ * @since 3.0
+ */
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CLONE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postCloneNodeEvent(node, clone);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Parses the source string of the given Java model compilation unit element
+ * and creates and returns a corresponding abstract syntax tree. The source
+ * string is obtained from the Java model element using
+ * <code>ICompilationUnit.getSource()</code>.
+ * <p>
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as <code>MALFORMED</code>.
+ * </p>
+ * <p>
+ * If <code>resolveBindings</code> is <code>true</code>, the various names
+ * and types appearing in the compilation unit can be resolved to "bindings"
+ * by calling the <code>resolveBinding</code> methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * <code>resolveBinding</code> methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If <code>resolveBindings</code> is <code>false</code>, the analysis
+ * does not go beyond parsing and building the tree, and all
+ * <code>resolveBinding</code> methods return <code>null</code> from the
+ * outset.
+ * </p>
+ *
+ * @param unit the Java model compilation unit whose source code is to be parsed
+ * @param resolveBindings <code>true</code> if bindings are wanted,
+ * and <code>false</code> if bindings are not of interest
+ * @return the compilation unit node
+ * @exception IllegalArgumentException if the given Java element does not
+ * exist or if its source string cannot be obtained
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 2.0
+ * @deprecated Use {@link ASTParser} instead.
+ */
+ public static CompilationUnit parseCompilationUnit(
+ ICompilationUnit unit,
+ boolean resolveBindings) {
+
+ try {
+ ASTParser c = ASTParser.newParser(AST.JLS2);
+ c.setSource(unit);
+ c.setResolveBindings(resolveBindings);
+ ASTNode result = c.createAST(null);
+ return (CompilationUnit) result;
+ } catch (IllegalStateException e) {
+ // convert ASTParser's complaints into old form
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Parses the source string corresponding to the given Java class file
+ * element and creates and returns a corresponding abstract syntax tree.
+ * The source string is obtained from the Java model element using
+ * <code>IClassFile.getSource()</code>, and is only available for a class
+ * files with attached source.
+ * <p>
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as <code>MALFORMED</code>.
+ * </p>
+ * <p>
+ * If <code>resolveBindings</code> is <code>true</code>, the various names
+ * and types appearing in the compilation unit can be resolved to "bindings"
+ * by calling the <code>resolveBinding</code> methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * <code>resolveBinding</code> methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If <code>resolveBindings</code> is <code>false</code>, the analysis
+ * does not go beyond parsing and building the tree, and all
+ * <code>resolveBinding</code> methods return <code>null</code> from the
+ * outset.
+ * </p>
+ *
+ * @param classFile the Java model class file whose corresponding source code is to be parsed
+ * @param resolveBindings <code>true</code> if bindings are wanted,
+ * and <code>false</code> if bindings are not of interest
+ * @return the compilation unit node
+ * @exception IllegalArgumentException if the given Java element does not
+ * exist or if its source string cannot be obtained
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 2.1
+ * @deprecated Use {@link ASTParser} instead.
+ */
+ public static CompilationUnit parseCompilationUnit(
+ IClassFile classFile,
+ boolean resolveBindings) {
+
+ if (classFile == null) {
+ throw new IllegalArgumentException();
+ }
+ try {
+ ASTParser c = ASTParser.newParser(AST.JLS2);
+ c.setSource(classFile);
+ c.setResolveBindings(resolveBindings);
+ ASTNode result = c.createAST(null);
+ return (CompilationUnit) result;
+ } catch (IllegalStateException e) {
+ // convert ASTParser's complaints into old form
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Parses the given string as the hypothetical contents of the named
+ * compilation unit and creates and returns a corresponding abstract syntax tree.
+ * <p>
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the given source string (the given source string itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as <code>MALFORMED</code>.
+ * </p>
+ * <p>
+ * If the given project is not <code>null</code>, the various names
+ * and types appearing in the compilation unit can be resolved to "bindings"
+ * by calling the <code>resolveBinding</code> methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * <code>resolveBinding</code> methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If the given project is <code>null</code>, the analysis
+ * does not go beyond parsing and building the tree, and all
+ * <code>resolveBinding</code> methods return <code>null</code> from the
+ * outset.
+ * </p>
+ * <p>
+ * The name of the compilation unit must be supplied for resolving bindings.
+ * This name should be suffixed by a dot ('.') followed by one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
+ * and match the name of the main
+ * (public) class or interface declared in the source. For example, if the source
+ * declares a public class named "Foo", the name of the compilation can be
+ * "Foo.java". For the purposes of resolving bindings, types declared in the
+ * source string hide types by the same name available through the classpath
+ * of the given project.
+ * </p>
+ *
+ * @param source the string to be parsed as a Java compilation unit
+ * @param unitName the name of the compilation unit that would contain the source
+ * string, or <code>null</code> if <code>javaProject</code> is also <code>null</code>
+ * @param project the Java project used to resolve names, or
+ * <code>null</code> if bindings are not resolved
+ * @return the compilation unit node
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 2.0
+ * @deprecated Use {@link ASTParser} instead.
+ */
+ public static CompilationUnit parseCompilationUnit(
+ char[] source,
+ String unitName,
+ IJavaProject project) {
+
+ if (source == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTParser astParser = ASTParser.newParser(AST.JLS2);
+ astParser.setSource(source);
+ astParser.setUnitName(unitName);
+ astParser.setProject(project);
+ astParser.setResolveBindings(project != null);
+ ASTNode result = astParser.createAST(null);
+ return (CompilationUnit) result;
+ }
+
+ /**
+ * Parses the given string as a Java compilation unit and creates and
+ * returns a corresponding abstract syntax tree.
+ * <p>
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the given source string (the given source string itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as <code>MALFORMED</code>.
+ * </p>
+ * <p>
+ * This method does not compute binding information; all <code>resolveBinding</code>
+ * methods applied to nodes of the resulting AST return <code>null</code>.
+ * </p>
+ *
+ * @param source the string to be parsed as a Java compilation unit
+ * @return the compilation unit node
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 2.0
+ * @deprecated Use {@link ASTParser} instead.
+ */
+ public static CompilationUnit parseCompilationUnit(char[] source) {
+ if (source == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTParser c = ASTParser.newParser(AST.JLS2);
+ c.setSource(source);
+ ASTNode result = c.createAST(null);
+ return (CompilationUnit) result;
+ }
+
+ /**
+ * Returns the binding resolver for this AST.
+ *
+ * @return the binding resolver for this AST
+ */
+ BindingResolver getBindingResolver() {
+ return this.resolver;
+ }
+
+ /**
+ * Returns the event handler for this AST.
+ *
+ * @return the event handler for this AST
+ * @since 3.0
+ */
+ NodeEventHandler getEventHandler() {
+ return this.eventHandler;
+ }
+
+ /**
+ * Sets the event handler for this AST.
+ *
+ * @param eventHandler the event handler for this AST
+ * @since 3.0
+ */
+ void setEventHandler(NodeEventHandler eventHandler) {
+ if (this.eventHandler == null) {
+ throw new IllegalArgumentException();
+ }
+ this.eventHandler = eventHandler;
+ }
+
+ /**
+ * Returns default node flags of new nodes of this AST.
+ *
+ * @return the default node flags of new nodes of this AST
+ * @since 3.0
+ */
+ int getDefaultNodeFlag() {
+ return this.defaultNodeFlag;
+ }
+
+ /**
+ * Sets default node flags of new nodes of this AST.
+ *
+ * @param flag node flags of new nodes of this AST
+ * @since 3.0
+ */
+ void setDefaultNodeFlag(int flag) {
+ this.defaultNodeFlag = flag;
+ }
+
+ /**
+ * Set <code>originalModificationCount</code> to the current modification count
+ *
+ * @since 3.0
+ */
+ void setOriginalModificationCount(long count) {
+ this.originalModificationCount = count;
+ }
+
+ /**
+ * Returns the type binding for a "well known" type.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ * <p>
+ * The following type names are supported:
+ * <ul>
+ * <li><code>"boolean"</code></li>
+ * <li><code>"byte"</code></li>
+ * <li><code>"char"</code></li>
+ * <li><code>"double"</code></li>
+ * <li><code>"float"</code></li>
+ * <li><code>"int"</code></li>
+ * <li><code>"long"</code></li>
+ * <li><code>"short"</code></li>
+ * <li><code>"void"</code></li>
+ * <li><code>"java.lang.Boolean"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Byte"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Character"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Class"</code></li>
+ * <li><code>"java.lang.Cloneable"</code></li>
+ * <li><code>"java.lang.Double"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Error"</code></li>
+ * <li><code>"java.lang.Exception"</code></li>
+ * <li><code>"java.lang.Float"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Integer"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Long"</code> (since 3.1)</li>
+ * <li><code>"java.lang.Object"</code></li>
+ * <li><code>"java.lang.RuntimeException"</code></li>
+ * <li><code>"java.lang.Short"</code> (since 3.1)</li>
+ * <li><code>"java.lang.String"</code></li>
+ * <li><code>"java.lang.StringBuffer"</code></li>
+ * <li><code>"java.lang.Throwable"</code></li>
+ * <li><code>"java.lang.Void"</code> (since 3.1)</li>
+ * <li><code>"java.io.Serializable"</code></li>
+ * </ul>
+ * </p>
+ *
+ * @param name the name of a well known type
+ * @return the corresponding type binding, or <code>null</code> if the
+ * named type is not considered well known or if no binding can be found
+ * for it
+ */
+ public ITypeBinding resolveWellKnownType(String name) {
+ if (name == null) {
+ return null;
+ }
+ return getBindingResolver().resolveWellKnownType(name);
+ }
+
+ /**
+ * Sets the binding resolver for this AST.
+ *
+ * @param resolver the new binding resolver for this AST
+ */
+ void setBindingResolver(BindingResolver resolver) {
+ if (resolver == null) {
+ throw new IllegalArgumentException();
+ }
+ this.resolver = resolver;
+ }
+
+ /**
+ * Checks that this AST operation is not used when
+ * building level JLS2 ASTs.
+
+ * @exception UnsupportedOperationException
+ * @since 3.0
+ */
+ void unsupportedIn2() {
+ if (this.apiLevel == AST.JLS2) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks that this AST operation is only used when
+ * building level JLS2 ASTs.
+
+ * @exception UnsupportedOperationException
+ * @since 3.0
+ */
+ void supportedOnlyIn2() {
+ if (this.apiLevel != AST.JLS2) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * new Class[] {AST.class}
+ * @since 3.0
+ */
+ private static final Class[] AST_CLASS = new Class[] {AST.class};
+
+ /**
+ * new Object[] {this}
+ * @since 3.0
+ */
+ private final Object[] THIS_AST= new Object[] {this};
+
+ /*
+ * Must not collide with a value for ICompilationUnit constants
+ */
+ static final int RESOLVED_BINDINGS = 0x80000000;
+
+ /**
+ * Tag bit value. This represents internal state of the tree.
+ */
+ private int bits;
+
+ /**
+ * Creates an unparented node of the given node class
+ * (non-abstract subclass of {@link ASTNode}).
+ *
+ * @param nodeClass AST node class
+ * @return a new unparented node owned by this AST
+ * @exception IllegalArgumentException if <code>nodeClass</code> is
+ * <code>null</code> or is not a concrete node type class
+ * @since 3.0
+ */
+ public ASTNode createInstance(Class nodeClass) {
+ if (nodeClass == null) {
+ throw new IllegalArgumentException();
+ }
+ try {
+ // invoke constructor with signature Foo(AST)
+ Constructor c = nodeClass.getDeclaredConstructor(AST_CLASS);
+ Object result = c.newInstance(this.THIS_AST);
+ return (ASTNode) result;
+ } catch (NoSuchMethodException e) {
+ // all AST node classes have a Foo(AST) constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (InstantiationException e) {
+ // all concrete AST node classes can be instantiated
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (IllegalAccessException e) {
+ // all AST node classes have an accessible Foo(AST) constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (InvocationTargetException e) {
+ // concrete AST node classes do not die in the constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Creates an unparented node of the given node type.
+ * This convenience method is equivalent to:
+ * <pre>
+ * createInstance(ASTNode.nodeClassForType(nodeType))
+ * </pre>
+ *
+ * @param nodeType AST node type, one of the node type
+ * constants declared on {@link ASTNode}
+ * @return a new unparented node owned by this AST
+ * @exception IllegalArgumentException if <code>nodeType</code> is
+ * not a legal AST node type
+ * @since 3.0
+ */
+ public ASTNode createInstance(int nodeType) {
+ // nodeClassForType throws IllegalArgumentException if nodeType is bogus
+ Class nodeClass = ASTNode.nodeClassForType(nodeType);
+ return createInstance(nodeClass);
+ }
+
+ //=============================== NAMES ===========================
+ /**
+ * Creates and returns a new unparented simple name node for the given
+ * identifier. The identifier should be a legal Java identifier, but not
+ * a keyword, boolean literal ("true", "false") or null literal ("null").
+ *
+ * @param identifier the identifier
+ * @return a new unparented simple name node
+ * @exception IllegalArgumentException if the identifier is invalid
+ */
+ public SimpleName newSimpleName(String identifier) {
+ if (identifier == null) {
+ throw new IllegalArgumentException();
+ }
+ SimpleName result = new SimpleName(this);
+ result.setIdentifier(identifier);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented qualified name node for the given
+ * qualifier and simple name child node.
+ *
+ * @param qualifier the qualifier name node
+ * @param name the simple name being qualified
+ * @return a new unparented qualified name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public QualifiedName newQualifiedName(
+ Name qualifier,
+ SimpleName name) {
+ QualifiedName result = new QualifiedName(this);
+ result.setQualifier(qualifier);
+ result.setName(name);
+ return result;
+
+ }
+
+ /**
+ * Creates and returns a new unparented name node for the given name
+ * segments. Returns a simple name if there is only one name segment, and
+ * a qualified name if there are multiple name segments. Each of the name
+ * segments should be legal Java identifiers (this constraint may or may
+ * not be enforced), and there must be at least one name segment.
+ *
+ * @param identifiers a list of 1 or more name segments, each of which
+ * is a legal Java identifier
+ * @return a new unparented name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the identifier is invalid</li>
+ * <li>the list of identifiers is empty</li>
+ * </ul>
+ */
+ public Name newName(String[] identifiers) {
+ // update internalSetName(String[] if changed
+ int count = identifiers.length;
+ if (count == 0) {
+ throw new IllegalArgumentException();
+ }
+ Name result = newSimpleName(identifiers[0]);
+ for (int i = 1; i < count; i++) {
+ SimpleName name = newSimpleName(identifiers[i]);
+ result = newQualifiedName(result, name);
+ }
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setName(String[]) that doesn't do any validation.
+ */
+ Name internalNewName(String[] identifiers) {
+ int count = identifiers.length;
+ if (count == 0) {
+ throw new IllegalArgumentException();
+ }
+ final SimpleName simpleName = new SimpleName(this);
+ simpleName.internalSetIdentifier(identifiers[0]);
+ Name result = simpleName;
+ for (int i = 1; i < count; i++) {
+ SimpleName name = new SimpleName(this);
+ name.internalSetIdentifier(identifiers[i]);
+ result = newQualifiedName(result, name);
+ }
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented name node for the given name.
+ * The name string must consist of 1 or more name segments separated
+ * by single dots '.'. Returns a {@link QualifiedName} if the name has
+ * dots, and a {@link SimpleName} otherwise. Each of the name
+ * segments should be legal Java identifiers (this constraint may or may
+ * not be enforced), and there must be at least one name segment.
+ * The string must not contains white space, '&lt;', '&gt;',
+ * '[', ']', or other any other characters that are not
+ * part of the Java identifiers or separating '.'s.
+ *
+ * @param qualifiedName string consisting of 1 or more name segments,
+ * each of which is a legal Java identifier, separated by single dots '.'
+ * @return a new unparented name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the string is empty</li>
+ * <li>the string begins or ends in a '.'</li>
+ * <li>the string has adjacent '.'s</li>
+ * <li>the segments between the '.'s are not valid Java identifiers</li>
+ * </ul>
+ * @since 3.1
+ */
+ public Name newName(String qualifiedName) {
+ StringTokenizer t = new StringTokenizer(qualifiedName, ".", true); //$NON-NLS-1$
+ Name result = null;
+ // balance is # of name tokens - # of period tokens seen so far
+ // initially 0; finally 1; should never drop < 0 or > 1
+ int balance = 0;
+ while(t.hasMoreTokens()) {
+ String s = t.nextToken();
+ if (s.indexOf('.') >= 0) {
+ // this is a delimiter
+ if (s.length() > 1) {
+ // too many dots in a row
+ throw new IllegalArgumentException();
+ }
+ balance--;
+ if (balance < 0) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ // this is an identifier segment
+ balance++;
+ SimpleName name = newSimpleName(s);
+ if (result == null) {
+ result = name;
+ } else {
+ result = newQualifiedName(result, name);
+ }
+ }
+ }
+ if (balance != 1) {
+ throw new IllegalArgumentException();
+ }
+ return result;
+ }
+//{ObjectTeams: factories for faked resolved name:
+ // Note, these methods are implemented here, because they need access to some
+ // package-private features.
+ /** This method creates a new dom-AST SimpleName that can be resolved to the same type as the provided <code>type</code>.
+ * the binding be of kind VARIABLE. */
+ public SimpleName newResolvedVariableName(String name, Type type) {
+ DefaultBindingResolver resolver = (DefaultBindingResolver)this.resolver;
+ org.eclipse.jdt.internal.compiler.ast.Expression givenCompilerNode =
+ (org.eclipse.jdt.internal.compiler.ast.Expression)resolver.newAstToOldAst.get(type);
+ long pos = ((long)givenCompilerNode.sourceStart << 32) + givenCompilerNode.sourceEnd;
+ return createMappedVariableNode(name, givenCompilerNode.resolvedType, pos);
+ }
+ public SimpleName newResolvedVariableName(String name, TypeDeclaration type) {
+ DefaultBindingResolver resolver = (DefaultBindingResolver)this.resolver;
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration givenCompilerNode =
+ (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)resolver.newAstToOldAst.get(type);
+ long pos = ((long)givenCompilerNode.sourceStart << 32) + givenCompilerNode.sourceEnd;
+ return createMappedVariableNode(name, givenCompilerNode.binding, pos);
+ }
+
+ private SimpleName createMappedVariableNode(String name,
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding,
+ long pos)
+ {
+ org.eclipse.jdt.internal.compiler.ast.SingleNameReference newCompilerNode
+ = new org.eclipse.jdt.internal.compiler.ast.SingleNameReference(name.toCharArray(), pos);
+ newCompilerNode.resolvedType = typeBinding;
+ newCompilerNode.binding = new LocalVariableBinding(name.toCharArray(), typeBinding, 0, false);
+ SimpleName result = newSimpleName(name);
+ this.resolver.store(result, newCompilerNode);
+ return result;
+ }
+// SH}
+
+ //=============================== TYPES ===========================
+ /**
+ * Creates and returns a new unparented simple type node with the given
+ * type name.
+ * <p>
+ * This method can be used to convert a name (<code>Name</code>) into a
+ * type (<code>Type</code>) by wrapping it.
+ * </p>
+ *
+ * @param typeName the name of the class or interface
+ * @return a new unparented simple type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public SimpleType newSimpleType(Name typeName) {
+ SimpleType result = new SimpleType(this);
+ result.setName(typeName);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array type node with the given
+ * component type, which may be another array type.
+ *
+ * @param componentType the component type (possibly another array type)
+ * @return a new unparented array type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public ArrayType newArrayType(Type componentType) {
+ ArrayType result = new ArrayType(this);
+ result.setComponentType(componentType);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array type node with the given
+ * element type and number of dimensions.
+ * <p>
+ * Note that if the element type passed in is an array type, the
+ * element type of the result will not be the same as what was passed in.
+ * </p>
+ *
+ * @param elementType the element type (never an array type)
+ * @param dimensions the number of dimensions, a positive number
+ * @return a new unparented array type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * <li>the element type is null</li>
+ * <li>the element type is an array type</li>
+ * <li>the number of dimensions is lower than 1</li>
+ * <li>the number of dimensions is greater than 1000</li>
+ * </ul>
+ */
+ public ArrayType newArrayType(Type elementType, int dimensions) {
+ if (elementType == null || elementType.isArrayType()) {
+ throw new IllegalArgumentException();
+ }
+ if (dimensions < 1 || dimensions > 1000) {
+ // we would blow our stacks anyway with a 1000-D array
+ throw new IllegalArgumentException();
+ }
+ ArrayType result = new ArrayType(this);
+ result.setComponentType(elementType);
+ for (int i = 2; i <= dimensions; i++) {
+ result = newArrayType(result);
+ }
+ return result;
+
+ }
+
+ /**
+ * Creates and returns a new unparented primitive type node with the given
+ * type code.
+ *
+ * @param typeCode one of the primitive type code constants declared in
+ * <code>PrimitiveType</code>
+ * @return a new unparented primitive type node
+ * @exception IllegalArgumentException if the primitive type code is invalid
+ */
+ public PrimitiveType newPrimitiveType(PrimitiveType.Code typeCode) {
+ PrimitiveType result = new PrimitiveType(this);
+ result.setPrimitiveTypeCode(typeCode);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented parameterized type node with the
+ * given type and an empty list of type arguments.
+ *
+ * @param type the type that is parameterized
+ * @return a new unparented parameterized type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public ParameterizedType newParameterizedType(Type type) {
+ ParameterizedType result = new ParameterizedType(this);
+ result.setType(type);
+ return result;
+ }
+
+//{ObjectTeams: type anchor to be used with ParameterizedType:
+ public TypeAnchor newTypeAnchor(Name path) {
+ TypeAnchor result = new TypeAnchor(this);
+ result.setPath(path);
+ return result;
+ }
+// SH}
+
+ /**
+ * Creates and returns a new unparented qualified type node with
+ * the given qualifier type and name.
+ *
+ * @param qualifier the qualifier type node
+ * @param name the simple name being qualified
+ * @return a new unparented qualified type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public QualifiedType newQualifiedType(Type qualifier, SimpleName name) {
+ QualifiedType result = new QualifiedType(this);
+ result.setQualifier(qualifier);
+ result.setName(name);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented wildcard type node with no
+ * type bound.
+ *
+ * @return a new unparented wildcard type node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public WildcardType newWildcardType() {
+ WildcardType result = new WildcardType(this);
+ return result;
+ }
+
+//{ObjectTeams: factory method for LiftingType
+ /**
+ * Creates and returns a new unparented lifting type node with the given
+ * type name.
+ *
+ * @param typeName the name of the class or interface
+ * @return a new unparented lifting type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public LiftingType newLiftingType(Name typeName)
+ {
+ LiftingType result = new LiftingType(this);
+ result.setName(typeName);
+ return result;
+ }
+//gbr}
+
+ //=============================== DECLARATIONS ===========================
+ /**
+ * Creates an unparented compilation unit node owned by this AST.
+ * The compilation unit initially has no package declaration, no
+ * import declarations, and no type declarations.
+ *
+ * @return the new unparented compilation unit node
+ */
+ public CompilationUnit newCompilationUnit() {
+ return new CompilationUnit(this);
+ }
+
+ /**
+ * Creates an unparented package declaration node owned by this AST.
+ * The package declaration initially declares a package with an
+ * unspecified name.
+ *
+ * @return the new unparented package declaration node
+ */
+ public PackageDeclaration newPackageDeclaration() {
+ PackageDeclaration result = new PackageDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented import declaration node owned by this AST.
+ * The import declaration initially contains a single-type import
+ * of a type with an unspecified name.
+ *
+ * @return the new unparented import declaration node
+ */
+ public ImportDeclaration newImportDeclaration() {
+ ImportDeclaration result = new ImportDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented class declaration node owned by this AST.
+ * The name of the class is an unspecified, but legal, name;
+ * no modifiers; no doc comment; no superclass or superinterfaces;
+ * and an empty class body.
+ * <p>
+ * To create an interface, use this method and then call
+ * <code>TypeDeclaration.setInterface(true)</code>.
+ * </p>
+ *
+ * @return a new unparented type declaration node
+ */
+ public TypeDeclaration newTypeDeclaration() {
+ TypeDeclaration result = new TypeDeclaration(this);
+ result.setInterface(false);
+ return result;
+ }
+
+//{ObjectTeams:
+ /**
+ * Creates an unparented class declaration node owned by this AST.
+ * The name of the class is an unspecified, but legal, name;
+ * no modifiers; no doc comment; no superclass or superinterfaces;
+ * and an empty class body.
+ * <p>
+ * To create an interface, use this method and then call
+ * <code>RoleTypeDeclaration.setInterface(true)</code>.
+ * </p>
+ *
+ * @return a new unparented roleType declaration node
+ */
+ public RoleTypeDeclaration newRoleTypeDeclaration() {
+ RoleTypeDeclaration result = new RoleTypeDeclaration(this);
+ return result;
+ }
+
+ public PrecedenceDeclaration newPrecedenceDeclaration() {
+ return new PrecedenceDeclaration(this);
+ }
+
+ public GuardPredicateDeclaration newGuardPredicateDeclaration () {
+ return new GuardPredicateDeclaration(this);
+ }
+// km(merge) }
+
+ /**
+ * Creates an unparented method declaration node owned by this AST.
+ * By default, the declaration is for a method of an unspecified, but
+ * legal, name; no modifiers; no doc comment; no parameters; return
+ * type void; no extra array dimensions; no thrown exceptions; and no
+ * body (as opposed to an empty body).
+ * <p>
+ * To create a constructor, use this method and then call
+ * <code>MethodDeclaration.setConstructor(true)</code> and
+ * <code>MethodDeclaration.setName(className)</code>.
+ * </p>
+ *
+ * @return a new unparented method declaration node
+ */
+ public MethodDeclaration newMethodDeclaration() {
+ MethodDeclaration result = new MethodDeclaration(this);
+ result.setConstructor(false);
+ return result;
+ }
+
+ /**
+ * Creates an unparented single variable declaration node owned by this AST.
+ * By default, the declaration is for a variable with an unspecified, but
+ * legal, name and type; no modifiers; no array dimensions after the
+ * variable; no initializer; not variable arity.
+ *
+ * @return a new unparented single variable declaration node
+ */
+ public SingleVariableDeclaration newSingleVariableDeclaration() {
+ SingleVariableDeclaration result = new SingleVariableDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented variable declaration fragment node owned by this
+ * AST. By default, the fragment is for a variable with an unspecified, but
+ * legal, name; no extra array dimensions; and no initializer.
+ *
+ * @return a new unparented variable declaration fragment node
+ */
+ public VariableDeclarationFragment newVariableDeclarationFragment() {
+ VariableDeclarationFragment result = new VariableDeclarationFragment(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented initializer node owned by this AST, with an
+ * empty block. By default, the initializer has no modifiers and
+ * an empty block.
+ *
+ * @return a new unparented initializer node
+ */
+ public Initializer newInitializer() {
+ Initializer result = new Initializer(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented enum constant declaration node owned by this AST.
+ * The name of the constant is an unspecified, but legal, name;
+ * no doc comment; no modifiers or annotations; no arguments;
+ * and does not declare an anonymous class.
+ *
+ * @return a new unparented enum constant declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public EnumConstantDeclaration newEnumConstantDeclaration() {
+ EnumConstantDeclaration result = new EnumConstantDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented enum declaration node owned by this AST.
+ * The name of the enum is an unspecified, but legal, name;
+ * no doc comment; no modifiers or annotations;
+ * no superinterfaces; and empty lists of enum constants
+ * and body declarations.
+ *
+ * @return a new unparented enum declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public EnumDeclaration newEnumDeclaration() {
+ EnumDeclaration result = new EnumDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented type parameter type node with an
+ * unspecified type variable name and an empty list of type bounds.
+ *
+ * @return a new unparented type parameter node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public TypeParameter newTypeParameter() {
+ TypeParameter result = new TypeParameter(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented annotation type declaration
+ * node for an unspecified, but legal, name; no modifiers; no javadoc;
+ * and an empty list of member declarations.
+ *
+ * @return a new unparented annotation type declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public AnnotationTypeDeclaration newAnnotationTypeDeclaration() {
+ AnnotationTypeDeclaration result = new AnnotationTypeDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented annotation type
+ * member declaration node for an unspecified, but legal,
+ * member name and type; no modifiers; no javadoc;
+ * and no default value.
+ *
+ * @return a new unparented annotation type member declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public AnnotationTypeMemberDeclaration newAnnotationTypeMemberDeclaration() {
+ AnnotationTypeMemberDeclaration result = new AnnotationTypeMemberDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented modifier node for the given
+ * modifier.
+ *
+ * @param keyword one of the modifier keyword constants
+ * @return a new unparented modifier node
+ * @exception IllegalArgumentException if the primitive type code is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public Modifier newModifier(Modifier.ModifierKeyword keyword) {
+ Modifier result = new Modifier(this);
+ result.setKeyword(keyword);
+ return result;
+ }
+
+ /**
+ * Creates and returns a list of new unparented modifier nodes
+ * for the given modifier flags. When multiple modifiers are
+ * requested the modifiers nodes will appear in the following order:
+ * public, protected, private, abstract, static, final, synchronized,
+ * native, strictfp, transient, volatile. This order is consistent
+ * with the recommendations in JLS2 8.1.1, 8.3.1, and 8.4.3.
+ *
+ * @param flags bitwise or of modifier flags declared on {@link Modifier}
+ * @return a possibly empty list of new unparented modifier nodes
+ * (element type <code>Modifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List newModifiers(int flags) {
+ if (this.apiLevel == AST.JLS2) {
+ unsupportedIn2();
+ }
+ List result = new ArrayList(3); // 3 modifiers is more than average
+ if (Modifier.isPublic(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
+ }
+ if (Modifier.isProtected(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD));
+ }
+ if (Modifier.isPrivate(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
+ }
+ if (Modifier.isAbstract(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD));
+ }
+ if (Modifier.isStatic(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.STATIC_KEYWORD));
+ }
+ if (Modifier.isFinal(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
+ }
+ if (Modifier.isSynchronized(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD));
+ }
+ if (Modifier.isNative(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD));
+ }
+ if (Modifier.isStrictfp(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD));
+ }
+ if (Modifier.isTransient(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD));
+ }
+ if (Modifier.isVolatile(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD));
+ }
+//{ObjectTeams: OT-specific modifiers (any context):
+ if (Modifier.isReplace(flags) || Modifier.isBefore(flags) || Modifier.isAfter(flags))
+ throw new IllegalArgumentException("not applicable for callin modifiers"); //$NON-NLS-1$
+
+ if (Modifier.isGet(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.GET_KEYWORD));
+ }
+ if (Modifier.isSet(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.SET_KEYWORD));
+ }
+ if (Modifier.isTeam(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.TEAM_KEYWORD));
+ }
+ if (Modifier.isCallin(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.CALLIN_KEYWORD));
+ }
+// SH}
+ return result;
+ }
+
+//{ObjectTeams: factory methods for CallinMappingDeclaration and CalloutMappingDeclaration
+ /**
+ * Creates an unparented callin mapping declaration node owned by this AST.
+ * The binding kind is set to {@link MethodBindingOperator#KIND_CALLIN}
+ *
+ * @return a new unparented callin mapping declaration node
+ */
+ public CallinMappingDeclaration newCallinMappingDeclaration()
+ {
+ CallinMappingDeclaration callinMappingDeclaration = new CallinMappingDeclaration(this);
+ callinMappingDeclaration.bindingOperator().setBindingKind(MethodBindingOperator.KIND_CALLIN);
+ return callinMappingDeclaration;
+ }
+
+ /**
+ * Creates an unparented callout mapping declaration node owned by this AST.
+ * The binding kind is set to {@link MethodBindingOperator#KIND_CALLOUT},
+ * clients creating a callout override must change this property afterwards.
+ *
+ * @return a new unparented callout mapping declaration node
+ */
+ public CalloutMappingDeclaration newCalloutMappingDeclaration()
+ {
+ CalloutMappingDeclaration calloutMappingDeclaration = new CalloutMappingDeclaration(this);
+ calloutMappingDeclaration.bindingOperator().setBindingKind(MethodBindingOperator.KIND_CALLOUT); // default
+ return calloutMappingDeclaration;
+ }
+
+ /**
+ * creates a new unparented method bidning operator node owned by this AST.
+ * @param keyword one of before/replace/after (callin) or get/set (c-t-f) or null (regular callout)
+ * @param bindingKind one of {@link MethodBindingOperator#KIND_CALLOUT}, {@link MethodBindingOperator#KIND_CALLOUT_OVERRIDE} or {@link MethodBindingOperator#KIND_CALLIN}.
+ * @return new unparented node
+ * @since 1.3.1
+ */
+ public MethodBindingOperator newMethodBindingOperator(ModifierKeyword keyword, int bindingKind) {
+ MethodBindingOperator result = new MethodBindingOperator(this);
+ if (keyword != null)
+ result.setBindingModifier(newModifier(keyword));
+ result.setBindingKind(bindingKind);
+ return result;
+ }
+//gbr+SH}
+
+//{ObjectTeams: factory method for MethodSpec
+ /**
+ * Creates an unparented method spec declaration node owned by this AST.
+ *
+ * @return a new unparented method spec declaration node
+ */
+ public MethodSpec newMethodSpec()
+ {
+ return new MethodSpec(this);
+ }
+//gbr}
+
+// {ObjectTeams: factory method for FieldAccessSpec
+ /**
+ * Creates an unparented method spec declaration node owned by this AST.
+ *
+ * @return a new unparented method spec declaration node
+ */
+ public FieldAccessSpec newFieldAccessSpec()
+ {
+ return new FieldAccessSpec(this);
+ }
+//jsv}
+
+ //=============================== COMMENTS ===========================
+
+ /**
+ * Creates and returns a new block comment placeholder node.
+ * <p>
+ * Note that this node type is used to recording the source
+ * range where a comment was found in the source string.
+ * These comment nodes are normally found (only) in
+ * {@linkplain CompilationUnit#getCommentList()
+ * the comment table} for parsed compilation units.
+ * </p>
+ *
+ * @return a new unparented block comment node
+ * @since 3.0
+ */
+ public BlockComment newBlockComment() {
+ BlockComment result = new BlockComment(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new line comment placeholder node.
+ * <p>
+ * Note that this node type is used to recording the source
+ * range where a comment was found in the source string.
+ * These comment nodes are normally found (only) in
+ * {@linkplain CompilationUnit#getCommentList()
+ * the comment table} for parsed compilation units.
+ * </p>
+ *
+ * @return a new unparented line comment node
+ * @since 3.0
+ */
+ public LineComment newLineComment() {
+ LineComment result = new LineComment(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new doc comment node.
+ * Initially the new node has an empty list of tag elements
+ * (and, for backwards compatability, an unspecified, but legal,
+ * doc comment string)
+ *
+ * @return a new unparented doc comment node
+ */
+ public Javadoc newJavadoc() {
+ Javadoc result = new Javadoc(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new tag element node.
+ * Initially the new node has no tag name and an empty list of fragments.
+ * <p>
+ * Note that this node type is used only inside doc comments
+ * ({@link Javadoc}).
+ * </p>
+ *
+ * @return a new unparented tag element node
+ * @since 3.0
+ */
+ public TagElement newTagElement() {
+ TagElement result = new TagElement(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new text element node.
+ * Initially the new node has an empty text string.
+ * <p>
+ * Note that this node type is used only inside doc comments
+ * ({@link Javadoc Javadoc}).
+ * </p>
+ *
+ * @return a new unparented text element node
+ * @since 3.0
+ */
+ public TextElement newTextElement() {
+ TextElement result = new TextElement(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new member reference node.
+ * Initially the new node has no qualifier name and
+ * an unspecified, but legal, member name.
+ * <p>
+ * Note that this node type is used only inside doc comments
+ * ({@link Javadoc}).
+ * </p>
+ *
+ * @return a new unparented member reference node
+ * @since 3.0
+ */
+ public MemberRef newMemberRef() {
+ MemberRef result = new MemberRef(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new method reference node.
+ * Initially the new node has no qualifier name,
+ * an unspecified, but legal, method name, and an
+ * empty parameter list.
+ * <p>
+ * Note that this node type is used only inside doc comments
+ * ({@link Javadoc Javadoc}).
+ * </p>
+ *
+ * @return a new unparented method reference node
+ * @since 3.0
+ */
+ public MethodRef newMethodRef() {
+ MethodRef result = new MethodRef(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new method reference node.
+ * Initially the new node has an unspecified, but legal,
+ * type, not variable arity, and no parameter name.
+ * <p>
+ * Note that this node type is used only inside doc comments
+ * ({@link Javadoc}).
+ * </p>
+ *
+ * @return a new unparented method reference parameter node
+ * @since 3.0
+ */
+ public MethodRefParameter newMethodRefParameter() {
+ MethodRefParameter result = new MethodRefParameter(this);
+ return result;
+ }
+
+ //=============================== STATEMENTS ===========================
+ /**
+ * Creates a new unparented local variable declaration statement node
+ * owned by this AST, for the given variable declaration fragment.
+ * By default, there are no modifiers and the base type is unspecified
+ * (but legal).
+ * <p>
+ * This method can be used to convert a variable declaration fragment
+ * (<code>VariableDeclarationFragment</code>) into a statement
+ * (<code>Statement</code>) by wrapping it. Additional variable
+ * declaration fragments can be added afterwards.
+ * </p>
+ *
+ * @param fragment the variable declaration fragment
+ * @return a new unparented variable declaration statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * <li>the variable declaration fragment is null</li>
+ * </ul>
+ */
+ public VariableDeclarationStatement
+ newVariableDeclarationStatement(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ VariableDeclarationStatement result =
+ new VariableDeclarationStatement(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local type declaration statement node
+ * owned by this AST, for the given type declaration.
+ * <p>
+ * This method can be used to convert a type declaration
+ * (<code>TypeDeclaration</code>) into a statement
+ * (<code>Statement</code>) by wrapping it.
+ * </p>
+ *
+ * @param decl the type declaration
+ * @return a new unparented local type declaration statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public TypeDeclarationStatement
+ newTypeDeclarationStatement(TypeDeclaration decl) {
+ TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+ result.setDeclaration(decl);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local type declaration statement node
+ * owned by this AST, for the given type declaration.
+ * <p>
+ * This method can be used to convert any kind of type declaration
+ * (<code>AbstractTypeDeclaration</code>) into a statement
+ * (<code>Statement</code>) by wrapping it.
+ * </p>
+ *
+ * @param decl the type declaration
+ * @return a new unparented local type declaration statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ * @since 3.0
+ */
+ public TypeDeclarationStatement
+ newTypeDeclarationStatement(AbstractTypeDeclaration decl) {
+ TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+ if (this.apiLevel == AST.JLS2) {
+ result.internalSetTypeDeclaration((TypeDeclaration) decl);
+ }
+ if (this.apiLevel >= AST.JLS3) {
+ result.setDeclaration(decl);
+ }
+ return result;
+ }
+
+ /**
+ * Creates an unparented block node owned by this AST, for an empty list
+ * of statements.
+ *
+ * @return a new unparented, empty block node
+ */
+ public Block newBlock() {
+ return new Block(this);
+ }
+
+ /**
+ * Creates an unparented continue statement node owned by this AST.
+ * The continue statement has no label.
+ *
+ * @return a new unparented continue statement node
+ */
+ public ContinueStatement newContinueStatement() {
+ return new ContinueStatement(this);
+ }
+
+ /**
+ * Creates an unparented break statement node owned by this AST.
+ * The break statement has no label.
+ *
+ * @return a new unparented break statement node
+ */
+ public BreakStatement newBreakStatement() {
+ return new BreakStatement(this);
+ }
+
+ /**
+ * Creates a new unparented expression statement node owned by this AST,
+ * for the given expression.
+ * <p>
+ * This method can be used to convert an expression
+ * (<code>Expression</code>) into a statement (<code>Type</code>)
+ * by wrapping it. Note, however, that the result is only legal for
+ * limited expression types, including method invocations, assignments,
+ * and increment/decrement operations.
+ * </p>
+ *
+ * @param expression the expression
+ * @return a new unparented statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public ExpressionStatement newExpressionStatement(Expression expression) {
+ ExpressionStatement result = new ExpressionStatement(this);
+ result.setExpression(expression);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented if statement node owned by this AST.
+ * By default, the expression is unspecified (but legal),
+ * the then statement is an empty block, and there is no else statement.
+ *
+ * @return a new unparented if statement node
+ */
+ public IfStatement newIfStatement() {
+ return new IfStatement(this);
+ }
+
+ /**
+ * Creates a new unparented while statement node owned by this AST.
+ * By default, the expression is unspecified (but legal), and
+ * the body statement is an empty block.
+ *
+ * @return a new unparented while statement node
+ */
+ public WhileStatement newWhileStatement() {
+ return new WhileStatement(this);
+ }
+
+ /**
+ * Creates a new unparented do statement node owned by this AST.
+ * By default, the expression is unspecified (but legal), and
+ * the body statement is an empty block.
+ *
+ * @return a new unparented do statement node
+ */
+ public DoStatement newDoStatement() {
+ return new DoStatement(this);
+ }
+
+ /**
+ * Creates a new unparented try statement node owned by this AST.
+ * By default, the try statement has an empty block, no catch
+ * clauses, and no finally block.
+ *
+ * @return a new unparented try statement node
+ */
+ public TryStatement newTryStatement() {
+ return new TryStatement(this);
+ }
+
+ /**
+ * Creates a new unparented catch clause node owned by this AST.
+ * By default, the catch clause declares an unspecified, but legal,
+ * exception declaration and has an empty block.
+ *
+ * @return a new unparented catch clause node
+ */
+ public CatchClause newCatchClause() {
+ return new CatchClause(this);
+ }
+
+ /**
+ * Creates a new unparented return statement node owned by this AST.
+ * By default, the return statement has no expression.
+ *
+ * @return a new unparented return statement node
+ */
+ public ReturnStatement newReturnStatement() {
+ return new ReturnStatement(this);
+ }
+
+ /**
+ * Creates a new unparented throw statement node owned by this AST.
+ * By default, the expression is unspecified, but legal.
+ *
+ * @return a new unparented throw statement node
+ */
+ public ThrowStatement newThrowStatement() {
+ return new ThrowStatement(this);
+ }
+
+ /**
+ * Creates a new unparented assert statement node owned by this AST.
+ * By default, the first expression is unspecified, but legal, and has no
+ * message expression.
+ *
+ * @return a new unparented assert statement node
+ */
+ public AssertStatement newAssertStatement() {
+ return new AssertStatement(this);
+ }
+
+ /**
+ * Creates a new unparented empty statement node owned by this AST.
+ *
+ * @return a new unparented empty statement node
+ */
+ public EmptyStatement newEmptyStatement() {
+ return new EmptyStatement(this);
+ }
+
+ /**
+ * Creates a new unparented labeled statement node owned by this AST.
+ * By default, the label and statement are both unspecified, but legal.
+ *
+ * @return a new unparented labeled statement node
+ */
+ public LabeledStatement newLabeledStatement() {
+ return new LabeledStatement(this);
+ }
+
+ /**
+ * Creates a new unparented switch statement node owned by this AST.
+ * By default, the expression is unspecified, but legal, and there are
+ * no statements or switch cases.
+ *
+ * @return a new unparented labeled statement node
+ */
+ public SwitchStatement newSwitchStatement() {
+ return new SwitchStatement(this);
+ }
+
+ /**
+ * Creates a new unparented switch case statement node owned by
+ * this AST. By default, the expression is unspecified, but legal.
+ *
+ * @return a new unparented switch case node
+ */
+ public SwitchCase newSwitchCase() {
+ return new SwitchCase(this);
+ }
+
+ /**
+ * Creates a new unparented synchronized statement node owned by this AST.
+ * By default, the expression is unspecified, but legal, and the body is
+ * an empty block.
+ *
+ * @return a new unparented synchronized statement node
+ */
+ public SynchronizedStatement newSynchronizedStatement() {
+ return new SynchronizedStatement(this);
+ }
+
+ /**
+ * Creates a new unparented for statement node owned by this AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @return a new unparented for statement node
+ */
+ public ForStatement newForStatement() {
+ return new ForStatement(this);
+ }
+
+ /**
+ * Creates a new unparented enhanced for statement node owned by this AST.
+ * By default, the paramter and expression are unspecified
+ * but legal subtrees, and the body is an empty block.
+ *
+ * @return a new unparented throw statement node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public EnhancedForStatement newEnhancedForStatement() {
+ return new EnhancedForStatement(this);
+ }
+
+//{ObjectTeams: factory method for WithinStatement
+ /**
+ * Creates a new unparented within statement node owned by this AST,
+ * for an empty list of statements.
+ *
+ * @return a new unparented, empty within statement node
+ *
+ */
+ public WithinStatement newWithinStatement()
+ {
+ return new WithinStatement(this);
+ }
+//gbr}
+
+// {ObjectTeams: factory method for ParameterMapping
+ /**
+ * Creates a new unparented parameter mapping node owned by this AST
+ *
+ * @return a new unparented, empty parameter mapping node
+ *
+ */
+ public ParameterMapping newParameterMapping()
+ {
+ return new ParameterMapping(this);
+ }
+//jsv}
+
+ //=============================== EXPRESSIONS ===========================
+ /**
+ * Creates and returns a new unparented string literal node for
+ * the empty string literal.
+ *
+ * @return a new unparented string literal node
+ */
+ public StringLiteral newStringLiteral() {
+ return new StringLiteral(this);
+ }
+
+
+ /**
+ * Creates and returns a new unparented character literal node.
+ * Initially the node has an unspecified character literal.
+ *
+ * @return a new unparented character literal node
+ */
+ public CharacterLiteral newCharacterLiteral() {
+ return new CharacterLiteral(this);
+ }
+
+ /**
+ * Creates and returns a new unparented number literal node.
+ *
+ * @param literal the token for the numeric literal as it would
+ * appear in Java source code
+ * @return a new unparented number literal node
+ * @exception IllegalArgumentException if the literal is null
+ */
+ public NumberLiteral newNumberLiteral(String literal) {
+ if (literal == null) {
+ throw new IllegalArgumentException();
+ }
+ NumberLiteral result = new NumberLiteral(this);
+ result.setToken(literal);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented number literal node.
+ * Initially the number literal token is <code>"0"</code>.
+ *
+ * @return a new unparented number literal node
+ */
+ public NumberLiteral newNumberLiteral() {
+ NumberLiteral result = new NumberLiteral(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented null literal node.
+ *
+ * @return a new unparented null literal node
+ */
+ public NullLiteral newNullLiteral() {
+ return new NullLiteral(this);
+ }
+
+ /**
+ * Creates and returns a new unparented boolean literal node.
+ * <p>
+ * For example, the assignment expression <code>foo = true</code>
+ * is generated by the following snippet:
+ * <code>
+ * <pre>
+ * Assignment e= ast.newAssignment();
+ * e.setLeftHandSide(ast.newSimpleName("foo"));
+ * e.setRightHandSide(ast.newBooleanLiteral(true));
+ * </pre>
+ * </code>
+ * </p>
+ *
+ * @param value the boolean value
+ * @return a new unparented boolean literal node
+ */
+ public BooleanLiteral newBooleanLiteral(boolean value) {
+ BooleanLiteral result = new BooleanLiteral(this);
+ result.setBooleanValue(value);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented assignment expression node
+ * owned by this AST. By default, the assignment operator is "=" and
+ * the left and right hand side expressions are unspecified, but
+ * legal, names.
+ *
+ * @return a new unparented assignment expression node
+ */
+ public Assignment newAssignment() {
+ Assignment result = new Assignment(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented method invocation expression node owned by this
+ * AST. By default, the name of the method is unspecified (but legal)
+ * there is no receiver expression, no type arguments, and the list of
+ * arguments is empty.
+ *
+ * @return a new unparented method invocation expression node
+ */
+ public MethodInvocation newMethodInvocation() {
+ MethodInvocation result = new MethodInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented "super" method invocation expression node owned by
+ * this AST. By default, the name of the method is unspecified (but legal)
+ * there is no qualifier, no type arguments, and the list of arguments is empty.
+ *
+ * @return a new unparented "super" method invocation
+ * expression node
+ */
+ public SuperMethodInvocation newSuperMethodInvocation() {
+ SuperMethodInvocation result = new SuperMethodInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented alternate constructor ("this(...);") invocation
+ * statement node owned by this AST. By default, the lists of arguments
+ * and type arguments are both empty.
+ * <p>
+ * Note that this type of node is a Statement, whereas a regular
+ * method invocation is an Expression. The only valid use of these
+ * statements are as the first statement of a constructor body.
+ * </p>
+ *
+ * @return a new unparented alternate constructor invocation statement node
+ */
+ public ConstructorInvocation newConstructorInvocation() {
+ ConstructorInvocation result = new ConstructorInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented alternate super constructor ("super(...);")
+ * invocation statement node owned by this AST. By default, there is no
+ * qualifier, no type arguments, and the list of arguments is empty.
+ * <p>
+ * Note that this type of node is a Statement, whereas a regular
+ * super method invocation is an Expression. The only valid use of these
+ * statements are as the first statement of a constructor body.
+ * </p>
+ *
+ * @return a new unparented super constructor invocation statement node
+ */
+ public SuperConstructorInvocation newSuperConstructorInvocation() {
+ SuperConstructorInvocation result =
+ new SuperConstructorInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local variable declaration expression node
+ * owned by this AST, for the given variable declaration fragment. By
+ * default, there are no modifiers and the base type is unspecified
+ * (but legal).
+ * <p>
+ * This method can be used to convert a variable declaration fragment
+ * (<code>VariableDeclarationFragment</code>) into an expression
+ * (<code>Expression</code>) by wrapping it. Additional variable
+ * declaration fragments can be added afterwards.
+ * </p>
+ *
+ * @param fragment the first variable declaration fragment
+ * @return a new unparented variable declaration expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * <li>the given fragment is null</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public VariableDeclarationExpression
+ newVariableDeclarationExpression(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ VariableDeclarationExpression result =
+ new VariableDeclarationExpression(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented field declaration node owned by this AST,
+ * for the given variable declaration fragment. By default, there are no
+ * modifiers, no doc comment, and the base type is unspecified
+ * (but legal).
+ * <p>
+ * This method can be used to wrap a variable declaration fragment
+ * (<code>VariableDeclarationFragment</code>) into a field declaration
+ * suitable for inclusion in the body of a type declaration
+ * (<code>FieldDeclaration</code> implements <code>BodyDeclaration</code>).
+ * Additional variable declaration fragments can be added afterwards.
+ * </p>
+ *
+ * @param fragment the variable declaration fragment
+ * @return a new unparented field declaration node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * <li>the given fragment is null</li>
+ * </ul>
+ */
+ public FieldDeclaration newFieldDeclaration(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ FieldDeclaration result = new FieldDeclaration(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented "this" expression node
+ * owned by this AST. By default, there is no qualifier.
+ *
+ * @return a new unparented "this" expression node
+ */
+ public ThisExpression newThisExpression() {
+ ThisExpression result = new ThisExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented field access expression node
+ * owned by this AST. By default, the expression and field are both
+ * unspecified, but legal, names.
+ *
+ * @return a new unparented field access expression node
+ */
+ public FieldAccess newFieldAccess() {
+ FieldAccess result = new FieldAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented super field access expression node
+ * owned by this AST. By default, the expression and field are both
+ * unspecified, but legal, names.
+ *
+ * @return a new unparented super field access expression node
+ */
+ public SuperFieldAccess newSuperFieldAccess() {
+ SuperFieldAccess result = new SuperFieldAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented type literal expression node
+ * owned by this AST. By default, the type is unspecified (but legal).
+ *
+ * @return a new unparented type literal node
+ */
+ public TypeLiteral newTypeLiteral() {
+ TypeLiteral result = new TypeLiteral(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented cast expression node
+ * owned by this AST. By default, the type and expression are unspecified
+ * (but legal).
+ *
+ * @return a new unparented cast expression node
+ */
+ public CastExpression newCastExpression() {
+ CastExpression result = new CastExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented parenthesized expression node
+ * owned by this AST. By default, the expression is unspecified (but legal).
+ *
+ * @return a new unparented parenthesized expression node
+ */
+ public ParenthesizedExpression newParenthesizedExpression() {
+ ParenthesizedExpression result = new ParenthesizedExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented infix expression node
+ * owned by this AST. By default, the operator and left and right
+ * operand are unspecified (but legal), and there are no extended
+ * operands.
+ *
+ * @return a new unparented infix expression node
+ */
+ public InfixExpression newInfixExpression() {
+ InfixExpression result = new InfixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented instanceof expression node
+ * owned by this AST. By default, the operator and left and right
+ * operand are unspecified (but legal).
+ *
+ * @return a new unparented instanceof expression node
+ */
+ public InstanceofExpression newInstanceofExpression() {
+ InstanceofExpression result = new InstanceofExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented postfix expression node
+ * owned by this AST. By default, the operator and operand are
+ * unspecified (but legal).
+ *
+ * @return a new unparented postfix expression node
+ */
+ public PostfixExpression newPostfixExpression() {
+ PostfixExpression result = new PostfixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented prefix expression node
+ * owned by this AST. By default, the operator and operand are
+ * unspecified (but legal).
+ *
+ * @return a new unparented prefix expression node
+ */
+ public PrefixExpression newPrefixExpression() {
+ PrefixExpression result = new PrefixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array access expression node
+ * owned by this AST. By default, the array and index expression are
+ * both unspecified (but legal).
+ *
+ * @return a new unparented array access expression node
+ */
+ public ArrayAccess newArrayAccess() {
+ ArrayAccess result = new ArrayAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array creation expression node
+ * owned by this AST. By default, the array type is an unspecified
+ * 1-dimensional array, the list of dimensions is empty, and there is no
+ * array initializer.
+ * <p>
+ * Examples:
+ * <code>
+ * <pre>
+ * // new String[len]
+ * ArrayCreation ac1 = ast.newArrayCreation();
+ * ac1.setType(
+ * ast.newArrayType(
+ * ast.newSimpleType(ast.newSimpleName("String"))));
+ * ac1.dimensions().add(ast.newSimpleName("len"));
+ *
+ * // new double[7][24][]
+ * ArrayCreation ac2 = ast.newArrayCreation();
+ * ac2.setType(
+ * ast.newArrayType(
+ * ast.newPrimitiveType(PrimitiveType.DOUBLE), 3));
+ * ac2.dimensions().add(ast.newNumberLiteral("7"));
+ * ac2.dimensions().add(ast.newNumberLiteral("24"));
+ *
+ * // new int[] {1, 2}
+ * ArrayCreation ac3 = ast.newArrayCreation();
+ * ac3.setType(
+ * ast.newArrayType(
+ * ast.newPrimitiveType(PrimitiveType.INT)));
+ * ArrayInitializer ai = ast.newArrayInitializer();
+ * ac3.setInitializer(ai);
+ * ai.expressions().add(ast.newNumberLiteral("1"));
+ * ai.expressions().add(ast.newNumberLiteral("2"));
+ * </pre>
+ * </code>
+ * </p>
+ *
+ * @return a new unparented array creation expression node
+ */
+ public ArrayCreation newArrayCreation() {
+ ArrayCreation result = new ArrayCreation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented class instance creation
+ * ("new") expression node owned by this AST. By default,
+ * there is no qualifying expression, no type parameters,
+ * an unspecified (but legal) type name, an empty list of
+ * arguments, and does not declare an anonymous class declaration.
+ *
+ * @return a new unparented class instance creation expression node
+ */
+ public ClassInstanceCreation newClassInstanceCreation() {
+ ClassInstanceCreation result = new ClassInstanceCreation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented anonymous class declaration
+ * node owned by this AST. By default, the body declaration list is empty.
+ *
+ * @return a new unparented anonymous class declaration node
+ */
+ public AnonymousClassDeclaration newAnonymousClassDeclaration() {
+ AnonymousClassDeclaration result = new AnonymousClassDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array initializer node
+ * owned by this AST. By default, the initializer has no expressions.
+ *
+ * @return a new unparented array initializer node
+ */
+ public ArrayInitializer newArrayInitializer() {
+ ArrayInitializer result = new ArrayInitializer(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented conditional expression node
+ * owned by this AST. By default, the condition and both expressions
+ * are unspecified (but legal).
+ *
+ * @return a new unparented array conditional expression node
+ */
+ public ConditionalExpression newConditionalExpression() {
+ ConditionalExpression result = new ConditionalExpression(this);
+ return result;
+ }
+
+//{ObjectTeams: factory methods for TSuperMessageSend, BaseConstructorMessageSend, BaseReference, BaseCallMessageSend
+ /**
+ * Creates and returns a new unparented "tsuper" expression node
+ * owned by this AST. By default, there is no qualifier.
+ *
+ * @return a new unparented "tsuper" expression node
+ */
+ public TSuperMessageSend newTSuperMessageSend()
+ {
+ return new TSuperMessageSend(this);
+ }
+
+ /**
+ * Creates and returns a new unparented "tsuper" statement node
+ * owned by this AST. By default, there is no qualifier.
+ *
+ * @return a new unparented "tsuper" expression node
+ */
+ public TSuperConstructorInvocation newTSuperConstructorInvocation()
+ {
+ return new TSuperConstructorInvocation(this);
+ }
+
+
+
+ /**
+ * Creates and returns a new unparented "base" callout node
+ * owned by this AST.
+ *
+ * @return a new unparented "base" callout node
+ */
+ public BaseCallMessageSend newBaseCallMessageSend()
+ {
+ return new BaseCallMessageSend(this);
+ }
+
+
+
+ /**
+ * Creates and returns a new unparented "base" constructor expression node
+ * owned by this AST.
+ *
+ * @return a new unparented "base" constructor expression node
+ */
+ public BaseConstructorInvocation newBaseConstructorInvocation()
+ {
+ return new BaseConstructorInvocation(this);
+ }
+//gbr,mkr}
+
+ //=============================== ANNOTATIONS ====================
+
+ /**
+ * Creates and returns a new unparented normal annotation node with
+ * an unspecified type name and an empty list of member value
+ * pairs.
+ *
+ * @return a new unparented normal annotation node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public NormalAnnotation newNormalAnnotation() {
+ NormalAnnotation result = new NormalAnnotation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented marker annotation node with
+ * an unspecified type name.
+ *
+ * @return a new unparented marker annotation node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public MarkerAnnotation newMarkerAnnotation() {
+ MarkerAnnotation result = new MarkerAnnotation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented single member annotation node with
+ * an unspecified type name and value.
+ *
+ * @return a new unparented single member annotation node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public SingleMemberAnnotation newSingleMemberAnnotation() {
+ SingleMemberAnnotation result = new SingleMemberAnnotation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented member value pair node with
+ * an unspecified member name and value.
+ *
+ * @return a new unparented member value pair node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public MemberValuePair newMemberValuePair() {
+ MemberValuePair result = new MemberValuePair(this);
+ return result;
+ }
+
+ /**
+ * Enables the recording of changes to the given compilation
+ * unit and its descendents. The compilation unit must have
+ * been created by <code>ASTParser</code> and still be in
+ * its original state. Once recording is on,
+ * arbitrary changes to the subtree rooted at the compilation
+ * unit are recorded internally. Once the modification has
+ * been completed, call <code>rewrite</code> to get an object
+ * representing the corresponding edits to the original
+ * source code string.
+ *
+ * @exception IllegalArgumentException if this compilation unit is
+ * marked as unmodifiable, or if this compilation unit has already
+ * been tampered with, or if recording has already been enabled,
+ * or if <code>root</code> is not owned by this AST
+ * @see CompilationUnit#recordModifications()
+ * @since 3.0
+ */
+ void recordModifications(CompilationUnit root) {
+ if(this.modificationCount != this.originalModificationCount) {
+ throw new IllegalArgumentException("AST is already modified"); //$NON-NLS-1$
+ } else if(this.rewriter != null) {
+ throw new IllegalArgumentException("AST modifications are already recorded"); //$NON-NLS-1$
+ } else if((root.getFlags() & ASTNode.PROTECT) != 0) {
+ throw new IllegalArgumentException("Root node is unmodifiable"); //$NON-NLS-1$
+ } else if(root.getAST() != this) {
+ throw new IllegalArgumentException("Root node is not owned by this ast"); //$NON-NLS-1$
+ }
+
+ this.rewriter = new InternalASTRewrite(root);
+ setEventHandler(this.rewriter);
+ }
+
+ /**
+ * Converts all modifications recorded into an object
+ * representing the corresponding text edits to the
+ * given document containing the original source
+ * code for the compilation unit that gave rise to
+ * this AST.
+ *
+ * @param document original document containing source code
+ * for the compilation unit
+ * @param options the table of formatter options
+ * (key type: <code>String</code>; value type: <code>String</code>);
+ * or <code>null</code> to use the standard global options
+ * {@link JavaCore#getOptions() JavaCore.getOptions()}.
+ * @return text edit object describing the changes to the
+ * document corresponding to the recorded AST modifications
+ * @exception IllegalArgumentException if the document passed is
+ * <code>null</code> or does not correspond to this AST
+ * @exception IllegalStateException if <code>recordModifications</code>
+ * was not called to enable recording
+ * @see CompilationUnit#rewrite(IDocument, Map)
+ * @since 3.0
+ */
+ TextEdit rewrite(IDocument document, Map options) {
+ if (document == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.rewriter == null) {
+ throw new IllegalStateException("Modifications record is not enabled"); //$NON-NLS-1$
+ }
+ return this.rewriter.rewriteAST(document, options);
+ }
+
+ /**
+ * Returns true if the ast tree was created with bindings, false otherwise
+ *
+ * @return true if the ast tree was created with bindings, false otherwise
+ * @since 3.3
+ */
+ public boolean hasResolvedBindings() {
+ return (this.bits & RESOLVED_BINDINGS) != 0;
+ }
+
+ /**
+ * Returns true if the ast tree was created with statements recovery, false otherwise
+ *
+ * @return true if the ast tree was created with statements recovery, false otherwise
+ * @since 3.3
+ */
+ public boolean hasStatementsRecovery() {
+ return (this.bits & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+ }
+
+ /**
+ * Returns true if the ast tree was created with bindings recovery, false otherwise
+ *
+ * @return true if the ast tree was created with bindings recovery, false otherwise
+ * @since 3.3
+ */
+ public boolean hasBindingsRecovery() {
+ return (this.bits & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0;
+ }
+
+ void setFlag(int newValue) {
+ this.bits |= newValue;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
new file mode 100644
index 000000000..a4ce40dc4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -0,0 +1,6318 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTConverter.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression;
+import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TsuperReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TypeAnchorReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.WithinStatement;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lowering;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
+import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
+
+/**
+ * Internal class for converting internal compiler ASTs into public ASTs.
+ */
+@SuppressWarnings("unchecked")
+class ASTConverter {
+
+ protected AST ast;
+ protected Comment[] commentsTable;
+ char[] compilationUnitSource;
+ int compilationUnitSourceLength;
+ protected DocCommentParser docParser;
+ // comments
+ protected boolean insideComments;
+ protected IProgressMonitor monitor;
+ protected Set pendingNameScopeResolution;
+ protected Set pendingThisExpressionScopeResolution;
+ protected boolean resolveBindings;
+ Scanner scanner;
+ private DefaultCommentMapper commentMapper;
+//{ObjectTeams: one more configuration option:
+ private boolean includeRoleFiles= false;
+// SH}
+
+ public ASTConverter(Map options, boolean resolveBindings, IProgressMonitor monitor) {
+ this.resolveBindings = resolveBindings;
+ Object sourceModeSetting = options.get(JavaCore.COMPILER_SOURCE);
+ long sourceLevel = CompilerOptions.versionToJdkLevel(sourceModeSetting);
+ if (sourceLevel == 0) {
+ // unknown sourceModeSetting
+ sourceLevel = ClassFileConstants.JDK1_3;
+ }
+//{ObjectTeams: one more configuration option:
+ Object roleFileOption= options.get(JavaCore.AST_INCLUDES_ROLE_FILES);
+ if (roleFileOption != null)
+ includeRoleFiles= JavaCore.ENABLED.equals(roleFileOption);
+// SH}
+
+ this.scanner = new Scanner(
+ true /*comment*/,
+ false /*whitespace*/,
+ false /*nls*/,
+ sourceLevel /*sourceLevel*/,
+ null /*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ this.monitor = monitor;
+ this.insideComments = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_DOC_COMMENT_SUPPORT));
+//{ObjectTeams: initialize scanner mode from options
+ Object option = options.get(JavaCore.COMPILER_OPT_SCOPED_KEYWORDS);
+ if (option != null)
+ this.scanner.parseOTJonly = JavaCore.DISABLED.equals(option);
+// SH}
+ }
+
+ protected void adjustSourcePositionsForParent(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+ int start = expression.sourceStart;
+ int end = expression.sourceEnd;
+ int leftParentCount = 1;
+ int rightParentCount = 0;
+ this.scanner.resetTo(start, end);
+ try {
+ int token = this.scanner.getNextToken();
+ expression.sourceStart = this.scanner.currentPosition;
+ boolean stop = false;
+ while (!stop && ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)) {
+ switch(token) {
+ case TerminalTokens.TokenNameLPAREN:
+ leftParentCount++;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ rightParentCount++;
+ if (rightParentCount == leftParentCount) {
+ // we found the matching parenthesis
+ stop = true;
+ }
+ }
+ }
+ expression.sourceEnd = this.scanner.startPosition - 1;
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration, AbstractTypeDeclaration typeDecl) {
+ // add body declaration in the lexical order
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = typeDeclaration.memberTypes;
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = typeDeclaration.fields;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+
+ int fieldsLength = fields == null? 0 : fields.length;
+ int methodsLength = methods == null? 0 : methods.length;
+ int membersLength = members == null ? 0 : members.length;
+ int fieldsIndex = 0;
+ int methodsIndex = 0;
+ int membersIndex = 0;
+
+//{ObjectTeams: more setup before the loop:
+ // members were sorted by inheritance, restore lexical order:
+ if (typeDeclaration.isTeam() && members != null)
+ Arrays.sort(members, new Comparator<org.eclipse.jdt.internal.compiler.ast.TypeDeclaration>() {
+ public int compare(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration t1,
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration t2) {
+ return (t1.sourceStart < t2.sourceStart) ? -1 : 1;
+ }});
+
+ // method mapping declarations (callins, callouts)
+ AbstractMethodMappingDeclaration[] callinCallouts = typeDeclaration.callinCallouts;
+ int methodMappingsLength = callinCallouts == null ? 0 : callinCallouts.length;
+ int methodMappingsIndex = 0;
+//gbr+SH}
+
+ while ((fieldsIndex < fieldsLength)
+ || (membersIndex < membersLength)
+ || (methodsIndex < methodsLength)
+//{ObjectTeams
+ || (methodMappingsIndex < methodMappingsLength)) {
+//gbr}
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+//{ObjectTeams
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration nextMethodMappingDeclaration = null;
+//gbr}
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldsIndex < fieldsLength) {
+ nextFieldDeclaration = fields[fieldsIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodsIndex < methodsLength) {
+ nextMethodDeclaration = methods[methodsIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (membersIndex < membersLength) {
+ nextMemberDeclaration = members[membersIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+//{ObjectTeams: case added for method mappings
+ if (methodMappingsIndex < methodMappingsLength)
+ {
+ nextMethodMappingDeclaration = callinCallouts[methodMappingsIndex];
+ if (nextMethodMappingDeclaration.sourceStart < position)
+ {
+ position = nextMethodMappingDeclaration.sourceStart;
+ nextDeclarationType = 3; // METHOD_MAPPING
+ }
+ }
+//gbr}
+ switch (nextDeclarationType) {
+ case 0 :
+ if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ typeDecl.bodyDeclarations().add(convert(nextFieldDeclaration));
+ } else {
+ checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, typeDecl.bodyDeclarations());
+ }
+ fieldsIndex++;
+ break;
+ case 1 :
+ methodsIndex++;
+//{ObjectTeams: skip guard predicates which come as methods (are converted via field TypeDeclaration.predicate)
+ if (nextMethodDeclaration instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration) {
+ break;
+ }
+// SH}
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()
+//{ObjectTeams: ignore generated and copied method declarations
+ && !nextMethodDeclaration.isGenerated
+ && !nextMethodDeclaration.isCopied)
+//jwl}
+ {
+ typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+//{ObjectTeams: convert reused abstract method declaration
+ else if (isReusedAbstractMethodDeclaration(typeDeclaration,nextMethodDeclaration))
+ {
+ typeDecl.bodyDeclarations().add(convertReusedAbstractMethodDeclaration(nextMethodDeclaration));
+ }
+//jsv}
+ break;
+ case 2 :
+ membersIndex++;
+//{ObjectTeams: skip generated members and role files when visited via enclosing team - conditionally:
+ if ( nextMemberDeclaration.isGenerated
+ || Flags.isSynthetic(nextMemberDeclaration.modifiers))
+ continue;
+ if (!includeRoleFiles && nextMemberDeclaration.isRoleFile())
+ continue;
+// SH, jwl}
+ ASTNode node = convert(nextMemberDeclaration);
+ if (node == null) {
+ typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+ } else {
+ typeDecl.bodyDeclarations().add(node);
+ }
+//{ObjectTeams: case statement added for method mappings
+ break;
+ case 3 :
+ methodMappingsIndex++;
+ if (nextMethodMappingDeclaration != null)
+ {
+ typeDecl.bodyDeclarations().add(convert(nextMethodMappingDeclaration));
+ }
+//gbr}
+ }
+ }
+ // Convert javadoc
+ convert(typeDeclaration.javadoc, typeDecl);
+ }
+
+ protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enumDeclaration2, EnumDeclaration enumDeclaration) {
+ // add body declaration in the lexical order
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = enumDeclaration2.memberTypes;
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = enumDeclaration2.fields;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = enumDeclaration2.methods;
+
+ int fieldsLength = fields == null? 0 : fields.length;
+ int methodsLength = methods == null? 0 : methods.length;
+ int membersLength = members == null ? 0 : members.length;
+ int fieldsIndex = 0;
+ int methodsIndex = 0;
+ int membersIndex = 0;
+
+ while ((fieldsIndex < fieldsLength)
+ || (membersIndex < membersLength)
+ || (methodsIndex < methodsLength)) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldsIndex < fieldsLength) {
+ nextFieldDeclaration = fields[fieldsIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodsIndex < methodsLength) {
+ nextMethodDeclaration = methods[methodsIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (membersIndex < membersLength) {
+ nextMemberDeclaration = members[membersIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ enumDeclaration.enumConstants().add(convert(nextFieldDeclaration));
+ } else {
+ checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, enumDeclaration.bodyDeclarations());
+ }
+ fieldsIndex++;
+ break;
+ case 1 :
+ methodsIndex++;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+ enumDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+ break;
+ case 2 :
+ membersIndex++;
+ enumDeclaration.bodyDeclarations().add(convert(nextMemberDeclaration));
+ break;
+ }
+ }
+ convert(enumDeclaration2.javadoc, enumDeclaration);
+ }
+
+ protected void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
+ // add body declaration in the lexical order
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
+
+ int fieldsLength = fields == null? 0 : fields.length;
+ int methodsLength = methods == null? 0 : methods.length;
+ int membersLength = members == null ? 0 : members.length;
+ int fieldsIndex = 0;
+ int methodsIndex = 0;
+ int membersIndex = 0;
+
+ while ((fieldsIndex < fieldsLength)
+ || (membersIndex < membersLength)
+ || (methodsIndex < methodsLength)) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldsIndex < fieldsLength) {
+ nextFieldDeclaration = fields[fieldsIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodsIndex < methodsLength) {
+ nextMethodDeclaration = methods[methodsIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (membersIndex < membersLength) {
+ nextMemberDeclaration = members[membersIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ anonymousClassDeclaration.bodyDeclarations().add(convert(nextFieldDeclaration));
+ } else {
+ checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, anonymousClassDeclaration.bodyDeclarations());
+ }
+ fieldsIndex++;
+ break;
+ case 1 :
+ methodsIndex++;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()
+//{ObjectTeams: ignore generated and copied method declarations
+ && !nextMethodDeclaration.isGenerated
+ && !nextMethodDeclaration.isCopied)
+ {
+//jwl})
+ anonymousClassDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+//{ObjectTeams: convert reused abstract method declaration
+ else if (isReusedAbstractMethodDeclaration(expression, nextMethodDeclaration))
+ {
+ anonymousClassDeclaration.bodyDeclarations().add(convertReusedAbstractMethodDeclaration(nextMethodDeclaration));
+ }
+//jsv}
+ break;
+ case 2 :
+ membersIndex++;
+ ASTNode node = convert(nextMemberDeclaration);
+ if (node == null) {
+ anonymousClassDeclaration.setFlags(anonymousClassDeclaration.getFlags() | ASTNode.MALFORMED);
+ } else {
+//{ObjectTeams: ignore generated role interfaces
+ if (!Flags.isSynthetic(nextMemberDeclaration.modifiers))
+// jwl}
+
+ anonymousClassDeclaration.bodyDeclarations().add(node);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param compilationUnit
+ * @param comments
+ */
+ void buildCommentsTable(CompilationUnit compilationUnit, int[][] comments) {
+ // Build comment table
+ this.commentsTable = new Comment[comments.length];
+ int nbr = 0;
+ for (int i = 0; i < comments.length; i++) {
+ Comment comment = createComment(comments[i]);
+ if (comment != null) {
+ comment.setAlternateRoot(compilationUnit);
+ this.commentsTable[nbr++] = comment;
+ }
+ }
+ // Resize table if necessary
+ if (nbr<comments.length) {
+ Comment[] newCommentsTable = new Comment[nbr];
+ System.arraycopy(this.commentsTable, 0, newCommentsTable, 0, nbr);
+ this.commentsTable = newCommentsTable;
+ }
+ compilationUnit.setCommentTable(this.commentsTable);
+ }
+
+ protected void checkAndAddMultipleFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields, int index, List bodyDeclarations) {
+//{ObjecTeams: ignore generated field declarations
+ if (Flags.isSynthetic(fields[index].modifiers) || fields[index].copyInheritanceSrc != null)
+ {
+ return;
+ }
+//jwl}
+ if (fields[index] instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+ org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.jdt.internal.compiler.ast.Initializer) fields[index];
+ Initializer initializer = new Initializer(this.ast);
+ initializer.setBody(convert(oldInitializer.block));
+ setModifiers(initializer, oldInitializer);
+ initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+ // The javadoc comment is now got from list store in compilation unit declaration
+ convert(oldInitializer.javadoc, initializer);
+ bodyDeclarations.add(initializer);
+ return;
+ }
+ if (index > 0 && fields[index - 1].declarationSourceStart == fields[index].declarationSourceStart) {
+ // we have a multiple field declaration
+ // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclarations.get(bodyDeclarations.size() - 1);
+ fieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fields[index]));
+ } else {
+ // we can create a new FieldDeclaration
+ bodyDeclarations.add(convertToFieldDeclaration(fields[index]));
+ }
+ }
+
+ protected void checkAndAddMultipleLocalDeclaration(org.eclipse.jdt.internal.compiler.ast.Statement[] stmts, int index, List blockStatements) {
+ if (index > 0
+ && stmts[index - 1] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration
+//{ObjectTeams: ignore generated variable declarations within blocks
+ && !((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]).isGenerated) {
+//jwl}
+ org.eclipse.jdt.internal.compiler.ast.LocalDeclaration local1 = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) stmts[index - 1];
+ org.eclipse.jdt.internal.compiler.ast.LocalDeclaration local2 = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) stmts[index];
+ if (local1.declarationSourceStart == local2.declarationSourceStart) {
+ // we have a multiple local declarations
+ // We retrieve the existing VariableDeclarationStatement to add the new VariableDeclarationFragment
+ VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) blockStatements.get(blockStatements.size() - 1);
+ variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+ } else {
+ // we can create a new FieldDeclaration
+ blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+ }
+ } else {
+ // we can create a new FieldDeclaration
+ blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+ }
+ }
+
+ protected void checkCanceled() {
+ if (this.monitor != null && this.monitor.isCanceled())
+ throw new OperationCanceledException();
+ }
+
+ protected void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
+ ArrayType array = arrayType;
+ int dimensions = array.getDimensions();
+ for (int i = 0; i < dimensions; i++) {
+ Type componentType = array.getComponentType();
+ this.recordNodes(componentType, astNode);
+ if (componentType.isArrayType()) {
+ array = (ArrayType) componentType;
+ }
+ }
+ }
+
+ public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
+ checkCanceled();
+ if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) methodDeclaration);
+ }
+ MethodDeclaration methodDecl = new MethodDeclaration(this.ast);
+ setModifiers(methodDecl, methodDeclaration);
+ boolean isConstructor = methodDeclaration.isConstructor();
+ methodDecl.setConstructor(isConstructor);
+ final SimpleName methodName = new SimpleName(this.ast);
+ methodName.internalSetIdentifier(new String(methodDeclaration.selector));
+ int start = methodDeclaration.sourceStart;
+ int end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd);
+ methodName.setSourceRange(start, end - start + 1);
+ methodDecl.setName(methodName);
+ org.eclipse.jdt.internal.compiler.ast.TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+ int methodHeaderEnd = methodDeclaration.sourceEnd;
+ int thrownExceptionsLength = thrownExceptions == null ? 0 : thrownExceptions.length;
+ if (thrownExceptionsLength > 0) {
+ Name thrownException;
+ int i = 0;
+ do {
+ thrownException = convert(thrownExceptions[i++]);
+ methodDecl.thrownExceptions().add(thrownException);
+ } while (i < thrownExceptionsLength);
+ methodHeaderEnd = thrownException.getStartPosition() + thrownException.getLength();
+ }
+//{ObjectTeams:
+/* orig:
+ org.eclipse.jdt.internal.compiler.ast.Argument[] parameters = methodDeclaration.arguments;
+ :giro */
+ org.eclipse.jdt.internal.compiler.ast.Argument[] parameters = MethodSignatureEnhancer.getSourceArguments(methodDeclaration);
+// SH}
+ int parametersLength = parameters == null ? 0 : parameters.length;
+ if (parametersLength > 0) {
+ SingleVariableDeclaration parameter;
+ int i = 0;
+ do {
+ parameter = convert(parameters[i++]);
+ methodDecl.parameters().add(parameter);
+ } while (i < parametersLength);
+ if (thrownExceptionsLength == 0) {
+ methodHeaderEnd = parameter.getStartPosition() + parameter.getLength();
+ }
+ }
+ org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null;
+ if (isConstructor) {
+ org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration;
+ explicitConstructorCall = constructorDeclaration.constructorCall;
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ // set the return type to VOID
+ PrimitiveType returnType = new PrimitiveType(this.ast);
+ returnType.setPrimitiveTypeCode(PrimitiveType.VOID);
+ returnType.setSourceRange(methodDeclaration.sourceStart, 0);
+ methodDecl.internalSetReturnType(returnType);
+ break;
+ case AST.JLS3 :
+ methodDecl.setReturnType2(null);
+ }
+ } else if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) methodDeclaration;
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = method.returnType;
+ if (typeReference != null) {
+ Type returnType = convertType(typeReference);
+ // get the positions of the right parenthesis
+ int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd);
+ int extraDimensions = retrieveExtraDimension(rightParenthesisPosition, method.bodyEnd);
+ methodDecl.setExtraDimensions(extraDimensions);
+ setTypeForMethodDeclaration(methodDecl, returnType, extraDimensions);
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ methodDecl.setReturnType2(null);
+ }
+ }
+//{ObjectTeams:
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration guard = method.predicate;
+ if (guard != null)
+ methodDecl.setGuardPredicate(convertGuardPredicate(guard));
+// SH}
+ }
+ int declarationSourceStart = methodDeclaration.declarationSourceStart;
+ int declarationSourceEnd = methodDeclaration.bodyEnd;
+//{ObjectTeams: adjust positions for callout wrappers reusing a source method:
+ if (declarationSourceEnd < declarationSourceStart) {
+ assert (methodDeclaration.isCalloutWrapper() && methodDeclaration.isReusingSourceMethod): "should only happen for reused source methods"; //$NON-NLS-1$
+ // declarationSourceStart is pointing to the abstract method declaration,
+ // here we need positions for the generated wrapper which are derived from the callout mapping:
+ declarationSourceStart= methodDeclaration.bodyStart;
+ }
+// SH}
+ methodDecl.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+ int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDeclaration.bodyEnd + 1, methodDeclaration.declarationSourceEnd);
+ if (closingPosition != -1) {
+ int startPosition = methodDecl.getStartPosition();
+ methodDecl.setSourceRange(startPosition, closingPosition - startPosition + 1);
+
+ org.eclipse.jdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
+
+ start = retrieveStartBlockPosition(methodHeaderEnd, methodDeclaration.bodyStart);
+ if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start
+ end = retrieveRightBrace(methodDeclaration.bodyEnd, methodDeclaration.declarationSourceEnd);
+ Block block = null;
+ if (start != -1 && end != -1) {
+ /*
+ * start or end can be equal to -1 if we have an interface's method.
+ */
+ block = new Block(this.ast);
+ block.setSourceRange(start, closingPosition - start + 1);
+ methodDecl.setBody(block);
+ }
+ if (block != null && (statements != null || explicitConstructorCall != null)) {
+ if (explicitConstructorCall != null && explicitConstructorCall.accessMode != org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall.ImplicitSuper) {
+ block.statements().add(convert(explicitConstructorCall));
+ }
+ int statementsLength = statements == null ? 0 : statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+//{ObjectTeams: ignore generated local declarations within method declarations
+ if ((statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)
+ && ((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)statements[i]).isGenerated) {
+ continue;
+ }
+//jwl}
+ if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+ checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+ } else {
+ final Statement statement = convert(statements[i]);
+ if (statement != null) {
+ block.statements().add(statement);
+ }
+ }
+ }
+ }
+ if (block != null && (Modifier.isAbstract(methodDecl.getModifiers()) || Modifier.isNative(methodDecl.getModifiers()))) {
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ } else {
+ // syntax error in this method declaration
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) {
+ start = retrieveStartBlockPosition(methodHeaderEnd, declarationSourceEnd);
+ if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start
+ end = methodDeclaration.bodyEnd;
+ // try to get the best end position
+ CategorizedProblem[] problems = methodDeclaration.compilationResult().problems;
+ if (problems != null) {
+ for (int i = 0, max = methodDeclaration.compilationResult().problemCount; i < max; i++) {
+ CategorizedProblem currentProblem = problems[i];
+ if (currentProblem.getSourceStart() == start && currentProblem.getID() == IProblem.ParsingErrorInsertToComplete) {
+ end = currentProblem.getSourceEnd();
+ break;
+ }
+ }
+ }
+ int startPosition = methodDecl.getStartPosition();
+ methodDecl.setSourceRange(startPosition, end - startPosition + 1);
+ if (start != -1 && end != -1) {
+ /*
+ * start or end can be equal to -1 if we have an interface's method.
+ */
+ Block block = new Block(this.ast);
+ block.setSourceRange(start, end - start + 1);
+ methodDecl.setBody(block);
+ }
+ }
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = methodDeclaration.typeParameters();
+ if (typeParameters != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = typeParameters.length; i < max; i++) {
+ methodDecl.typeParameters().add(convert(typeParameters[i]));
+ }
+ }
+ }
+
+ // The javadoc comment is now got from list store in compilation unit declaration
+ convert(methodDeclaration.javadoc, methodDecl);
+ if (this.resolveBindings) {
+ recordNodes(methodDecl, methodDeclaration);
+ recordNodes(methodName, methodDeclaration);
+ methodDecl.resolveBinding();
+ }
+ return methodDecl;
+ }
+
+//{ObjectTeams: convert method for OT-specific internal type AbstractMethodMappingDeclaration
+ public org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration convert(
+ AbstractMethodMappingDeclaration abstractMethodMapping)
+ {
+ if (abstractMethodMapping instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration)
+ {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration)abstractMethodMapping);
+ }
+ if (abstractMethodMapping instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration)
+ {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration)abstractMethodMapping);
+ }
+ throw new IllegalArgumentException("There does not exist a method binding of type" + abstractMethodMapping.getClass()); //$NON-NLS-1$
+ }
+//gbr}
+// {ObjectTeams: convert methods for OT-specific internal types CallinMappingDeclaration
+// and CalloutMappingDeclaration
+ public CallinMappingDeclaration convert(
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration callinMapping) {
+ org.eclipse.jdt.core.dom.CallinMappingDeclaration result = this.ast
+ .newCallinMappingDeclaration();
+
+ // annotations
+ setModifiers(result, callinMapping);
+
+ // name
+ if (callinMapping.hasName()) {
+ SimpleName labelName = ast.newSimpleName(String.valueOf(callinMapping.name));
+ labelName.setSourceRange(callinMapping.sourceStart, callinMapping.sourceEnd - callinMapping.sourceStart + 1);
+ result.setName(labelName);
+ }
+
+ // left side, role method
+ if (callinMapping.roleMethodSpec != null)
+ result.setRoleMappingElement(convert(callinMapping.roleMethodSpec));
+
+ // right side, base methods
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec[] baseMethodSpecs = callinMapping.baseMethodSpecs;
+ int len = (baseMethodSpecs != null) ? baseMethodSpecs.length : 0;
+ for (int idx = 0; idx < len; idx++) {
+ if (baseMethodSpecs[idx].selector.length > 0)
+ result.getBaseMappingElements().add(convert(baseMethodSpecs[idx]));
+ }
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration guard = callinMapping.predicate;
+ if (guard != null)
+ result.setGuardPredicate(convertGuardPredicate(guard));
+
+
+ // with { ... }, parameter mappings
+ if (callinMapping.mappings != null) {
+ int mappingsLength = callinMapping.mappings.length;
+ for (int idx = 0; idx < mappingsLength; idx++) {
+ result.getParameterMappings().add(
+ convert(callinMapping.mappings[idx]));
+ }
+ }
+
+ // callin modifier: after, before, replace
+ ModifierKeyword keyword = null;
+ int modifierStart = callinMapping.modifierStart;
+ int modifierLength = callinMapping.modifierEnd- modifierStart + 1;
+ switch (callinMapping.callinModifier) {
+ case TerminalTokens.TokenNamebefore:
+ keyword = ModifierKeyword.BEFORE_KEYWORD;
+ break;
+ case TerminalTokens.TokenNameafter:
+ keyword = ModifierKeyword.AFTER_KEYWORD;
+ break;
+ case TerminalTokens.TokenNamereplace:
+ keyword = ModifierKeyword.REPLACE_KEYWORD;
+ break;
+ default:
+ keyword = ModifierKeyword.MISSING_KEYWORD;
+ modifierStart= retrieveBINDINPosition(callinMapping.sourceEnd, callinMapping.declarationSourceEnd);
+ if (modifierStart == -1)
+ modifierStart= callinMapping.baseDeclarationSourceStart()-1;
+ else
+ modifierStart += 2; // skip "<-"
+ modifierLength= 0;
+ break;
+ }
+ MethodBindingOperator bindingOperator = this.ast.newMethodBindingOperator(keyword, MethodBindingOperator.KIND_CALLIN);
+ bindingOperator.setSourceRange(callinMapping.bindingTokenStart, callinMapping.modifierEnd-callinMapping.bindingTokenStart+1);
+ bindingOperator.bindingModifier().setSourceRange(modifierStart, modifierLength);
+ result.setBindingOperator(bindingOperator);
+
+ result.setSourceRange(callinMapping.declarationSourceStart,
+ callinMapping.declarationSourceEnd - callinMapping.declarationSourceStart + 1);
+
+ convert(callinMapping.javadoc, result);
+
+ if (this.resolveBindings) {
+ this.recordNodes(result, callinMapping);
+ }
+ return result;
+ }
+
+ public org.eclipse.jdt.core.dom.CalloutMappingDeclaration convert(
+ CalloutMappingDeclaration calloutMapping)
+ {
+ org.eclipse.jdt.core.dom.CalloutMappingDeclaration result = this.ast
+ .newCalloutMappingDeclaration();
+
+ // annotations
+ setModifiers(result, calloutMapping);
+
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec roleMethodSpec = calloutMapping.roleMethodSpec;
+ if (roleMethodSpec != null) {
+ org.eclipse.jdt.core.dom.MethodMappingElement leftMethodSpec = convert(roleMethodSpec);
+ result.setRoleMappingElement(leftMethodSpec);
+ }
+ // possible types for calloutMapping.baseMethodSpec: MethodSpec,
+ // FieldAccesSpec
+ if (calloutMapping.baseMethodSpec != null && calloutMapping.baseMethodSpec.selector.length > 0) {
+ result.setBaseMappingElement(convert(calloutMapping.baseMethodSpec));
+ if (calloutMapping.isCalloutToField()) {
+ FieldAccessSpec fieldAccessSpec = (FieldAccessSpec)calloutMapping.baseMethodSpec;
+ result.bindingOperator().setBindingModifier(fieldAccessSpec.isSetter() ? Modifier.OT_SET_CALLOUT : Modifier.OT_GET_CALLOUT);
+ }
+ } else {
+ result.setBaseMappingElement(null); // mark as initialized
+ }
+
+ // convert parameter mappings
+ if (calloutMapping.mappings != null) {
+ for (int idx = 0; idx < calloutMapping.mappings.length; idx++) {
+ result.getParameterMappings().add(idx,
+ convert(calloutMapping.mappings[idx]));
+ }
+ }
+
+ result.setSourceRange(calloutMapping.declarationSourceStart,
+ calloutMapping.declarationSourceEnd - calloutMapping.declarationSourceStart + 1);
+
+ convert(calloutMapping.javadoc, result);
+
+ if (this.resolveBindings) {
+ this.recordNodes(result, calloutMapping);
+ result.resolveBinding();
+ }
+ result.setSignatureFlag(calloutMapping.hasSignature);
+
+ // binding operator (kind and modifier)
+ ModifierKeyword keyword = null;
+ int modifierStart = calloutMapping.modifierStart;
+ int modifierLength = calloutMapping.modifierEnd - modifierStart + 1;
+ if (calloutMapping.baseMethodSpec instanceof FieldAccessSpec) {
+ if (((FieldAccessSpec)calloutMapping.baseMethodSpec).isSetter())
+ keyword = ModifierKeyword.SET_KEYWORD;
+ else
+ keyword = ModifierKeyword.GET_KEYWORD;
+ }
+ int calloutKind = calloutMapping.isCalloutOverride() ? MethodBindingOperator.KIND_CALLOUT_OVERRIDE : MethodBindingOperator.KIND_CALLOUT;
+
+ MethodBindingOperator bindingOperator = this.ast.newMethodBindingOperator(keyword, calloutKind);
+ bindingOperator.setSourceRange(calloutMapping.bindingTokenStart, calloutMapping.modifierEnd-calloutMapping.bindingTokenStart+1);
+ if (keyword != null)
+ bindingOperator.bindingModifier().setSourceRange(modifierStart, modifierLength);
+ result.setBindingOperator(bindingOperator);
+
+ return result;
+ }
+//gbr}
+
+//{ObjectTeams: convert method for OT-specific internal type ParameterMapping
+ @SuppressWarnings("nls")
+ public org.eclipse.jdt.core.dom.ParameterMapping convert(
+ ParameterMapping parameterMapping) {
+ org.eclipse.jdt.core.dom.ParameterMapping result = this.ast
+ .newParameterMapping();
+
+ result
+ .setSourceRange(
+ parameterMapping.sourceStart,
+ (parameterMapping.sourceEnd - parameterMapping.sourceStart) + 1);
+
+ result.setExpression(convert(parameterMapping.expression));
+
+ if (parameterMapping.direction == TerminalTokens.TokenNameBINDIN)
+ result.setDirection("<-");
+
+ if (parameterMapping.direction == TerminalTokens.TokenNameBINDOUT)
+ result.setDirection("->");
+
+ result.setIdentifier(convert(parameterMapping.ident));
+
+ if (new String(parameterMapping.ident.token).equals("result"))
+ result.setResultFlag(true);
+ else
+ result.setResultFlag(false);
+
+ return result;
+ }
+
+ // jsv}
+
+// {ObjectTeams: convert method for OT-specific internal type
+ // ParameterMapping
+ public org.eclipse.jdt.core.dom.FieldAccessSpec convert(
+ FieldAccessSpec fieldAccessSpec) {
+ org.eclipse.jdt.core.dom.FieldAccessSpec result = this.ast
+ .newFieldAccessSpec();
+
+ result.setSourceRange(fieldAccessSpec.declarationSourceStart,
+ fieldAccessSpec.declarationSourceEnd - fieldAccessSpec.declarationSourceStart + 1);
+
+ result.setSignatureFlag(fieldAccessSpec.hasSignature);
+
+ String[] tokens = (new String(fieldAccessSpec.selector)).split("\\" //$NON-NLS-1$
+ + IOTConstants.JAVA_SEPARATOR);
+ String realName = tokens[tokens.length - 1];
+ SimpleName fieldName = this.ast.newSimpleName(realName);
+ int start = fieldAccessSpec.sourceStart;
+ int end = retrieveEndOfElementTypeNamePosition(start,
+ fieldAccessSpec.sourceEnd);
+ fieldName.setSourceRange(start, end - start + 1);
+ result.setName(fieldName);
+
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = fieldAccessSpec.declaredType();
+ if (typeReference != null) {
+ Type fieldType = convertType(typeReference);
+ result.setFieldType(fieldType);
+ }
+
+ if (this.resolveBindings) {
+ recordNodes(result, fieldAccessSpec);
+ recordNodes(fieldName, fieldAccessSpec);
+ }
+
+ return result;
+ }
+
+ // jsv}
+
+// {ObjectTeams: convert method for OT-specific internal type
+ // MethodMappingElement
+ public MethodMappingElement convert(MethodSpec methodSpec) {
+ if (methodSpec instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec) {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec) methodSpec);
+ }
+
+ org.eclipse.jdt.core.dom.MethodSpec result = this.ast.newMethodSpec();
+
+ SimpleName methodName = this.ast.newSimpleName(new String(methodSpec.selector));
+ int start = methodSpec.sourceStart;
+ int end = retrieveEndOfElementTypeNamePosition(start, methodSpec.sourceEnd);
+ methodName.setSourceRange(start, end - start + 1);
+ result.setName(methodName);
+
+ if (methodSpec.hasSignature) {
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = methodSpec.returnType;
+ if (typeReference != null) {
+ Type returnType = convertType(typeReference);
+ if(result.getAST().apiLevel() == AST.JLS3)
+ result.setReturnType2(returnType);
+ else
+ result.setReturnType(returnType);
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.Argument[] parameters = methodSpec.arguments;
+ if (parameters != null) {
+ int parametersLength = parameters.length;
+ for (int idx = 0; idx < parametersLength; idx++) {
+ result.parameters().add(convert(parameters[idx]));
+ }
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = methodSpec.typeParameters;
+ if (typeParameters != null)
+ if (this.ast.apiLevel == AST.JLS3)
+ for (int i = 0, max = typeParameters.length; i < max; i++)
+ result.typeParameters().add(convert(typeParameters[i]));
+ }
+
+ result.setSourceRange(methodSpec.declarationSourceStart,
+ methodSpec.declarationSourceEnd
+ - methodSpec.declarationSourceStart + 1);
+
+ result.setSignatureFlag(methodSpec.hasSignature);
+ result.setCovariantReturnFlag(methodSpec.covariantReturn);
+
+ if (this.resolveBindings) {
+ recordNodes(result, methodSpec);
+ recordNodes(methodName, methodSpec);
+ }
+
+ return result;
+ }
+//gbr}
+
+
+ public ClassInstanceCreation convert(org.eclipse.jdt.internal.compiler.ast.AllocationExpression expression) {
+ ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, expression);
+ }
+ if (expression.typeArguments != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = expression.typeArguments.length; i < max; i++) {
+ classInstanceCreation.typeArguments().add(convertType(expression.typeArguments[i]));
+ }
+ }
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ classInstanceCreation.internalSetName(convert(expression.type));
+ break;
+ case AST.JLS3 :
+ classInstanceCreation.setType(convertType(expression.type));
+ }
+ classInstanceCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ classInstanceCreation.arguments().add(convert(arguments[i]));
+ }
+ }
+ removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+ return classInstanceCreation;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ final int expressionOperatorID = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ if (expression.left instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.jdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.jdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+ private AnnotationTypeDeclaration convertToAnnotationDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ checkCanceled();
+ if (this.scanner.sourceLevel < ClassFileConstants.JDK1_5) return null;
+ AnnotationTypeDeclaration typeDecl = this.ast.newAnnotationTypeDeclaration();
+ setModifiers(typeDecl, typeDeclaration);
+ final SimpleName typeName = new SimpleName(this.ast);
+ typeName.internalSetIdentifier(new String(typeDeclaration.name));
+ typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+ typeDecl.setName(typeName);
+ typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+
+ buildBodyDeclarations(typeDeclaration, typeDecl);
+ // The javadoc comment is now got from list store in compilation unit declaration
+ if (this.resolveBindings) {
+ recordNodes(typeDecl, typeDeclaration);
+ recordNodes(typeName, typeDeclaration);
+ typeDecl.resolveBinding();
+ }
+ return typeDecl;
+ }
+
+ public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+ checkCanceled();
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ return null;
+ }
+ AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration2 = new AnnotationTypeMemberDeclaration(this.ast);
+ setModifiers(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+ final SimpleName methodName = new SimpleName(this.ast);
+ methodName.internalSetIdentifier(new String(annotationTypeMemberDeclaration.selector));
+ int start = annotationTypeMemberDeclaration.sourceStart;
+ int end = retrieveIdentifierEndPosition(start, annotationTypeMemberDeclaration.sourceEnd);
+ methodName.setSourceRange(start, end - start + 1);
+ annotationTypeMemberDeclaration2.setName(methodName);
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = annotationTypeMemberDeclaration.returnType;
+ if (typeReference != null) {
+ Type returnType = convertType(typeReference);
+ setTypeForMethodDeclaration(annotationTypeMemberDeclaration2, returnType, 0);
+ }
+ int declarationSourceStart = annotationTypeMemberDeclaration.declarationSourceStart;
+ int declarationSourceEnd = annotationTypeMemberDeclaration.bodyEnd;
+ annotationTypeMemberDeclaration2.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+ // The javadoc comment is now got from list store in compilation unit declaration
+ convert(annotationTypeMemberDeclaration.javadoc, annotationTypeMemberDeclaration2);
+ org.eclipse.jdt.internal.compiler.ast.Expression memberValue = annotationTypeMemberDeclaration.defaultValue;
+ if (memberValue != null) {
+ annotationTypeMemberDeclaration2.setDefault(convert(memberValue));
+ }
+ if (this.resolveBindings) {
+ recordNodes(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+ recordNodes(methodName, annotationTypeMemberDeclaration);
+ annotationTypeMemberDeclaration2.resolveBinding();
+ }
+ return annotationTypeMemberDeclaration2;
+ }
+
+ public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.Argument argument) {
+ SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+ setModifiers(variableDecl, argument);
+//{ObjectTeams: we have to check the variable name e.g. in a LiftingType
+ String[] tokens = (new String(argument.name)).split("\\"+IOTConstants.JAVA_SEPARATOR); //$NON-NLS-1$
+ String realName = tokens[tokens.length-1];
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(realName);
+/* orig:
+ name.internalSetIdentifier(new String(argument.name));
+ :giro */
+//jsv} Original:
+ int start = argument.sourceStart;
+ int nameEnd = argument.sourceEnd;
+ name.setSourceRange(start, nameEnd - start + 1);
+ variableDecl.setName(name);
+ final int typeSourceEnd = argument.type.sourceEnd;
+ final int extraDimensions = retrieveExtraDimension(nameEnd + 1, typeSourceEnd);
+ variableDecl.setExtraDimensions(extraDimensions);
+ final boolean isVarArgs = argument.isVarArgs();
+ if (isVarArgs && extraDimensions == 0) {
+ // remove the ellipsis from the type source end
+ argument.type.sourceEnd = retrieveEllipsisStartPosition(argument.type.sourceStart, typeSourceEnd);
+ }
+ Type type = convertType(argument.type);
+ int typeEnd = type.getStartPosition() + type.getLength() - 1;
+ int rightEnd = Math.max(typeEnd, argument.declarationSourceEnd);
+ /*
+ * There is extra work to do to set the proper type positions
+ * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+ */
+ if (isVarArgs) {
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
+ if (extraDimensions != 0) {
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ } else {
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+ }
+ variableDecl.setSourceRange(argument.declarationSourceStart, rightEnd - argument.declarationSourceStart + 1);
+
+ if (isVarArgs) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ variableDecl.setVarargs(true);
+ }
+ }
+ if (this.resolveBindings) {
+ recordNodes(name, argument);
+ recordNodes(variableDecl, argument);
+ variableDecl.resolveBinding();
+ }
+ return variableDecl;
+ }
+
+
+ public Annotation convert(org.eclipse.jdt.internal.compiler.ast.Annotation annotation) {
+ if (annotation instanceof org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation) annotation);
+ } else if (annotation instanceof org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation) annotation);
+ } else {
+ return convert((org.eclipse.jdt.internal.compiler.ast.NormalAnnotation) annotation);
+ }
+ }
+
+ public ArrayCreation convert(org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression expression) {
+ ArrayCreation arrayCreation = new ArrayCreation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayCreation, expression);
+ }
+ arrayCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Expression[] dimensions = expression.dimensions;
+
+ int dimensionsLength = dimensions.length;
+ for (int i = 0; i < dimensionsLength; i++) {
+ if (dimensions[i] != null) {
+ Expression dimension = convert(dimensions[i]);
+ if (this.resolveBindings) {
+ recordNodes(dimension, dimensions[i]);
+ }
+ arrayCreation.dimensions().add(dimension);
+ }
+ }
+ Type type = convertType(expression.type);
+ if (this.resolveBindings) {
+ recordNodes(type, expression.type);
+ }
+ ArrayType arrayType = null;
+ if (type.isArrayType()) {
+ arrayType = (ArrayType) type;
+ } else {
+ arrayType = this.ast.newArrayType(type, dimensionsLength);
+ if (this.resolveBindings) {
+ completeRecord(arrayType, expression);
+ }
+ int start = type.getStartPosition();
+ int end = type.getStartPosition() + type.getLength();
+ int previousSearchStart = end - 1;
+ ArrayType componentType = (ArrayType) type.getParent();
+ for (int i = 0; i < dimensionsLength; i++) {
+ previousSearchStart = retrieveRightBracketPosition(previousSearchStart + 1, this.compilationUnitSourceLength);
+ componentType.setSourceRange(start, previousSearchStart - start + 1);
+ componentType = (ArrayType) componentType.getParent();
+ }
+ }
+ arrayCreation.setType(arrayType);
+ if (this.resolveBindings) {
+ recordNodes(arrayType, expression);
+ }
+ if (expression.initializer != null) {
+ arrayCreation.setInitializer(convert(expression.initializer));
+ }
+ return arrayCreation;
+ }
+
+ public ArrayInitializer convert(org.eclipse.jdt.internal.compiler.ast.ArrayInitializer expression) {
+ ArrayInitializer arrayInitializer = new ArrayInitializer(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayInitializer, expression);
+ }
+ arrayInitializer.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Expression[] expressions = expression.expressions;
+ if (expressions != null) {
+ int length = expressions.length;
+ for (int i = 0; i < length; i++) {
+ Expression expr = convert(expressions[i]);
+ if (this.resolveBindings) {
+ recordNodes(expr, expressions[i]);
+ }
+ arrayInitializer.expressions().add(expr);
+ }
+ }
+ return arrayInitializer;
+ }
+
+ public ArrayAccess convert(org.eclipse.jdt.internal.compiler.ast.ArrayReference reference) {
+ ArrayAccess arrayAccess = new ArrayAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayAccess, reference);
+ }
+ arrayAccess.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ arrayAccess.setArray(convert(reference.receiver));
+ arrayAccess.setIndex(convert(reference.position));
+ return arrayAccess;
+ }
+
+ public AssertStatement convert(org.eclipse.jdt.internal.compiler.ast.AssertStatement statement) {
+ AssertStatement assertStatement = new AssertStatement(this.ast);
+ final Expression assertExpression = convert(statement.assertExpression);
+ Expression searchingNode = assertExpression;
+ assertStatement.setExpression(assertExpression);
+ org.eclipse.jdt.internal.compiler.ast.Expression exceptionArgument = statement.exceptionArgument;
+ if (exceptionArgument != null) {
+ final Expression exceptionMessage = convert(exceptionArgument);
+ assertStatement.setMessage(exceptionMessage);
+ searchingNode = exceptionMessage;
+ }
+ int start = statement.sourceStart;
+ int sourceEnd = retrieveSemiColonPosition(searchingNode);
+ if (sourceEnd == -1) {
+ sourceEnd = searchingNode.getStartPosition() + searchingNode.getLength() - 1;
+ assertStatement.setSourceRange(start, sourceEnd - start + 1);
+ } else {
+ assertStatement.setSourceRange(start, sourceEnd - start + 1);
+ }
+ return assertStatement;
+ }
+
+ public Assignment convert(org.eclipse.jdt.internal.compiler.ast.Assignment expression) {
+ Assignment assignment = new Assignment(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(assignment, expression);
+ }
+ Expression lhs = convert(expression.lhs);
+ assignment.setLeftHandSide(lhs);
+ assignment.setOperator(Assignment.Operator.ASSIGN);
+ assignment.setRightHandSide(convert(expression.expression));
+ int start = lhs.getStartPosition();
+ assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+ return assignment;
+ }
+
+ /*
+ * Internal use only
+ * Used to convert class body declarations
+ */
+ public TypeDeclaration convert(org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes) {
+ final TypeDeclaration typeDecl = new TypeDeclaration(this.ast);
+ typeDecl.setInterface(false);
+ int nodesLength = nodes.length;
+ for (int i = 0; i < nodesLength; i++) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodes[i];
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+ org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.jdt.internal.compiler.ast.Initializer) node;
+ Initializer initializer = new Initializer(this.ast);
+ initializer.setBody(convert(oldInitializer.block));
+ setModifiers(initializer, oldInitializer);
+ initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+// setJavaDocComment(initializer);
+// initializer.setJavadoc(convert(oldInitializer.javadoc));
+ convert(oldInitializer.javadoc, initializer);
+ typeDecl.bodyDeclarations().add(initializer);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+ if (i > 0
+ && (nodes[i - 1] instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)
+ && ((org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == fieldDeclaration.declarationSourceStart) {
+ // we have a multiple field declaration
+ // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+ FieldDeclaration currentFieldDeclaration = (FieldDeclaration) typeDecl.bodyDeclarations().get(typeDecl.bodyDeclarations().size() - 1);
+ currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fieldDeclaration));
+ } else {
+ // we can create a new FieldDeclaration
+ typeDecl.bodyDeclarations().add(convertToFieldDeclaration(fieldDeclaration));
+ }
+ } else if(node instanceof org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration) {
+ AbstractMethodDeclaration nextMethodDeclaration = (AbstractMethodDeclaration) node;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+//{ObjectTeams: ignore generated and copied method declarations
+ if (!nextMethodDeclaration.isGenerated && !nextMethodDeclaration.isCopied)
+//jwl}
+ typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+ } else if(node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ASTNode nextMemberDeclarationNode = convert(nextMemberDeclaration);
+ if (nextMemberDeclarationNode == null) {
+ typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+ } else {
+//{ObjectTeams: ignore generated role interfaces
+ if (!Flags.isSynthetic(nextMemberDeclaration.modifiers))
+// jwl}
+ typeDecl.bodyDeclarations().add(nextMemberDeclarationNode);
+ }
+ }
+ }
+ return typeDecl;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.BinaryExpression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+
+ int expressionOperatorID = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ switch (expressionOperatorID) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.LESS_EQUALS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.GREATER_EQUALS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.LEFT_SHIFT);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_SIGNED);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ infixExpression.setOperator(InfixExpression.Operator.PLUS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ infixExpression.setOperator(InfixExpression.Operator.MINUS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ infixExpression.setOperator(InfixExpression.Operator.REMAINDER);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
+ infixExpression.setOperator(InfixExpression.Operator.XOR);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
+ infixExpression.setOperator(InfixExpression.Operator.AND);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ infixExpression.setOperator(InfixExpression.Operator.TIMES);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
+ infixExpression.setOperator(InfixExpression.Operator.OR);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ infixExpression.setOperator(InfixExpression.Operator.DIVIDE);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
+ infixExpression.setOperator(InfixExpression.Operator.GREATER);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
+ infixExpression.setOperator(InfixExpression.Operator.LESS);
+ }
+
+ if (expression.left instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.jdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.jdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ } else if (expression.left instanceof StringLiteralConcatenation
+ && ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)
+ && (OperatorIds.PLUS == expressionOperatorID)) {
+ StringLiteralConcatenation literal = (StringLiteralConcatenation) expression.left;
+ final org.eclipse.jdt.internal.compiler.ast.Expression[] stringLiterals = literal.literals;
+ infixExpression.setLeftOperand(convert(stringLiterals[0]));
+ infixExpression.setRightOperand(convert(stringLiterals[1]));
+ for (int i = 2; i < literal.counter; i++) {
+ infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+ }
+ infixExpression.extendedOperands().add(convert(expression.right));
+ int startPosition = literal.sourceStart;
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+ public Block convert(org.eclipse.jdt.internal.compiler.ast.Block statement) {
+ Block block = new Block(this.ast);
+ if (statement.sourceEnd > 0) {
+ block.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ }
+ org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration
+//{ObjectTeams: ignore generated local declarations within blocs
+ && !((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)statements[i]).isGenerated) {
+//jwl}
+ checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+ } else {
+ Statement statement2 = convert(statements[i]);
+ if (statement2 != null) {
+ block.statements().add(statement2);
+ }
+ }
+ }
+ }
+ return block;
+ }
+
+// {ObjectTeams: convert method for OT-specific internal type WithinStatement
+ /**
+ * Converts internal compiler type WithinStatement to dom type WithinStatement.
+ * The first two _OT$ Elements (for team activation) are left out. The body is
+ * recovered from the try block, e.g.
+ * <code>
+ * within(new SimpleTeam())
+ * {
+ * foo();
+ * }
+ * </code>
+ * will be in the internal compiler ast
+ * <code>
+ * org.objectteams.Team _OT$team$206 = new SimpleTeam();
+ * ...
+ * int _OT$level206 = _OT$team$206.activate(3);
+ * try
+ * {
+ * foo();
+ * }
+ * finally
+ * {
+ * _OT$team$206.deactivate(_OT$level206);
+ * }
+ * </code>
+ */
+ public org.eclipse.jdt.core.dom.WithinStatement convert(WithinStatement statement)
+ {
+ org.eclipse.jdt.core.dom.WithinStatement result = this.ast.newWithinStatement();
+
+ if (statement.sourceEnd > 0)
+ {
+ result.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ }
+
+ result.setTeamExpression(convert(statement.getTeamExpression()));
+
+ org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
+ if (statements != null)
+ {
+ // for within statements use statements inside try block
+ for (int idx = 0; idx < statements.length; idx++) {
+ if (statements[idx] instanceof org.eclipse.jdt.internal.compiler.ast.TryStatement)
+ {
+ org.eclipse.jdt.internal.compiler.ast.TryStatement tryStatement =
+ (org.eclipse.jdt.internal.compiler.ast.TryStatement)statements[idx];
+ Block tryBlock = convert(tryStatement.tryBlock);
+ tryBlock.setParent(null, null);
+ result.setBody(tryBlock);
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+//mkr}
+
+
+ public BreakStatement convert(org.eclipse.jdt.internal.compiler.ast.BreakStatement statement) {
+ BreakStatement breakStatement = new BreakStatement(this.ast);
+ breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.label != null) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+ breakStatement.setLabel(name);
+ }
+ return breakStatement;
+ }
+
+
+ public SwitchCase convert(org.eclipse.jdt.internal.compiler.ast.CaseStatement statement) {
+ SwitchCase switchCase = new SwitchCase(this.ast);
+ org.eclipse.jdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
+ if (constantExpression == null) {
+ switchCase.setExpression(null);
+ } else {
+ switchCase.setExpression(convert(constantExpression));
+ }
+ switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ retrieveColonPosition(switchCase);
+ return switchCase;
+ }
+
+ public CastExpression convert(org.eclipse.jdt.internal.compiler.ast.CastExpression expression) {
+ CastExpression castExpression = new CastExpression(this.ast);
+ castExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Expression type = expression.type;
+ trimWhiteSpacesAndComments(type);
+ if (type instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference ) {
+ castExpression.setType(convertType((org.eclipse.jdt.internal.compiler.ast.TypeReference)type));
+ } else if (type instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+ castExpression.setType(convertToType((org.eclipse.jdt.internal.compiler.ast.NameReference)type));
+ }
+ castExpression.setExpression(convert(expression.expression));
+ if (this.resolveBindings) {
+ recordNodes(castExpression, expression);
+ }
+ return castExpression;
+ }
+
+ public CharacterLiteral convert(org.eclipse.jdt.internal.compiler.ast.CharLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ CharacterLiteral literal = new CharacterLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.internalSetEscapedValue(new String(this.compilationUnitSource, sourceStart, length));
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess expression) {
+ TypeLiteral typeLiteral = new TypeLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(typeLiteral, expression);
+ }
+ typeLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ typeLiteral.setType(convertType(expression.type));
+ return typeLiteral;
+ }
+
+ public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
+ if(unit.compilationResult.recoveryScannerData != null) {
+ RecoveryScanner recoveryScanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused());
+ this.scanner = recoveryScanner;
+ this.docParser.scanner = this.scanner;
+ }
+ this.compilationUnitSource = source;
+ this.compilationUnitSourceLength = source.length;
+ this.scanner.setSource(source, unit.compilationResult);
+ CompilationUnit compilationUnit = new CompilationUnit(this.ast);
+ compilationUnit.setStatementsRecoveryData(unit.compilationResult.recoveryScannerData);
+
+ // Parse comments
+ int[][] comments = unit.comments;
+ if (comments != null) {
+ buildCommentsTable(compilationUnit, comments);
+ }
+
+ // handle the package declaration immediately
+ // There is no node corresponding to the package declaration
+ if (this.resolveBindings) {
+ recordNodes(compilationUnit, unit);
+ }
+ if (unit.currentPackage != null) {
+ PackageDeclaration packageDeclaration = convertPackage(unit);
+ compilationUnit.setPackage(packageDeclaration);
+ }
+ org.eclipse.jdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
+ if (imports != null) {
+ int importLength = imports.length;
+ for (int i = 0; i < importLength; i++) {
+ compilationUnit.imports().add(convertImport(imports[i]));
+ }
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
+ if (types != null) {
+ int typesLength = types.length;
+ for (int i = 0; i < typesLength; i++) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
+ if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
+ continue;
+ }
+ ASTNode type = convert(declaration);
+ if (type == null) {
+ compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+ } else {
+//{ObjectTeams: ignore generated role interfaces
+ if (!Flags.isSynthetic(types[i].modifiers))
+// jwl}
+
+ compilationUnit.types().add(type);
+ }
+ }
+ }
+ compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart + 1);
+
+ int problemLength = unit.compilationResult.problemCount;
+ if (problemLength != 0) {
+ CategorizedProblem[] resizedProblems = null;
+ final CategorizedProblem[] problems = unit.compilationResult.getProblems();
+ final int realProblemLength=problems.length;
+ if (realProblemLength == problemLength) {
+ resizedProblems = problems;
+ } else {
+ System.arraycopy(problems, 0, (resizedProblems = new CategorizedProblem[realProblemLength]), 0, realProblemLength);
+ }
+ ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
+ compilationUnit.accept(syntaxErrorPropagator);
+ ASTRecoveryPropagator recoveryPropagator =
+ new ASTRecoveryPropagator(resizedProblems, unit.compilationResult.recoveryScannerData);
+ compilationUnit.accept(recoveryPropagator);
+ compilationUnit.setProblems(resizedProblems);
+ }
+ if (this.resolveBindings) {
+ lookupForScopes();
+ }
+ compilationUnit.initCommentMapper(this.scanner);
+ return compilationUnit;
+ }
+
+ public Assignment convert(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment expression) {
+ Assignment assignment = new Assignment(this.ast);
+ Expression lhs = convert(expression.lhs);
+ assignment.setLeftHandSide(lhs);
+ int start = lhs.getStartPosition();
+ assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+ switch (expression.operator) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
+ assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
+ assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
+ assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
+ break;
+ }
+ assignment.setRightHandSide(convert(expression.expression));
+ if (this.resolveBindings) {
+ recordNodes(assignment, expression);
+ }
+ return assignment;
+ }
+
+ public ConditionalExpression convert(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression expression) {
+ ConditionalExpression conditionalExpression = new ConditionalExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(conditionalExpression, expression);
+ }
+ conditionalExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ conditionalExpression.setExpression(convert(expression.condition));
+ conditionalExpression.setThenExpression(convert(expression.valueIfTrue));
+ conditionalExpression.setElseExpression(convert(expression.valueIfFalse));
+ return conditionalExpression;
+ }
+
+ public ContinueStatement convert(org.eclipse.jdt.internal.compiler.ast.ContinueStatement statement) {
+ ContinueStatement continueStatement = new ContinueStatement(this.ast);
+ continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.label != null) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+ continueStatement.setLabel(name);
+ }
+ return continueStatement;
+ }
+
+ public DoStatement convert(org.eclipse.jdt.internal.compiler.ast.DoStatement statement) {
+ DoStatement doStatement = new DoStatement(this.ast);
+ doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ doStatement.setExpression(convert(statement.condition));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ doStatement.setBody(action);
+ return doStatement;
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public EmptyStatement convert(org.eclipse.jdt.internal.compiler.ast.EmptyStatement statement) {
+ EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+ emptyStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ return emptyStatement;
+ }
+
+ // field is an enum constant
+ public EnumConstantDeclaration convert(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration enumConstant) {
+ checkCanceled();
+ EnumConstantDeclaration enumConstantDeclaration = new EnumConstantDeclaration(this.ast);
+ final SimpleName typeName = new SimpleName(this.ast);
+ typeName.internalSetIdentifier(new String(enumConstant.name));
+ typeName.setSourceRange(enumConstant.sourceStart, enumConstant.sourceEnd - enumConstant.sourceStart + 1);
+ enumConstantDeclaration.setName(typeName);
+ int declarationSourceStart = enumConstant.declarationSourceStart;
+ int declarationSourceEnd = enumConstant.declarationSourceEnd;
+ final org.eclipse.jdt.internal.compiler.ast.Expression initialization = enumConstant.initialization;
+
+ if (initialization != null) {
+
+ if (initialization instanceof QualifiedAllocationExpression) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousType = ((QualifiedAllocationExpression) initialization).anonymousType;
+ if (anonymousType != null) {
+ AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast);
+ int start = retrieveStartBlockPosition(anonymousType.sourceEnd, anonymousType.bodyEnd);
+ int end = retrieveRightBrace(anonymousType.bodyEnd, declarationSourceEnd);
+ if (end == -1) end = anonymousType.bodyEnd;
+ anonymousClassDeclaration.setSourceRange(start, end - start + 1);
+ enumConstantDeclaration.setAnonymousClassDeclaration(anonymousClassDeclaration);
+ buildBodyDeclarations(anonymousType, anonymousClassDeclaration);
+ if (this.resolveBindings) {
+ recordNodes(anonymousClassDeclaration, anonymousType);
+ anonymousClassDeclaration.resolveBinding();
+ }
+ enumConstantDeclaration.setSourceRange(declarationSourceStart, end - declarationSourceStart + 1);
+ }
+ } else {
+ enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+ }
+ final org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = ((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) initialization).arguments;
+
+ if (arguments != null) {
+ for (int i = 0, max = arguments.length; i < max; i++) {
+ enumConstantDeclaration.arguments().add(convert(arguments[i]));
+ }
+ }
+ } else {
+ enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+ }
+ setModifiers(enumConstantDeclaration, enumConstant);
+ if (this.resolveBindings) {
+ recordNodes(enumConstantDeclaration, enumConstant);
+ recordNodes(typeName, enumConstant);
+ enumConstantDeclaration.resolveVariable();
+ }
+ convert(enumConstant.javadoc, enumConstantDeclaration);
+ return enumConstantDeclaration;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.EqualExpression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(infixExpression, expression);
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+ }
+ return infixExpression;
+
+ }
+
+ public Statement convert(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall statement) {
+ Statement newStatement;
+ int sourceStart = statement.sourceStart;
+//{ObjectTeams: convert tsuper constructor invocation
+ if (statement.isTsuperAccess())
+ {
+ TSuperConstructorInvocation result = this.ast.newTSuperConstructorInvocation();
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+ if (arguments != null)
+ {
+ int length = arguments.length;
+ length--; // remove last marker argument
+ for (int i = 0; i < length; i++)
+ {
+ result.getArguments().add(convert(arguments[i]));
+ }
+ }
+ newStatement = result;
+ } else
+//mkr}
+ if (statement.isSuperAccess() || statement.isSuper()) {
+ SuperConstructorInvocation superConstructorInvocation = new SuperConstructorInvocation(this.ast);
+ if (statement.qualification != null) {
+ superConstructorInvocation.setExpression(convert(statement.qualification));
+ }
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ superConstructorInvocation.arguments().add(convert(arguments[i]));
+ }
+ }
+ if (statement.typeArguments != null) {
+ if (sourceStart > statement.typeArgumentsSourceStart) {
+ sourceStart = statement.typeArgumentsSourceStart;
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ superConstructorInvocation.setFlags(superConstructorInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+ superConstructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+ }
+ break;
+ }
+ }
+ newStatement = superConstructorInvocation;
+ } else {
+ ConstructorInvocation constructorInvocation = new ConstructorInvocation(this.ast);
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ constructorInvocation.arguments().add(convert(arguments[i]));
+ }
+ }
+ if (statement.typeArguments != null) {
+ if (sourceStart > statement.typeArgumentsSourceStart) {
+ sourceStart = statement.typeArgumentsSourceStart;
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+ constructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+ }
+ break;
+ }
+ }
+ if (statement.qualification != null) {
+ // this is an error
+ constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+ }
+ newStatement = constructorInvocation;
+ }
+ newStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(newStatement, statement);
+ }
+ return newStatement;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+ if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+ return convertToParenthesizedExpression(expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Annotation) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.Annotation) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CastExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.CastExpression) expression);
+ }
+ // switch between all types of expression
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AllocationExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PrefixExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.PrefixExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PostfixExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.PostfixExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Assignment) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.Assignment) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FalseLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.FalseLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TrueLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.TrueLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.NullLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.NullLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CharLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.CharLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FloatLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.FloatLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteral) expression);
+ }
+ if (expression instanceof StringLiteralConcatenation) {
+ return convert((StringLiteralConcatenation) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.StringLiteral) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.StringLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.EqualExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.EqualExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.UnaryExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.UnaryExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.MessageSend) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.MessageSend) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Reference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.Reference) expression);
+ }
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.TypeReference) expression);
+ }
+ if (expression instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend)
+ {
+ return convert(((org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend) expression));
+ }
+ if (expression instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping)
+ {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping) expression);
+ }
+ if (expression instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialTranslationExpression)
+ {
+ // Note (SH): this includes Potential{Lifting,Lowering}Expresssion:
+ return convert(((org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialTranslationExpression)expression).expression);
+ }
+ org.eclipse.jdt.internal.compiler.ast.Expression unwrapped = Lowering.unwrapExpression(expression);
+ if (unwrapped != null)
+ {
+ return convert(unwrapped);
+ }
+//gbr}
+ return null;
+ }
+
+ public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral expression) {
+ expression.computeConstant();
+ StringLiteral literal = new StringLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setLiteralValue(expression.constant.stringValue());
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.FalseLiteral expression) {
+ final BooleanLiteral literal = new BooleanLiteral(this.ast);
+ literal.setBooleanValue(false);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.FieldReference reference) {
+ if (reference.receiver.isSuper()) {
+ final SuperFieldAccess superFieldAccess = new SuperFieldAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(superFieldAccess, reference);
+ }
+ if (reference.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+ Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference.receiver);
+ superFieldAccess.setQualifier(qualifier);
+ if (this.resolveBindings) {
+ recordNodes(qualifier, reference.receiver);
+ }
+ }
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(reference.token));
+ int sourceStart = (int)(reference.nameSourcePosition>>>32);
+ int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+ simpleName.setSourceRange(sourceStart, length);
+ superFieldAccess.setName(simpleName);
+ if (this.resolveBindings) {
+ recordNodes(simpleName, reference);
+ }
+ superFieldAccess.setSourceRange(reference.receiver.sourceStart, reference.sourceEnd - reference.receiver.sourceStart + 1);
+ return superFieldAccess;
+ } else {
+ final FieldAccess fieldAccess = new FieldAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(fieldAccess, reference);
+ }
+ Expression receiver = convert(reference.receiver);
+ fieldAccess.setExpression(receiver);
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(reference.token));
+ int sourceStart = (int)(reference.nameSourcePosition>>>32);
+ int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+ simpleName.setSourceRange(sourceStart, length);
+ fieldAccess.setName(simpleName);
+ if (this.resolveBindings) {
+ recordNodes(simpleName, reference);
+ }
+ fieldAccess.setSourceRange(receiver.getStartPosition(), reference.sourceEnd - receiver.getStartPosition() + 1);
+ return fieldAccess;
+ }
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.FloatLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public Statement convert(ForeachStatement statement) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ return createFakeEmptyStatement(statement);
+ case AST.JLS3 :
+ EnhancedForStatement enhancedForStatement = new EnhancedForStatement(this.ast);
+ enhancedForStatement.setParameter(convertToSingleVariableDeclaration(statement.elementVariable));
+ org.eclipse.jdt.internal.compiler.ast.Expression collection = statement.collection;
+ if (collection == null) return null;
+ enhancedForStatement.setExpression(convert(collection));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ enhancedForStatement.setBody(action);
+ int start = statement.sourceStart;
+ int end = statement.sourceEnd;
+ enhancedForStatement.setSourceRange(start, end - start + 1);
+ return enhancedForStatement;
+ default:
+ return createFakeEmptyStatement(statement);
+ }
+ }
+
+ public ForStatement convert(org.eclipse.jdt.internal.compiler.ast.ForStatement statement) {
+ ForStatement forStatement = new ForStatement(this.ast);
+ forStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
+ if (initializations != null) {
+ // we know that we have at least one initialization
+ if (initializations[0] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.LocalDeclaration initialization = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[0];
+ VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(initialization);
+ int initializationsLength = initializations.length;
+ for (int i = 1; i < initializationsLength; i++) {
+ initialization = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)initializations[i];
+ variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment(initialization));
+ }
+ if (initializationsLength != 1) {
+ int start = variableDeclarationExpression.getStartPosition();
+ int end = ((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
+ variableDeclarationExpression.setSourceRange(start, end - start + 1);
+ }
+ forStatement.initializers().add(variableDeclarationExpression);
+ } else {
+ int initializationsLength = initializations.length;
+ for (int i = 0; i < initializationsLength; i++) {
+ Expression initializer = convertToExpression(initializations[i]);
+ if (initializer != null) {
+ forStatement.initializers().add(initializer);
+ } else {
+ forStatement.setFlags(forStatement.getFlags() | ASTNode.MALFORMED);
+ }
+ }
+ }
+ }
+ if (statement.condition != null) {
+ forStatement.setExpression(convert(statement.condition));
+ }
+ org.eclipse.jdt.internal.compiler.ast.Statement[] increments = statement.increments;
+ if (increments != null) {
+ int incrementsLength = increments.length;
+ for (int i = 0; i < incrementsLength; i++) {
+ forStatement.updaters().add(convertToExpression(increments[i]));
+ }
+ }
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ forStatement.setBody(action);
+ return forStatement;
+ }
+
+ public IfStatement convert(org.eclipse.jdt.internal.compiler.ast.IfStatement statement) {
+ IfStatement ifStatement = new IfStatement(this.ast);
+ ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ ifStatement.setExpression(convert(statement.condition));
+ final Statement thenStatement = convert(statement.thenStatement);
+ if (thenStatement == null) return null;
+ ifStatement.setThenStatement(thenStatement);
+ org.eclipse.jdt.internal.compiler.ast.Statement statement2 = statement.elseStatement;
+ if (statement2 != null) {
+ final Statement elseStatement = convert(statement2);
+ if (elseStatement != null) {
+ ifStatement.setElseStatement(elseStatement);
+ }
+ }
+ return ifStatement;
+ }
+
+ public InstanceofExpression convert(org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression expression) {
+ InstanceofExpression instanceOfExpression = new InstanceofExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(instanceOfExpression, expression);
+ }
+ Expression leftExpression = convert(expression.expression);
+ instanceOfExpression.setLeftOperand(leftExpression);
+ final Type convertType = convertType(expression.type);
+ instanceOfExpression.setRightOperand(convertType);
+ int startPosition = leftExpression.getStartPosition();
+ int sourceEnd = convertType.getStartPosition() + convertType.getLength() - 1;
+ instanceOfExpression.setSourceRange(startPosition, sourceEnd - startPosition + 1);
+ return instanceOfExpression;
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ final NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
+ if (bodyDeclaration.getJavadoc() == null) {
+ if (javadoc != null) {
+ if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+ this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+ }
+ Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+ if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+ Javadoc docComment = (Javadoc) comment;
+ if (this.resolveBindings) {
+ recordNodes(docComment, javadoc);
+ // resolve member and method references binding
+ Iterator tags = docComment.tags().listIterator();
+ while (tags.hasNext()) {
+ recordNodes(javadoc, (TagElement) tags.next());
+ }
+ }
+ bodyDeclaration.setJavadoc(docComment);
+ }
+ }
+ }
+ }
+
+ public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, PackageDeclaration packageDeclaration) {
+ if (this.ast.apiLevel == AST.JLS3 && packageDeclaration.getJavadoc() == null) {
+ if (javadoc != null) {
+ if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+ this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+ }
+ Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+ if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+ Javadoc docComment = (Javadoc) comment;
+ if (this.resolveBindings) {
+ recordNodes(docComment, javadoc);
+ // resolve member and method references binding
+ Iterator tags = docComment.tags().listIterator();
+ while (tags.hasNext()) {
+ recordNodes(javadoc, (TagElement) tags.next());
+ }
+ }
+ packageDeclaration.setJavadoc(docComment);
+ }
+ }
+ }
+ }
+
+ public LabeledStatement convert(org.eclipse.jdt.internal.compiler.ast.LabeledStatement statement) {
+ LabeledStatement labeledStatement = new LabeledStatement(this.ast);
+ final int sourceStart = statement.sourceStart;
+ labeledStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+ Statement body = convert(statement.statement);
+ if (body == null) return null;
+ labeledStatement.setBody(body);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ name.setSourceRange(sourceStart, statement.labelEnd - sourceStart + 1);
+ labeledStatement.setLabel(name);
+ return labeledStatement;
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ final NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ final NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public Expression convert(MessageSend expression) {
+ // will return a MethodInvocation or a SuperMethodInvocation or
+ Expression expr;
+ int sourceStart = expression.sourceStart;
+
+//{ObjectTeams: convert tsuper.methodName() and return TSuperMessageSend
+
+ // conversion of compiler ast nodes for tsuper method invocation.
+ // The compiler ast uses TSuperMessageSend instead of MessageSend.
+ if (expression instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend)
+ {
+ org.eclipse.jdt.core.dom.TSuperMessageSend result = this.ast.newTSuperMessageSend();
+ result.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend send =
+ (org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend)expression;
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.TsuperReference tsuperRef = send.tsuperReference;
+ TypeReference typeReference = tsuperRef.qualification;
+ if (typeReference != null) {
+ Name qualification = null;
+ if (typeReference instanceof QualifiedTypeReference)
+ {
+ long[] poss = ((QualifiedTypeReference)typeReference).sourcePositions;
+ qualification = setQualifiedNameNameAndSourceRanges(typeReference.getTypeName(), poss, tsuperRef);
+ } else {
+ qualification = this.ast.newSimpleName(new String(((SingleTypeReference)typeReference).token));
+ qualification.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd);
+ }
+ result.setQualification(qualification);
+ }
+
+
+ SimpleName name = this.ast.newSimpleName(new String(expression.selector));
+ int start = (int)(expression.nameSourcePosition >>> 32);
+ int end = (int)(expression.nameSourcePosition & 0xFFFFFFFF);
+ name.setSourceRange(start, end-start+1);
+
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ recordNodes(result, expression);
+ }
+ result.setName(name);
+
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null)
+ {
+ int argumentsLength = arguments.length;
+ argumentsLength--; //without marker element
+ for (int idx = 0; idx < argumentsLength; idx++)
+ {
+ Expression argExpr = convert(arguments[idx]);
+ if (this.resolveBindings)
+ {
+ recordNodes(argExpr, arguments[idx]);
+ }
+ result.getArguments().add(argExpr);
+ }
+ }
+ return result;
+ }
+//mkr}
+ if (expression.isSuperAccess()) {
+ // returns a SuperMethodInvocation
+ final SuperMethodInvocation superMethodInvocation = new SuperMethodInvocation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(superMethodInvocation, expression);
+ }
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(expression.selector));
+ int nameSourceStart = (int) (expression.nameSourcePosition >>> 32);
+ int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+ name.setSourceRange(nameSourceStart, nameSourceLength);
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ }
+ superMethodInvocation.setName(name);
+ // expression.receiver is either a QualifiedSuperReference or a SuperReference
+ // so the casting cannot fail
+ if (expression.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+ Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) expression.receiver);
+ superMethodInvocation.setQualifier(qualifier);
+ if (this.resolveBindings) {
+ recordNodes(qualifier, expression.receiver);
+ }
+ if (qualifier != null) {
+ sourceStart = qualifier.getStartPosition();
+ }
+ }
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ for (int i = 0; i < argumentsLength; i++) {
+ Expression expri = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(expri, arguments[i]);
+ }
+ superMethodInvocation.arguments().add(expri);
+ }
+ }
+ final TypeReference[] typeArguments = expression.typeArguments;
+ if (typeArguments != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ superMethodInvocation.setFlags(superMethodInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = typeArguments.length; i < max; i++) {
+ superMethodInvocation.typeArguments().add(convertType(typeArguments[i]));
+ }
+ break;
+ }
+ }
+ expr = superMethodInvocation;
+ } else {
+ // returns a MethodInvocation
+ final MethodInvocation methodInvocation = new MethodInvocation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(methodInvocation, expression);
+ }
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(expression.selector));
+ int nameSourceStart = (int) (expression.nameSourcePosition >>> 32);
+ int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+ name.setSourceRange(nameSourceStart, nameSourceLength);
+ methodInvocation.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ }
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ for (int i = 0; i < argumentsLength; i++) {
+ Expression expri = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(expri, arguments[i]);
+ }
+ methodInvocation.arguments().add(expri);
+ }
+ }
+ Expression qualifier = null;
+ org.eclipse.jdt.internal.compiler.ast.Expression receiver = expression.receiver;
+ if (receiver instanceof MessageSend) {
+ if ((receiver.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+ qualifier = convertToParenthesizedExpression(receiver);
+ } else {
+ qualifier = convert((MessageSend) receiver);
+ }
+ } else {
+ qualifier = convert(receiver);
+ }
+ if (qualifier instanceof Name && this.resolveBindings) {
+ recordNodes(qualifier, receiver);
+ }
+ methodInvocation.setExpression(qualifier);
+ if (qualifier != null) {
+ sourceStart = qualifier.getStartPosition();
+ }
+ final TypeReference[] typeArguments = expression.typeArguments;
+ if (typeArguments != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodInvocation.setFlags(methodInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = typeArguments.length; i < max; i++) {
+ methodInvocation.typeArguments().add(convertType(typeArguments[i]));
+ }
+ break;
+ }
+ }
+ expr = methodInvocation;
+ }
+ expr.setSourceRange(sourceStart, expression.sourceEnd - sourceStart + 1);
+ removeTrailingCommentFromExpressionEndingWithAParen(expr);
+ return expr;
+ }
+
+ public MarkerAnnotation convert(org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation annotation) {
+ final MarkerAnnotation markerAnnotation = new MarkerAnnotation(this.ast);
+ setTypeNameForAnnotation(annotation, markerAnnotation);
+ int start = annotation.sourceStart;
+ int end = annotation.declarationSourceEnd;
+ markerAnnotation.setSourceRange(start, end - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(markerAnnotation, annotation);
+ markerAnnotation.resolveAnnotationBinding();
+ }
+ return markerAnnotation;
+ }
+
+ public MemberValuePair convert(org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair) {
+ final MemberValuePair pair = new MemberValuePair(this.ast);
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(memberValuePair.name));
+ int start = memberValuePair.sourceStart;
+ int end = memberValuePair.sourceEnd;
+ simpleName.setSourceRange(start, end - start + 1);
+ pair.setName(simpleName);
+ final Expression value = convert(memberValuePair.value);
+ pair.setValue(value);
+ start = memberValuePair.sourceStart;
+ end = value.getStartPosition() + value.getLength() - 1;
+ pair.setSourceRange(start, end - start + 1);
+
+ if (memberValuePair.value instanceof SingleNameReference &&
+ ((SingleNameReference)memberValuePair.value).token == RecoveryScanner.FAKE_IDENTIFIER) {
+ pair.setFlags(pair.getFlags() | ASTNode.RECOVERED);
+ }
+
+ if (this.resolveBindings) {
+ recordNodes(simpleName, memberValuePair);
+ recordNodes(pair, memberValuePair);
+ }
+ return pair;
+ }
+
+ public Name convert(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
+ if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) reference);
+ } else {
+ return convert((org.eclipse.jdt.internal.compiler.ast.SingleNameReference) reference);
+ }
+ }
+
+ public InfixExpression convert(StringLiteralConcatenation expression) {
+ expression.computeConstant();
+ final InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.PLUS);
+ org.eclipse.jdt.internal.compiler.ast.Expression[] stringLiterals = expression.literals;
+ infixExpression.setLeftOperand(convert(stringLiterals[0]));
+ infixExpression.setRightOperand(convert(stringLiterals[1]));
+ for (int i = 2; i < expression.counter; i++) {
+ infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ infixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return infixExpression;
+ }
+
+ public NormalAnnotation convert(org.eclipse.jdt.internal.compiler.ast.NormalAnnotation annotation) {
+ final NormalAnnotation normalAnnotation = new NormalAnnotation(this.ast);
+ setTypeNameForAnnotation(annotation, normalAnnotation);
+
+ int start = annotation.sourceStart;
+ int end = annotation.declarationSourceEnd;
+
+ org.eclipse.jdt.internal.compiler.ast.MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
+ if (memberValuePairs != null) {
+ for (int i = 0, max = memberValuePairs.length; i < max; i++) {
+ MemberValuePair memberValuePair = convert(memberValuePairs[i]);
+ int memberValuePairEnd = memberValuePair.getStartPosition() + memberValuePair.getLength() - 1;
+ if (end == memberValuePairEnd) {
+ normalAnnotation.setFlags(normalAnnotation.getFlags() | ASTNode.RECOVERED);
+ }
+ normalAnnotation.values().add(memberValuePair);
+ }
+ }
+
+ normalAnnotation.setSourceRange(start, end - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(normalAnnotation, annotation);
+ normalAnnotation.resolveAnnotationBinding();
+ }
+ return normalAnnotation;
+ }
+
+ public NullLiteral convert(org.eclipse.jdt.internal.compiler.ast.NullLiteral expression) {
+ final NullLiteral literal = new NullLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ final int expressionOperatorID = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ if (expression.left instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.jdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.jdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+ public PostfixExpression convert(org.eclipse.jdt.internal.compiler.ast.PostfixExpression expression) {
+ final PostfixExpression postfixExpression = new PostfixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(postfixExpression, expression);
+ }
+ postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ postfixExpression.setOperand(convert(expression.lhs));
+ switch (expression.operator) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
+ break;
+ }
+ return postfixExpression;
+ }
+
+ public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.PrefixExpression expression) {
+ final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(prefixExpression, expression);
+ }
+ prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ prefixExpression.setOperand(convert(expression.lhs));
+ switch (expression.operator) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
+ break;
+ }
+ return prefixExpression;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
+ final ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+ if (allocation.enclosingInstance != null) {
+ classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ classInstanceCreation.internalSetName(convert(allocation.type));
+ break;
+ case AST.JLS3 :
+ classInstanceCreation.setType(convertType(allocation.type));
+ }
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ Expression argument = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(argument, arguments[i]);
+ }
+ classInstanceCreation.arguments().add(argument);
+ }
+ }
+ if (allocation.typeArguments != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = allocation.typeArguments.length; i < max; i++) {
+ classInstanceCreation.typeArguments().add(convertType(allocation.typeArguments[i]));
+ }
+ }
+ }
+ if (allocation.anonymousType != null) {
+ int declarationSourceStart = allocation.sourceStart;
+ classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
+ final AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast);
+ int start = retrieveStartBlockPosition(allocation.anonymousType.sourceEnd, allocation.anonymousType.bodyEnd);
+ anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
+ classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
+ buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, allocation.anonymousType);
+ recordNodes(anonymousClassDeclaration, allocation.anonymousType);
+ anonymousClassDeclaration.resolveBinding();
+ }
+ return classInstanceCreation;
+ } else {
+ final int start = allocation.sourceStart;
+ classInstanceCreation.setSourceRange(start, allocation.sourceEnd - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, allocation);
+ }
+ removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+ return classInstanceCreation;
+ }
+ }
+
+ public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference nameReference) {
+ return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
+ }
+
+ public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference reference) {
+ return convert(reference.qualification);
+ }
+
+//{ObjectTeams: convert methods for OT-specific internal types
+// BaseAllocationExpression, BaseCallMessageSend,
+// QualifiedFakedBaseReference
+
+public BaseConstructorInvocation convert(
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression expr) {
+ BaseConstructorInvocation result = this.ast
+ .newBaseConstructorInvocation();
+ result.setSourceRange(expr.sourceStart, expr.sourceEnd
+ - expr.sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(result, expr);
+ }
+
+ // [SH]: expression is set during TransformStatements, will be null if
+ // errors encountered
+ if (expr.expression != null) {
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments;
+ org.eclipse.jdt.internal.compiler.ast.Expression call = expr.expression;
+ if (call instanceof org.eclipse.jdt.internal.compiler.ast.CastExpression)
+ call = ((org.eclipse.jdt.internal.compiler.ast.CastExpression)call).expression;
+ if (call instanceof AllocationExpression)
+ arguments = ((AllocationExpression) call).arguments;
+ else if (call instanceof MessageSend)
+ arguments = ((MessageSend) call).arguments; // creator call
+ else
+ throw new InternalCompilerError("Unexpected expression type in BaseAllocationExpression"); //$NON-NLS-1$
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ for (int idx = 0; idx < argumentsLength; idx++) {
+ Expression argExpr = convert(arguments[idx]);
+ if (this.resolveBindings) {
+ recordNodes(argExpr, arguments[idx]);
+ }
+ result.getArguments().add(argExpr);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public org.eclipse.jdt.core.dom.BaseCallMessageSend convert(
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend expression) {
+ org.eclipse.jdt.core.dom.BaseCallMessageSend result = this.ast
+ .newBaseCallMessageSend();
+ result.setSourceRange(expression.sourceStart, expression.sourceEnd
+ - expression.sourceStart + 1);
+
+ MessageSend msgSend = expression.getMessageSend();
+ char[] srcSelector = expression.sourceSelector;
+ SimpleName name = this.ast.newSimpleName(new String(srcSelector));
+ int start = (int) (msgSend.nameSourcePosition >>> 32);
+ int end = (int) (msgSend.nameSourcePosition & 0xFFFFFFFF);
+ name.setSourceRange(start, end - start + 1);
+
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ recordNodes(result, expression);
+ }
+ result.setName(name);
+
+ org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = msgSend.arguments;
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ // FIXME(SH): static?
+ for (int idx = MethodSignatureEnhancer.ENHANCING_ARG_LEN+1; idx < argumentsLength; idx++) { // +1: skip 'isSuperAccess'
+ Expression argExpr = convert(arguments[idx]);
+ if (this.resolveBindings) {
+ recordNodes(argExpr, arguments[idx]);
+ }
+ result.getArguments().add(argExpr);
+ }
+ }
+ return result;
+ }
+//gbr}
+
+ public ThisExpression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference reference) {
+ final ThisExpression thisExpression = new ThisExpression(this.ast);
+ thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ thisExpression.setQualifier(convert(reference.qualification));
+ if (this.resolveBindings) {
+ recordNodes(thisExpression, reference);
+ recordPendingThisExpressionScopeResolution(thisExpression);
+ }
+ return thisExpression;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.Reference reference) {
+ if (reference instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.NameReference) reference);
+ }
+//{ObjectTeams: cases added for converting OT-specific internal types TSuperReference
+// and BaseReference
+ if (reference instanceof TsuperReference)
+ {
+ return convert((TsuperReference)reference);
+ }
+ if (reference instanceof BaseReference)
+ {
+ return convert((BaseReference)reference);
+ }
+//gbr}
+ if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ThisReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ThisReference) reference);
+ }
+ if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ArrayReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ArrayReference) reference);
+ }
+ if (reference instanceof org.eclipse.jdt.internal.compiler.ast.FieldReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.FieldReference) reference);
+ }
+ return null; // cannot be reached
+ }
+
+ public ReturnStatement convert(org.eclipse.jdt.internal.compiler.ast.ReturnStatement statement) {
+ final ReturnStatement returnStatement = new ReturnStatement(this.ast);
+ returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.expression != null) {
+ returnStatement.setExpression(convert(statement.expression));
+ }
+ return returnStatement;
+ }
+
+ public SingleMemberAnnotation convert(org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation annotation) {
+ final SingleMemberAnnotation singleMemberAnnotation = new SingleMemberAnnotation(this.ast);
+ setTypeNameForAnnotation(annotation, singleMemberAnnotation);
+ singleMemberAnnotation.setValue(convert(annotation.memberValue));
+ int start = annotation.sourceStart;
+ int end = annotation.declarationSourceEnd;
+ singleMemberAnnotation.setSourceRange(start, end - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(singleMemberAnnotation, annotation);
+ singleMemberAnnotation.resolveAnnotationBinding();
+ }
+ return singleMemberAnnotation;
+ }
+
+ public SimpleName convert(org.eclipse.jdt.internal.compiler.ast.SingleNameReference nameReference) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(nameReference.token));
+ if (this.resolveBindings) {
+ recordNodes(name, nameReference);
+ }
+ name.setSourceRange(nameReference.sourceStart, nameReference.sourceEnd - nameReference.sourceStart + 1);
+ return name;
+ }
+
+ public Statement convert(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+//{ObjectTeams: don't convert generated statements
+ if (statement != null && statement.isGenerated())
+ return null;
+// SH}
+ if (statement instanceof ForeachStatement) {
+ return convert((ForeachStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)statement;
+ return convertToVariableDeclarationStatement(localDeclaration);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.AssertStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.AssertStatement) statement);
+ }
+//{ObjectTeams: case added for converting OT-specific node WithinStatement
+ if (statement instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.WithinStatement)
+ {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.WithinStatement)statement);
+ }
+//gbr}
+//{ObjectTeams: handle BaseConstructorMessageSend. Note: might be unresolvable, i.e. incomplete rhs!
+ if (statement instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression) {
+ return convert((org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression) statement);
+ }
+//carp}
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Block) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.Block) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.BreakStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.BreakStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ContinueStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ContinueStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.CaseStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.CaseStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.DoStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.DoStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.EmptyStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.EmptyStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ForStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ForStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.IfStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.IfStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.LabeledStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.LabeledStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ReturnStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ReturnStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.SwitchStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.SwitchStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ThrowStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.ThrowStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TryStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.TryStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ ASTNode result = convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement);
+ if (result == null) {
+ return createFakeEmptyStatement(statement);
+ }
+ switch(result.getNodeType()) {
+ case ASTNode.ENUM_DECLARATION:
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ return createFakeEmptyStatement(statement);
+ case AST.JLS3 :
+ final TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+ typeDeclarationStatement.setDeclaration((EnumDeclaration) result);
+ AbstractTypeDeclaration typeDecl = typeDeclarationStatement.getDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+ return typeDeclarationStatement;
+ }
+ break;
+ case ASTNode.ANNOTATION_TYPE_DECLARATION :
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ return createFakeEmptyStatement(statement);
+ case AST.JLS3 :
+ TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+ typeDeclarationStatement.setDeclaration((AnnotationTypeDeclaration) result);
+ AbstractTypeDeclaration typeDecl = typeDeclarationStatement.getDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+ return typeDeclarationStatement;
+ }
+ break;
+ default:
+ TypeDeclaration typeDeclaration = (TypeDeclaration) result;
+ TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+ typeDeclarationStatement.setDeclaration(typeDeclaration);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ TypeDeclaration typeDecl = typeDeclarationStatement.internalGetTypeDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+ break;
+ case AST.JLS3 :
+ AbstractTypeDeclaration typeDeclAST3 = typeDeclarationStatement.getDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDeclAST3.getStartPosition(), typeDeclAST3.getLength());
+ break;
+ }
+ return typeDeclarationStatement;
+ }
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.WhileStatement) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.WhileStatement) statement);
+ }
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+ org.eclipse.jdt.internal.compiler.ast.Expression statement2 = (org.eclipse.jdt.internal.compiler.ast.Expression) statement;
+ final Expression expr = convert(statement2);
+ final ExpressionStatement stmt = new ExpressionStatement(this.ast);
+ stmt.setExpression(expr);
+ int sourceStart = expr.getStartPosition();
+ int sourceEnd = statement2.statementEnd;
+ stmt.setSourceRange(sourceStart, sourceEnd - sourceStart + 1);
+ return stmt;
+ }
+ return createFakeEmptyStatement(statement);
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.StringLiteral expression) {
+ if (expression instanceof StringLiteralConcatenation) {
+ return convert((StringLiteralConcatenation) expression);
+ }
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ StringLiteral literal = new StringLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.internalSetEscapedValue(new String(this.compilationUnitSource, sourceStart, length));
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public SwitchStatement convert(org.eclipse.jdt.internal.compiler.ast.SwitchStatement statement) {
+ SwitchStatement switchStatement = new SwitchStatement(this.ast);
+ switchStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ switchStatement.setExpression(convert(statement.expression));
+ org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+ checkAndAddMultipleLocalDeclaration(statements, i, switchStatement.statements());
+ } else {
+ final Statement currentStatement = convert(statements[i]);
+ if (currentStatement != null) {
+ switchStatement.statements().add(currentStatement);
+ }
+ }
+ }
+ }
+ return switchStatement;
+ }
+
+ public SynchronizedStatement convert(org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement statement) {
+ SynchronizedStatement synchronizedStatement = new SynchronizedStatement(this.ast);
+ synchronizedStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ synchronizedStatement.setBody(convert(statement.block));
+ synchronizedStatement.setExpression(convert(statement.expression));
+ return synchronizedStatement;
+ }
+
+ public Expression convert(org.eclipse.jdt.internal.compiler.ast.ThisReference reference) {
+ if (reference.isImplicitThis()) {
+ // There is no source associated with an implicit this
+ return null;
+ } else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference);
+ } else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) reference);
+ } else {
+ ThisExpression thisExpression = new ThisExpression(this.ast);
+ thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(thisExpression, reference);
+ recordPendingThisExpressionScopeResolution(thisExpression);
+ }
+ return thisExpression;
+ }
+ }
+
+ public ThrowStatement convert(org.eclipse.jdt.internal.compiler.ast.ThrowStatement statement) {
+ final ThrowStatement throwStatement = new ThrowStatement(this.ast);
+ throwStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ throwStatement.setExpression(convert(statement.exception));
+ return throwStatement;
+ }
+
+ public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.TrueLiteral expression) {
+ final BooleanLiteral literal = new BooleanLiteral(this.ast);
+ literal.setBooleanValue(true);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public TryStatement convert(org.eclipse.jdt.internal.compiler.ast.TryStatement statement) {
+ final TryStatement tryStatement = new TryStatement(this.ast);
+ tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+
+ tryStatement.setBody(convert(statement.tryBlock));
+ org.eclipse.jdt.internal.compiler.ast.Argument[] catchArguments = statement.catchArguments;
+ if (catchArguments != null) {
+ int catchArgumentsLength = catchArguments.length;
+ org.eclipse.jdt.internal.compiler.ast.Block[] catchBlocks = statement.catchBlocks;
+ int start = statement.tryBlock.sourceEnd;
+ for (int i = 0; i < catchArgumentsLength; i++) {
+ CatchClause catchClause = new CatchClause(this.ast);
+ int catchClauseSourceStart = retrieveStartingCatchPosition(start, catchArguments[i].sourceStart);
+ catchClause.setSourceRange(catchClauseSourceStart, catchBlocks[i].sourceEnd - catchClauseSourceStart + 1);
+ catchClause.setBody(convert(catchBlocks[i]));
+ catchClause.setException(convert(catchArguments[i]));
+ tryStatement.catchClauses().add(catchClause);
+ start = catchBlocks[i].sourceEnd;
+ }
+ }
+ if (statement.finallyBlock != null) {
+ tryStatement.setFinally(convert(statement.finallyBlock));
+ }
+ return tryStatement;
+ }
+
+ public ASTNode convert(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ int kind = org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.kind(typeDeclaration.modifiers);
+ switch (kind) {
+ case org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.ENUM_DECL :
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ return null;
+ } else {
+ return convertToEnumDeclaration(typeDeclaration);
+ }
+ case org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.ANNOTATION_TYPE_DECL :
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ return null;
+ } else {
+ return convertToAnnotationDeclaration(typeDeclaration);
+ }
+ }
+
+ checkCanceled();
+//{ObjectTeams: if TypeDeclaration is a role, it is a RoleTypeDeclaration, otherwise it is just a
+ //TypeDeclaration
+ TypeDeclaration typeDecl;
+ if (!typeDeclaration.isRole())
+ {
+//ike}
+ typeDecl = new TypeDeclaration(this.ast);
+ if (typeDeclaration.modifiersSourceStart != -1) {
+ setModifiers(typeDecl, typeDeclaration);
+ }
+ typeDecl.setInterface(kind == org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.INTERFACE_DECL);
+//{ObjectTeams: type declaration can be a team class or a role class, too
+ typeDecl.setTeam(typeDeclaration.isTeam());
+ typeDecl.setRole(typeDeclaration.isSourceRole());
+//gbr}
+ final SimpleName typeName = new SimpleName(this.ast);
+ typeName.internalSetIdentifier(new String(typeDeclaration.name));
+ typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+ typeDecl.setName(typeName);
+ typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+
+ // need to set the superclass and super interfaces here since we cannot distinguish them at
+ // the type references level.
+ if (typeDeclaration.superclass != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ typeDecl.internalSetSuperclass(convert(typeDeclaration.superclass));
+ break;
+ case AST.JLS3 :
+ typeDecl.setSuperclassType(convertType(typeDeclaration.superclass));
+ break;
+ }
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+ if (superInterfaces != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ for (int index = 0, length = superInterfaces.length; index < length; index++) {
+ typeDecl.internalSuperInterfaces().add(convert(superInterfaces[index]));
+ }
+ break;
+ case AST.JLS3 :
+ for (int index = 0, length = superInterfaces.length; index < length; index++) {
+ typeDecl.superInterfaceTypes().add(convertType(superInterfaces[index]));
+ }
+ }
+ }
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+ if (typeParameters != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int index = 0, length = typeParameters.length; index < length; index++) {
+ typeDecl.typeParameters().add(convert(typeParameters[index]));
+ }
+ }
+ }
+ buildBodyDeclarations(typeDeclaration, typeDecl);
+ if (this.resolveBindings) {
+ recordNodes(typeDecl, typeDeclaration);
+ recordNodes(typeName, typeDeclaration);
+ typeDecl.resolveBinding();
+ }
+//{ObjectTeams: do OT-specific stuff
+ }
+ else
+ {
+ typeDecl = buildRoleTypeDeclaration(typeDeclaration);
+ }
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration guard = typeDeclaration.predicate;
+ if (guard != null)
+ typeDecl.setGuardPredicate(convertGuardPredicate(guard));
+ if (typeDeclaration.precedences != null)
+ for (org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrecedenceDeclaration aPrecedence : typeDeclaration.precedences)
+ typeDecl.precedences().add(convertPrecedence(aPrecedence));
+//ike}
+ return typeDecl;
+ }
+
+//{ObjectTeams: build RoleTypeDeclaration with inforamtions from Compiler.TypeDeclaration
+ private RoleTypeDeclaration buildRoleTypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration)
+ {
+ RoleTypeDeclaration roleTypeDecl = this.ast.newRoleTypeDeclaration();
+ char[] oldSource = null;
+ try {
+ if (typeDeclaration.isRoleFile()) {
+ if (typeDeclaration.isConverted)
+ return null; // don't convert role files which may not have enough source information
+ if (typeDeclaration.compilationResult.compilationUnit != null)
+ {
+ oldSource = this.scanner.source; // try again (see revert in 3857 but also change in 5472..)
+ this.scanner.setSource(typeDeclaration.compilationResult);
+ this.compilationUnitSource = this.scanner.source;
+ this.compilationUnitSourceLength = this.scanner.source.length;
+ }
+ roleTypeDecl.setRoleFile(true);
+ }
+
+ //km: modifers are handled differently in JLS3
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL: {
+ int modifiers = typeDeclaration.modifiers;
+ modifiers &= ~ClassFileConstants.AccInterface; // remove AccInterface flags
+ // also allow additional flag to be passed: (how about deprecated?)
+ modifiers &= ExtraCompilerModifiers.AccOTTypeJustFlag;
+ roleTypeDecl.setModifiers(modifiers);
+
+ if (typeDeclaration.baseclass != null)
+ roleTypeDecl.setBaseClass(convert(typeDeclaration.baseclass));
+
+ // need to set the superclass and super interfaces here since we cannot distinguish them at
+ // the type references level.
+ if (typeDeclaration.superclass != null)
+ roleTypeDecl.setSuperclass(convert(typeDeclaration.superclass));
+
+ }
+ break;
+ case AST.JLS3:
+ this.setModifiers(roleTypeDecl, typeDeclaration);
+
+ if ( typeDeclaration.baseclass != null
+ && !typeDeclaration.baseclass.isGenerated())
+ roleTypeDecl.setBaseClassType(convertType(typeDeclaration.baseclass));
+
+ // need to set the superclass and super interfaces here since we cannot distinguish them at
+ // the type references level.
+ if ( typeDeclaration.superclass != null
+ && !typeDeclaration.superclass.isGenerated())
+ roleTypeDecl.setSuperclassType(convertType(typeDeclaration.superclass));
+
+ break;
+ }
+
+ roleTypeDecl.setInterface(typeDeclaration.isInterface());
+ roleTypeDecl.setTeam(typeDeclaration.isTeam());
+ roleTypeDecl.setRole(typeDeclaration.isSourceRole());
+
+ SimpleName typeName = this.ast.newSimpleName(
+ getRealName(typeDeclaration.name)
+ );
+
+ typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+ roleTypeDecl.setName(typeName);
+ roleTypeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+
+ // fetch superInterfaces from the interface part of the role:
+ org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = null;
+ RoleModel roleModel = typeDeclaration.getRoleModel();
+ if ( !typeDeclaration.isInterface() // class?
+ && roleModel != null && roleModel.hasState(ITranslationStates.STATE_ROLES_SPLIT)) // has been split?
+ {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration ifcDecl = roleModel.getInterfaceAst();
+ if (ifcDecl != null)
+ superInterfaces = ifcDecl.superInterfaces;
+ } else {
+ superInterfaces = typeDeclaration.superInterfaces;
+ }
+ if (superInterfaces != null)
+ for (int index = 0, length = superInterfaces.length; index < length; index++)
+ if (!superInterfaces[index].isGenerated())
+ roleTypeDecl.superInterfaceTypes().add(convertType(superInterfaces[index]));
+
+ org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration guard = typeDeclaration.predicate;
+ if (guard != null)
+ roleTypeDecl.setGuardPredicate(convertGuardPredicate(guard));
+
+ buildBodyDeclarations(typeDeclaration, roleTypeDecl);
+
+ SimpleName teamClassName = null;
+ if (typeDeclaration.enclosingType!=null)
+ {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration teamDecl
+ = typeDeclaration.enclosingType;
+ teamClassName = this.ast.newSimpleName(new String(teamDecl.name));
+ teamClassName.setSourceRange(teamDecl.sourceStart, teamDecl.sourceEnd - teamDecl.sourceStart + 1);
+ if(this.ast.apiLevel == AST.JLS3){
+ SimpleType teamType = this.ast.newSimpleType(teamClassName);
+ teamType.setSourceRange(teamClassName.getStartPosition(), teamClassName.getLength());
+ roleTypeDecl.setTeamClassType(teamType);
+ }
+ else
+ roleTypeDecl.setTeamClass(teamClassName);
+ }
+
+ if (this.resolveBindings)
+ {
+ recordNodes(roleTypeDecl, typeDeclaration);
+ recordNodes(typeName, typeDeclaration);
+ recordNodes(teamClassName, typeDeclaration.enclosingType);
+ roleTypeDecl.resolveBinding();
+ }
+ return roleTypeDecl;
+ } finally {
+ if (oldSource != null) {
+ this.scanner.setSource(oldSource);
+ this.compilationUnitSource = oldSource;
+ this.compilationUnitSourceLength = oldSource.length;
+ }
+ }
+ }
+
+ /** Retrieve the sibling type declaration corresponding to superIfcBinding. */
+ private TypeReference[] getInterfacePartInterfaces(
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration,
+ TypeBinding superIfcBinding)
+ {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosing = typeDeclaration.enclosingType;
+ if (enclosing == null)
+ return null;
+ if (enclosing.memberTypes == null)
+ return null;
+ for (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration memberType : enclosing.memberTypes)
+ if (memberType.binding == superIfcBinding)
+ return memberType.superInterfaces;
+
+ return null;
+ }
+
+ private String getRealName(char[] name)
+ {
+ if (name == null || name.length == 0)
+ {
+ return ""; // //$NON-NLS-1$
+ }
+ String realName;
+ String[] nameTokens = new String (name).split(IOTConstants.OT_DELIM);
+ realName = nameTokens[nameTokens.length-1];
+ return realName;
+ }
+
+ private PrecedenceDeclaration convertPrecedence(org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrecedenceDeclaration aPrecedence)
+ {
+ PrecedenceDeclaration newPrecedence = this.ast.newPrecedenceDeclaration();
+ newPrecedence.setSourceRange(aPrecedence.declarationSourceStart, aPrecedence.sourceEnd - aPrecedence.declarationSourceStart + 1);
+ for (org.eclipse.jdt.internal.compiler.ast.NameReference nameRef: aPrecedence.bindingNames) {
+ newPrecedence.elements().add(convert(nameRef));
+ }
+ return newPrecedence;
+ }
+
+ private GuardPredicateDeclaration convertGuardPredicate(org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration guard) {
+ GuardPredicateDeclaration newGuard = this.ast.newGuardPredicateDeclaration();
+ newGuard.setSourceRange(guard.declarationSourceStart, guard.declarationSourceEnd - guard.declarationSourceStart + 1);
+ if (guard.hasParsedStatements) {
+ org.eclipse.jdt.internal.compiler.ast.ReturnStatement returnStat = guard.returnStatement;
+ newGuard.setExpression(convert(returnStat.expression));
+ }
+ newGuard.setBase(guard.isBasePredicate);
+ return newGuard;
+ }
+
+//ike+SH}
+
+
+ public TypeParameter convert(org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter) {
+ final TypeParameter typeParameter2 = new TypeParameter(this.ast);
+//{ObjectTeams: distinguish TypeValueParameter:
+ if (typeParameter.getKind() == org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration.TYPE_VALUE_PARAMETER)
+ typeParameter2.setIsValueParameter(true);
+// SH}
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(typeParameter.name));
+ int start = typeParameter.sourceStart;
+ int end = typeParameter.sourceEnd;
+ simpleName.setSourceRange(start, end - start + 1);
+ typeParameter2.setName(simpleName);
+ final TypeReference superType = typeParameter.type;
+ end = typeParameter.declarationSourceEnd;
+ if (superType != null) {
+ Type type = convertType(superType);
+ typeParameter2.typeBounds().add(type);
+ end = type.getStartPosition() + type.getLength() - 1;
+ }
+ TypeReference[] bounds = typeParameter.bounds;
+ if (bounds != null) {
+ Type type = null;
+ for (int index = 0, length = bounds.length; index < length; index++) {
+ type = convertType(bounds[index]);
+ typeParameter2.typeBounds().add(type);
+ end = type.getStartPosition() + type.getLength() - 1;
+ }
+//{ObjectTeams: mark <B base R>:
+ if (typeParameter.hasBaseBound())
+ typeParameter2.setHasBaseBound(true);
+// SH}
+ }
+ start = typeParameter.declarationSourceStart;
+ end = retrieveClosingAngleBracketPosition(end);
+ typeParameter2.setSourceRange(start, end - start + 1);
+ if (this.resolveBindings) {
+ recordName(simpleName, typeParameter);
+ recordNodes(typeParameter2, typeParameter);
+ typeParameter2.resolveBinding();
+ }
+ return typeParameter2;
+ }
+
+ public Name convert(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
+ char[][] typeName = typeReference.getTypeName();
+ int length = typeName.length;
+ if (length > 1) {
+//{ObjectTeams: catch qualified lifting types
+ // TODO (SH): we probably need information about both names in a lifting type??
+ if (typeReference instanceof LiftingTypeReference)
+ typeReference = ((LiftingTypeReference)typeReference).baseReference;
+// SH}
+ // QualifiedName
+ org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
+ final long[] positions = qualifiedTypeReference.sourcePositions;
+ return setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
+ } else {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(typeName[0]));
+ name.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
+ name.index = 1;
+ if (this.resolveBindings) {
+ recordNodes(name, typeReference);
+ }
+ return name;
+ }
+ }
+
+ public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.UnaryExpression expression) {
+ final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(prefixExpression, expression);
+ }
+ prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ prefixExpression.setOperand(convert(expression.expression));
+ switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT :
+ prefixExpression.setOperator(PrefixExpression.Operator.NOT);
+ break;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.TWIDDLE :
+ prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
+ }
+ return prefixExpression;
+ }
+
+ public WhileStatement convert(org.eclipse.jdt.internal.compiler.ast.WhileStatement statement) {
+ final WhileStatement whileStatement = new WhileStatement(this.ast);
+ whileStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ whileStatement.setExpression(convert(statement.condition));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ whileStatement.setBody(action);
+ return whileStatement;
+ }
+
+ public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
+ final ImportDeclaration importDeclaration = new ImportDeclaration(this.ast);
+ final boolean onDemand = (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0;
+ final char[][] tokens = importReference.tokens;
+ int length = importReference.tokens.length;
+ final long[] positions = importReference.sourcePositions;
+ if (length > 1) {
+ importDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+ } else {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(tokens[0]));
+ final int start = (int)(positions[0]>>>32);
+ final int end = (int)(positions[0] & 0xFFFFFFFF);
+ name.setSourceRange(start, end - start + 1);
+ name.index = 1;
+ importDeclaration.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, importReference);
+ }
+ }
+ importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+ importDeclaration.setOnDemand(onDemand);
+ int modifiers = importReference.modifiers;
+ if (modifiers != ClassFileConstants.AccDefault) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ if (modifiers == ClassFileConstants.AccStatic) {
+ importDeclaration.setStatic(true);
+ } else {
+ importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+ }
+//{ObjectTeams: base imports:
+ if (modifiers == ExtraCompilerModifiers.AccBase) {
+ importDeclaration.setBase(true);
+ } else {
+ importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+ }
+// SH}
+ }
+ }
+ if (this.resolveBindings) {
+ recordNodes(importDeclaration, importReference);
+ }
+ return importDeclaration;
+ }
+
+ public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
+ final PackageDeclaration packageDeclaration = new PackageDeclaration(this.ast);
+ final char[][] tokens = importReference.tokens;
+ final int length = importReference.tokens.length;
+ long[] positions = importReference.sourcePositions;
+ if (length > 1) {
+ packageDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+ } else {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(tokens[0]));
+ int start = (int)(positions[0]>>>32);
+ int end = (int)(positions[length - 1] & 0xFFFFFFFF);
+ name.setSourceRange(start, end - start + 1);
+ name.index = 1;
+ packageDeclaration.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, compilationUnitDeclaration);
+ }
+ }
+ packageDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = importReference.annotations;
+ if (annotations != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ packageDeclaration.setFlags(packageDeclaration.getFlags() & ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ packageDeclaration.annotations().add(convert(annotations[i]));
+ }
+ }
+ }
+ if (this.resolveBindings) {
+ recordNodes(packageDeclaration, importReference);
+ }
+ // Set javadoc
+ convert(compilationUnitDeclaration.javadoc, packageDeclaration);
+ return packageDeclaration;
+ }
+
+ private EnumDeclaration convertToEnumDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ checkCanceled();
+ // enum declaration cannot be built if the source is not >= 1.5, since enum is then seen as an identifier
+ final EnumDeclaration enumDeclaration2 = new EnumDeclaration(this.ast);
+ setModifiers(enumDeclaration2, typeDeclaration);
+ final SimpleName typeName = new SimpleName(this.ast);
+ typeName.internalSetIdentifier(new String(typeDeclaration.name));
+ typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+ enumDeclaration2.setName(typeName);
+ enumDeclaration2.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+
+ org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+ if (superInterfaces != null) {
+ for (int index = 0, length = superInterfaces.length; index < length; index++) {
+ enumDeclaration2.superInterfaceTypes().add(convertType(superInterfaces[index]));
+ }
+ }
+ buildBodyDeclarations(typeDeclaration, enumDeclaration2);
+ if (this.resolveBindings) {
+ recordNodes(enumDeclaration2, typeDeclaration);
+ recordNodes(typeName, typeDeclaration);
+ enumDeclaration2.resolveBinding();
+ }
+ return enumDeclaration2;
+ }
+ public Expression convertToExpression(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+ if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+ return convert((org.eclipse.jdt.internal.compiler.ast.Expression) statement);
+ } else {
+ return null;
+ }
+ }
+
+ protected FieldDeclaration convertToFieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+ VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl);
+ final FieldDeclaration fieldDeclaration = new FieldDeclaration(this.ast);
+ fieldDeclaration.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, fieldDecl);
+ variableDeclarationFragment.resolveBinding();
+ }
+ fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationEnd - fieldDecl.declarationSourceStart + 1);
+ Type type = convertType(fieldDecl.type);
+ setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions());
+ setModifiers(fieldDeclaration, fieldDecl);
+ convert(fieldDecl.javadoc, fieldDeclaration);
+ return fieldDeclaration;
+ }
+
+ public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+ final ParenthesizedExpression parenthesizedExpression = new ParenthesizedExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(parenthesizedExpression, expression);
+ }
+ parenthesizedExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ adjustSourcePositionsForParent(expression);
+ trimWhiteSpacesAndComments(expression);
+ // decrement the number of parenthesis
+ int numberOfParenthesis = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+ expression.bits &= ~org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
+ expression.bits |= (numberOfParenthesis - 1) << org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+ parenthesizedExpression.setExpression(convert(expression));
+ return parenthesizedExpression;
+ }
+
+ public Type convertToType(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
+ Name name = convert(reference);
+ final SimpleType type = new SimpleType(this.ast);
+ type.setName(name);
+ type.setSourceRange(name.getStartPosition(), name.getLength());
+ if (this.resolveBindings) {
+ this.recordNodes(type, reference);
+ }
+ return type;
+ }
+
+ protected VariableDeclarationExpression convertToVariableDeclarationExpression(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+ final VariableDeclarationExpression variableDeclarationExpression = new VariableDeclarationExpression(this.ast);
+ variableDeclarationExpression.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ }
+ variableDeclarationExpression.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+ Type type = convertType(localDeclaration.type);
+ setTypeForVariableDeclarationExpression(variableDeclarationExpression, type, variableDeclarationFragment.getExtraDimensions());
+ if (localDeclaration.modifiersSourceStart != -1) {
+ setModifiers(variableDeclarationExpression, localDeclaration);
+ }
+ return variableDeclarationExpression;
+ }
+
+ protected SingleVariableDeclaration convertToSingleVariableDeclaration(LocalDeclaration localDeclaration) {
+ final SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+ setModifiers(variableDecl, localDeclaration);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(localDeclaration.name));
+ int start = localDeclaration.sourceStart;
+ int nameEnd = localDeclaration.sourceEnd;
+ name.setSourceRange(start, nameEnd - start + 1);
+ variableDecl.setName(name);
+ final int extraDimensions = retrieveExtraDimension(nameEnd + 1, localDeclaration.type.sourceEnd);
+ variableDecl.setExtraDimensions(extraDimensions);
+ Type type = convertType(localDeclaration.type);
+ int typeEnd = type.getStartPosition() + type.getLength() - 1;
+ int rightEnd = Math.max(typeEnd, localDeclaration.declarationSourceEnd);
+ /*
+ * There is extra work to do to set the proper type positions
+ * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+ */
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+ variableDecl.setSourceRange(localDeclaration.declarationSourceStart, rightEnd - localDeclaration.declarationSourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(name, localDeclaration);
+ recordNodes(variableDecl, localDeclaration);
+ variableDecl.resolveBinding();
+ }
+ return variableDecl;
+ }
+
+ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(fieldDeclaration.name));
+ name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setName(name);
+ int start = fieldDeclaration.sourceEnd;
+ int end = start;
+ int extraDimensions = retrieveExtraDimension(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd );
+ variableDeclarationFragment.setExtraDimensions(extraDimensions);
+ if (fieldDeclaration.initialization != null) {
+ final Expression expression = convert(fieldDeclaration.initialization);
+ variableDeclarationFragment.setInitializer(expression);
+ start = expression.getStartPosition() + expression.getLength();
+ end = start - 1;
+ } else {
+ // we need to do it even if extendedDimension is null in case of syntax error in an array initializer
+ // need the exclusive range for retrieveEndOfPotentialExtendedDimensions
+ int possibleEnd = retrieveEndOfPotentialExtendedDimensions(start + 1, fieldDeclaration.sourceEnd, fieldDeclaration.declarationSourceEnd);
+ if (possibleEnd == Integer.MIN_VALUE) {
+ end = fieldDeclaration.declarationSourceEnd;
+ variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+ } if (possibleEnd < 0) {
+ end = -possibleEnd;
+ variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+ } else {
+ end = possibleEnd;
+ }
+ }
+ variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, end - fieldDeclaration.sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(name, fieldDeclaration);
+ recordNodes(variableDeclarationFragment, fieldDeclaration);
+ variableDeclarationFragment.resolveBinding();
+ }
+ return variableDeclarationFragment;
+ }
+
+ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(localDeclaration.name));
+ name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setName(name);
+ int start = localDeclaration.sourceEnd;
+ org.eclipse.jdt.internal.compiler.ast.Expression initialization = localDeclaration.initialization;
+ int extraDimension = retrieveExtraDimension(localDeclaration.sourceEnd + 1, this.compilationUnitSourceLength);
+ variableDeclarationFragment.setExtraDimensions(extraDimension);
+ boolean hasInitialization = initialization != null;
+ int end;
+ if (hasInitialization) {
+ final Expression expression = convert(initialization);
+ variableDeclarationFragment.setInitializer(expression);
+ start = expression.getStartPosition() + expression.getLength();
+ end = start - 1;
+ } else {
+ // we need to do it even if extendedDimension is null in case of syntax error in an array initializer
+ // start + 1 because we need the exclusive range for retrieveEndOfPotentialExtendedDimensions
+ int possibleEnd = retrieveEndOfPotentialExtendedDimensions(start + 1, localDeclaration.sourceEnd, localDeclaration.declarationSourceEnd);
+ if (possibleEnd == Integer.MIN_VALUE) {
+ end = start;
+ variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+ } else if (possibleEnd < 0) {
+ end = -possibleEnd;
+ variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+ } else {
+ end = possibleEnd;
+ }
+ }
+ variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, end - localDeclaration.sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ recordNodes(name, localDeclaration);
+ variableDeclarationFragment.resolveBinding();
+ }
+ return variableDeclarationFragment;
+ }
+
+ protected VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+ final VariableDeclarationStatement variableDeclarationStatement = new VariableDeclarationStatement(this.ast);
+ variableDeclarationStatement.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ }
+ variableDeclarationStatement.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+ Type type = convertType(localDeclaration.type);
+ setTypeForVariableDeclarationStatement(variableDeclarationStatement, type, variableDeclarationFragment.getExtraDimensions());
+ if (localDeclaration.modifiersSourceStart != -1) {
+ setModifiers(variableDeclarationStatement, localDeclaration);
+ }
+ return variableDeclarationStatement;
+ }
+
+ public Type convertType(TypeReference typeReference) {
+ if (typeReference instanceof Wildcard) {
+ final Wildcard wildcard = (Wildcard) typeReference;
+ final WildcardType wildcardType = new WildcardType(this.ast);
+ if (wildcard.bound != null) {
+ final Type bound = convertType(wildcard.bound);
+ wildcardType.setBound(bound, wildcard.kind == Wildcard.EXTENDS);
+ int start = wildcard.sourceStart;
+ wildcardType.setSourceRange(start, bound.getStartPosition() + bound.getLength() - start);
+ } else {
+ final int start = wildcard.sourceStart;
+ final int end = wildcard.sourceEnd;
+ wildcardType.setSourceRange(start, end - start + 1);
+ }
+ if (this.resolveBindings) {
+ recordNodes(wildcardType, typeReference);
+ }
+ return wildcardType;
+ }
+ Type type = null;
+ int sourceStart = -1;
+ int length = 0;
+ int dimensions = typeReference.dimensions();
+//{ObjectTeams: check for lifting type reference
+ if (typeReference instanceof LiftingTypeReference)
+ {
+ return convertType((LiftingTypeReference)typeReference);
+ }
+ if (typeReference instanceof TypeAnchorReference)
+ {
+ return convertType((TypeAnchorReference)typeReference);
+ }
+//gbr+SH}
+ if (typeReference instanceof org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) {
+ // this is either an ArrayTypeReference or a SingleTypeReference
+ char[] name = ((org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
+ sourceStart = typeReference.sourceStart;
+ length = typeReference.sourceEnd - typeReference.sourceStart + 1;
+ // need to find out if this is an array type of primitive types or not
+ if (isPrimitiveType(name)) {
+ int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+ if (end == -1) {
+ end = sourceStart + length - 1;
+ }
+ final PrimitiveType primitiveType = new PrimitiveType(this.ast);
+ primitiveType.setPrimitiveTypeCode(getPrimitiveTypeCode(name));
+ primitiveType.setSourceRange(sourceStart, end - sourceStart + 1);
+ type = primitiveType;
+ } else if (typeReference instanceof ParameterizedSingleTypeReference) {
+ ParameterizedSingleTypeReference parameterizedSingleTypeReference = (ParameterizedSingleTypeReference) typeReference;
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(name));
+ int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+ if (end == -1) {
+ end = sourceStart + length - 1;
+ }
+ simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(simpleName);
+ simpleType.setFlags(simpleType.getFlags() | ASTNode.MALFORMED);
+ simpleType.setSourceRange(sourceStart, end - sourceStart + 1);
+ type = simpleType;
+ if (this.resolveBindings) {
+ this.recordNodes(simpleName, typeReference);
+ }
+ break;
+ case AST.JLS3 :
+ simpleType = new SimpleType(this.ast);
+ simpleType.setName(simpleName);
+ simpleType.setSourceRange(simpleName.getStartPosition(), simpleName.getLength());
+ final ParameterizedType parameterizedType = new ParameterizedType(this.ast);
+ parameterizedType.setType(simpleType);
+ type = parameterizedType;
+//{ObjectTeams:??type anchors:
+ TypeAnchorReference[] typeAnchors = parameterizedSingleTypeReference.typeAnchors;
+ if (typeAnchors != null){
+ for (TypeAnchorReference typeAnchor: typeAnchors) {
+ TypeAnchor anchorRef = convertType(typeAnchor);
+ parameterizedType.typeArguments().add(anchorRef);
+ end = anchorRef.getStartPosition() + anchorRef.getLength() - 1;
+ }
+ }
+// SH}
+ TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
+ if (typeArguments != null) {
+ Type type2 = null;
+ for (int i = 0, max = typeArguments.length; i < max; i++) {
+ type2 = convertType(typeArguments[i]);
+ ((ParameterizedType) type).typeArguments().add(type2);
+ end = type2.getStartPosition() + type2.getLength() - 1;
+ }
+ end = retrieveClosingAngleBracketPosition(end + 1);
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ } else {
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(simpleName, typeReference);
+ this.recordNodes(simpleType, typeReference);
+ }
+ }
+ } else {
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(name));
+ // we need to search for the starting position of the first brace in order to set the proper length
+ // PR http://dev.eclipse.org/bugs/show_bug.cgi?id=10759
+ int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+ if (end == -1) {
+ end = sourceStart + length - 1;
+ }
+ simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+ final SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(simpleName);
+ type = simpleType;
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ type = simpleType;
+ if (this.resolveBindings) {
+ this.recordNodes(simpleName, typeReference);
+ }
+ }
+ if (dimensions != 0) {
+ type = this.ast.newArrayType(type, dimensions);
+ type.setSourceRange(sourceStart, length);
+ ArrayType subarrayType = (ArrayType) type;
+ int index = dimensions - 1;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ int end = retrieveProperRightBracketPosition(index, sourceStart);
+ subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+ index--;
+ }
+ if (this.resolveBindings) {
+ // store keys for inner types
+ completeRecord((ArrayType) type, typeReference);
+ }
+ }
+ } else {
+ if (typeReference instanceof ParameterizedQualifiedTypeReference) {
+ ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = (ParameterizedQualifiedTypeReference) typeReference;
+ char[][] tokens = parameterizedQualifiedTypeReference.tokens;
+ TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
+ long[] positions = parameterizedQualifiedTypeReference.sourcePositions;
+ sourceStart = (int)(positions[0]>>>32);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL : {
+ char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+ int nameLength = name.length;
+ sourceStart = (int)(positions[0]>>>32);
+ length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+ Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+ final SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(qualifiedName);
+ simpleType.setSourceRange(sourceStart, length);
+ type = simpleType;
+ }
+ break;
+ case AST.JLS3 :
+ if (typeArguments != null) {
+ int numberOfEnclosingType = 0;
+ int startingIndex = 0;
+ int endingIndex = 0;
+ for (int i = 0, max = typeArguments.length; i < max; i++) {
+ if (typeArguments[i] != null) {
+ numberOfEnclosingType++;
+ } else if (numberOfEnclosingType == 0) {
+ endingIndex++;
+ }
+ }
+ Name name = null;
+ if (endingIndex - startingIndex == 0) {
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(tokens[startingIndex]));
+ recordPendingNameScopeResolution(simpleName);
+ int start = (int)(positions[startingIndex]>>>32);
+ int end = (int) positions[startingIndex];
+ simpleName.setSourceRange(start, end - start + 1);
+ simpleName.index = 1;
+ name = simpleName;
+ if (this.resolveBindings) {
+ recordNodes(simpleName, typeReference);
+ }
+ } else {
+ name = this.setQualifiedNameNameAndSourceRanges(tokens, positions, endingIndex, typeReference);
+ }
+ SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(name);
+ int start = (int)(positions[startingIndex]>>>32);
+ int end = (int) positions[endingIndex];
+ simpleType.setSourceRange(start, end - start + 1);
+ ParameterizedType parameterizedType = new ParameterizedType(this.ast);
+ parameterizedType.setType(simpleType);
+ if (this.resolveBindings) {
+ recordNodes(simpleType, typeReference);
+ recordNodes(parameterizedType, typeReference);
+ }
+ start = simpleType.getStartPosition();
+ end = start + simpleType.getLength() - 1;
+ for (int i = 0, max = typeArguments[endingIndex].length; i < max; i++) {
+ final Type type2 = convertType(typeArguments[endingIndex][i]);
+ parameterizedType.typeArguments().add(type2);
+ end = type2.getStartPosition() + type2.getLength() - 1;
+ }
+ int indexOfEnclosingType = 1;
+ parameterizedType.index = indexOfEnclosingType;
+ end = retrieveClosingAngleBracketPosition(end + 1);
+ length = end + 1;
+ parameterizedType.setSourceRange(start, end - start + 1);
+ startingIndex = endingIndex + 1;
+ Type currentType = parameterizedType;
+ while(startingIndex < typeArguments.length) {
+ SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(tokens[startingIndex]));
+ simpleName.index = startingIndex + 1;
+ start = (int)(positions[startingIndex]>>>32);
+ end = (int) positions[startingIndex];
+ simpleName.setSourceRange(start, end - start + 1);
+ recordPendingNameScopeResolution(simpleName);
+ QualifiedType qualifiedType = new QualifiedType(this.ast);
+ qualifiedType.setQualifier(currentType);
+ qualifiedType.setName(simpleName);
+ if (this.resolveBindings) {
+ recordNodes(simpleName, typeReference);
+ recordNodes(qualifiedType, typeReference);
+ }
+ start = currentType.getStartPosition();
+ end = simpleName.getStartPosition() + simpleName.getLength() - 1;
+ qualifiedType.setSourceRange(start, end - start + 1);
+ indexOfEnclosingType++;
+ if (typeArguments[startingIndex] != null) {
+ qualifiedType.index = indexOfEnclosingType;
+ ParameterizedType parameterizedType2 = new ParameterizedType(this.ast);
+ parameterizedType2.setType(qualifiedType);
+ parameterizedType2.index = indexOfEnclosingType;
+ if (this.resolveBindings) {
+ recordNodes(parameterizedType2, typeReference);
+ }
+ for (int i = 0, max = typeArguments[startingIndex].length; i < max; i++) {
+ final Type type2 = convertType(typeArguments[startingIndex][i]);
+ parameterizedType2.typeArguments().add(type2);
+ end = type2.getStartPosition() + type2.getLength() - 1;
+ }
+ end = retrieveClosingAngleBracketPosition(end + 1);
+ length = end + 1;
+ parameterizedType2.setSourceRange(start, end - start + 1);
+ currentType = parameterizedType2;
+ } else {
+ currentType = qualifiedType;
+ qualifiedType.index = indexOfEnclosingType;
+ }
+ startingIndex++;
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(currentType, typeReference);
+ }
+ type = currentType;
+ length -= sourceStart;
+ }
+ }
+ } else {
+ char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+//{ObjectTeams: revert anchored types like in MyTeam.this._OT$base.R => base.R
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding =
+ ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).resolvedType;
+ if (typeBinding != null) {
+ typeBinding = typeBinding.leafComponentType();
+ if (typeBinding instanceof RoleTypeBinding) {
+ RoleTypeBinding rtb = (RoleTypeBinding)typeBinding;
+ if (rtb.hasExplicitAnchor()) {
+ char[][] newName = CharOperation.splitOn('.', rtb.optimalName());
+ // refuse to use best name which is longer than source name.
+ if (name.length >= newName.length)
+ name = newName;
+ }
+ }
+ }
+// SH}
+ int nameLength = name.length;
+ long[] positions = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
+ sourceStart = (int)(positions[0]>>>32);
+ length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+ final Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+ final SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(qualifiedName);
+ type = simpleType;
+ type.setSourceRange(sourceStart, length);
+ }
+
+ length = typeReference.sourceEnd - sourceStart + 1;
+ if (dimensions != 0) {
+ type = this.ast.newArrayType(type, dimensions);
+ if (this.resolveBindings) {
+ completeRecord((ArrayType) type, typeReference);
+ }
+ int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSourceLength);
+ if (end != -1) {
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ } else {
+ type.setSourceRange(sourceStart, length);
+ }
+ ArrayType subarrayType = (ArrayType) type;
+ int index = dimensions - 1;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ end = retrieveProperRightBracketPosition(index, sourceStart);
+ subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+ index--;
+ }
+ }
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(type, typeReference);
+ }
+ return type;
+ }
+
+//{ObjectTeams: convert method for OT-specific internal types
+ // LiftingTypeReference
+ public LiftingType convertType(LiftingTypeReference typeReference)
+ {
+ Name name = convert(typeReference);
+ LiftingType result = this.ast.newLiftingType(name);
+ result.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
+
+ // convert base type
+ org.eclipse.jdt.internal.compiler.ast.TypeReference baseTypeReference = typeReference.baseReference;
+ if (baseTypeReference != null)
+ {
+ Type baseType = convertType(baseTypeReference);
+ result.setBaseType(baseType);
+ }
+
+ // convert role type
+ org.eclipse.jdt.internal.compiler.ast.TypeReference roleTypeReference = typeReference.roleReference;
+ if (roleTypeReference != null)
+ {
+ Type roleType = convertType(roleTypeReference);
+ result.setRoleType(roleType);
+ }
+
+ if (this.resolveBindings)
+ {
+ this.recordNodes(result, typeReference);
+ }
+ return result;
+ }
+ // Type Anchor
+ public TypeAnchor convertType(TypeAnchorReference anchorRef) {
+ TypeAnchor result = new TypeAnchor(this.ast);
+ if (anchorRef.anchor instanceof NameReference) {
+ result.setPath(convert((NameReference)anchorRef.anchor));
+ } else if (anchorRef.anchor instanceof FieldReference) {
+ throw new InternalCompilerError("Unexpected type "+anchorRef.anchor.getClass()+" for anchor reference "+anchorRef.anchor);
+ }
+ int start = anchorRef.sourceStart;
+ int end = anchorRef.sourceEnd;
+ result.setSourceRange(start, end-start+1);
+ return result;
+ }
+//gbr+SH}
+
+ protected Comment createComment(int[] positions) {
+ // Create comment node
+ Comment comment = null;
+ int start = positions[0];
+ int end = positions[1];
+ if (positions[1]>0) { // Javadoc comments have positive end position
+ Javadoc docComment = this.docParser.parse(positions);
+ if (docComment == null) return null;
+ comment = docComment;
+ } else {
+ end = -end;
+ if (positions[0] == 0) { // we cannot know without testing chars again
+ if (this.docParser.scanner.source[1] == '/') {
+ comment = new LineComment(this.ast);
+ } else {
+ comment = new BlockComment(this.ast);
+ }
+ }
+ else if (positions[0]>0) { // Block comment have positive start position
+ comment = new BlockComment(this.ast);
+ } else { // Line comment have negative start and end position
+ start = -start;
+ comment = new LineComment(this.ast);
+ }
+ comment.setSourceRange(start, end - start);
+ }
+ return comment;
+ }
+
+ protected Statement createFakeEmptyStatement(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
+ if (statement == null) return null;
+ EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+ emptyStatement.setFlags(emptyStatement.getFlags() | ASTNode.MALFORMED);
+ int start = statement.sourceStart;
+ int end = statement.sourceEnd;
+ emptyStatement.setSourceRange(start, end - start + 1);
+ return emptyStatement;
+ }
+ /**
+ * @return a new modifier
+ */
+ private Modifier createModifier(ModifierKeyword keyword) {
+ final Modifier modifier = new Modifier(this.ast);
+ modifier.setKeyword(keyword);
+ int start = this.scanner.getCurrentTokenStartPosition();
+ int end = this.scanner.getCurrentTokenEndPosition();
+ modifier.setSourceRange(start, end - start + 1);
+ return modifier;
+ }
+
+ protected InfixExpression.Operator getOperatorFor(int operatorID) {
+ switch (operatorID) {
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ return InfixExpression.Operator.EQUALS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+ return InfixExpression.Operator.LESS_EQUALS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+ return InfixExpression.Operator.GREATER_EQUALS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ return InfixExpression.Operator.NOT_EQUALS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ return InfixExpression.Operator.LEFT_SHIFT;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
+ return InfixExpression.Operator.CONDITIONAL_OR;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
+ return InfixExpression.Operator.CONDITIONAL_AND;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
+ return InfixExpression.Operator.PLUS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
+ return InfixExpression.Operator.MINUS;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ return InfixExpression.Operator.REMAINDER;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
+ return InfixExpression.Operator.XOR;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
+ return InfixExpression.Operator.AND;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ return InfixExpression.Operator.TIMES;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
+ return InfixExpression.Operator.OR;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ return InfixExpression.Operator.DIVIDE;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
+ return InfixExpression.Operator.GREATER;
+ case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
+ return InfixExpression.Operator.LESS;
+ }
+ return null;
+ }
+
+ protected PrimitiveType.Code getPrimitiveTypeCode(char[] name) {
+ switch(name[0]) {
+ case 'i' :
+ if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+ return PrimitiveType.INT;
+ }
+ break;
+ case 'l' :
+ if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+ return PrimitiveType.LONG;
+ }
+ break;
+ case 'd' :
+ if (name.length == 6
+ && name[1] == 'o'
+ && name[2] == 'u'
+ && name[3] == 'b'
+ && name[4] == 'l'
+ && name[5] == 'e') {
+ return PrimitiveType.DOUBLE;
+ }
+ break;
+ case 'f' :
+ if (name.length == 5
+ && name[1] == 'l'
+ && name[2] == 'o'
+ && name[3] == 'a'
+ && name[4] == 't') {
+ return PrimitiveType.FLOAT;
+ }
+ break;
+ case 'b' :
+ if (name.length == 4
+ && name[1] == 'y'
+ && name[2] == 't'
+ && name[3] == 'e') {
+ return PrimitiveType.BYTE;
+ } else
+ if (name.length == 7
+ && name[1] == 'o'
+ && name[2] == 'o'
+ && name[3] == 'l'
+ && name[4] == 'e'
+ && name[5] == 'a'
+ && name[6] == 'n') {
+ return PrimitiveType.BOOLEAN;
+ }
+ break;
+ case 'c' :
+ if (name.length == 4
+ && name[1] == 'h'
+ && name[2] == 'a'
+ && name[3] == 'r') {
+ return PrimitiveType.CHAR;
+ }
+ break;
+ case 's' :
+ if (name.length == 5
+ && name[1] == 'h'
+ && name[2] == 'o'
+ && name[3] == 'r'
+ && name[4] == 't') {
+ return PrimitiveType.SHORT;
+ }
+ break;
+ case 'v' :
+ if (name.length == 4
+ && name[1] == 'o'
+ && name[2] == 'i'
+ && name[3] == 'd') {
+ return PrimitiveType.VOID;
+ }
+ }
+ return null; // cannot be reached
+ }
+
+ protected boolean isPrimitiveType(char[] name) {
+ switch(name[0]) {
+ case 'i' :
+ if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+ return true;
+ }
+ return false;
+ case 'l' :
+ if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+ return true;
+ }
+ return false;
+ case 'd' :
+ if (name.length == 6
+ && name[1] == 'o'
+ && name[2] == 'u'
+ && name[3] == 'b'
+ && name[4] == 'l'
+ && name[5] == 'e') {
+ return true;
+ }
+ return false;
+ case 'f' :
+ if (name.length == 5
+ && name[1] == 'l'
+ && name[2] == 'o'
+ && name[3] == 'a'
+ && name[4] == 't') {
+ return true;
+ }
+ return false;
+ case 'b' :
+ if (name.length == 4
+ && name[1] == 'y'
+ && name[2] == 't'
+ && name[3] == 'e') {
+ return true;
+ } else
+ if (name.length == 7
+ && name[1] == 'o'
+ && name[2] == 'o'
+ && name[3] == 'l'
+ && name[4] == 'e'
+ && name[5] == 'a'
+ && name[6] == 'n') {
+ return true;
+ }
+ return false;
+ case 'c' :
+ if (name.length == 4
+ && name[1] == 'h'
+ && name[2] == 'a'
+ && name[3] == 'r') {
+ return true;
+ }
+ return false;
+ case 's' :
+ if (name.length == 5
+ && name[1] == 'h'
+ && name[2] == 'o'
+ && name[3] == 'r'
+ && name[4] == 't') {
+ return true;
+ }
+ return false;
+ case 'v' :
+ if (name.length == 4
+ && name[1] == 'o'
+ && name[2] == 'i'
+ && name[3] == 'd') {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ private void lookupForScopes() {
+ if (this.pendingNameScopeResolution != null) {
+ for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
+ Name name = (Name) iterator.next();
+ this.ast.getBindingResolver().recordScope(name, lookupScope(name));
+ }
+ }
+ if (this.pendingThisExpressionScopeResolution != null) {
+ for (Iterator iterator = this.pendingThisExpressionScopeResolution.iterator(); iterator.hasNext(); ) {
+ ThisExpression thisExpression = (ThisExpression) iterator.next();
+ this.ast.getBindingResolver().recordScope(thisExpression, lookupScope(thisExpression));
+ }
+ }
+
+ }
+
+ private BlockScope lookupScope(ASTNode node) {
+ ASTNode currentNode = node;
+ while(currentNode != null
+ &&!(currentNode instanceof MethodDeclaration)
+ && !(currentNode instanceof Initializer)
+ && !(currentNode instanceof FieldDeclaration)
+ && !(currentNode instanceof AbstractTypeDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ if (currentNode == null) {
+ return null;
+ }
+ if (currentNode instanceof Initializer) {
+ Initializer initializer = (Initializer) currentNode;
+ while(!(currentNode instanceof AbstractTypeDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ if (currentNode instanceof TypeDeclaration
+ || currentNode instanceof EnumDeclaration
+ || currentNode instanceof AnnotationTypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ if ((initializer.getModifiers() & Modifier.STATIC) != 0) {
+ return typeDecl.staticInitializerScope;
+ } else {
+ return typeDecl.initializerScope;
+ }
+ }
+ } else if (currentNode instanceof FieldDeclaration) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) currentNode;
+ while(!(currentNode instanceof AbstractTypeDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ if ((fieldDeclaration.getModifiers() & Modifier.STATIC) != 0) {
+ return typeDecl.staticInitializerScope;
+ } else {
+ return typeDecl.initializerScope;
+ }
+ } else if (currentNode instanceof AbstractTypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ return typeDecl.initializerScope;
+ }
+ AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ return abstractMethodDeclaration.scope;
+ }
+
+ protected void recordName(Name name, org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode) {
+ if (compilerNode != null) {
+ recordNodes(name, compilerNode);
+ if (compilerNode instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) compilerNode;
+ if (name.isQualifiedName()) {
+ SimpleName simpleName = null;
+ while (name.isQualifiedName()) {
+ simpleName = ((QualifiedName) name).getName();
+ recordNodes(simpleName, typeRef);
+ name = ((QualifiedName) name).getQualifier();
+ recordNodes(name, typeRef);
+ }
+ }
+ }
+ }
+ }
+
+ protected void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+ this.ast.getBindingResolver().store(node, oldASTNode);
+ }
+
+ protected void recordNodes(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
+ Iterator fragments = tagElement.fragments().listIterator();
+ while (fragments.hasNext()) {
+ ASTNode node = (ASTNode) fragments.next();
+ if (node.getNodeType() == ASTNode.MEMBER_REF) {
+ MemberRef memberRef = (MemberRef) node;
+ Name name = memberRef.getName();
+ // get compiler node and record nodes
+ int start = name.getStartPosition();
+ org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+ if (compilerNode!= null) {
+ recordNodes(name, compilerNode);
+ recordNodes(node, compilerNode);
+ }
+ // Replace qualifier to have all nodes recorded
+ if (memberRef.getQualifier() != null) {
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = null;
+ if (compilerNode instanceof JavadocFieldReference) {
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = ((JavadocFieldReference)compilerNode).receiver;
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) expression;
+ }
+ }
+ else if (compilerNode instanceof JavadocMessageSend) {
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = ((JavadocMessageSend)compilerNode).receiver;
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) expression;
+ }
+ }
+ if (typeRef != null) {
+ recordName(memberRef.getQualifier(), typeRef);
+ }
+ }
+ } else if (node.getNodeType() == ASTNode.METHOD_REF) {
+ MethodRef methodRef = (MethodRef) node;
+ Name name = methodRef.getName();
+ // get method name start position
+ int start = methodRef.getStartPosition();
+ this.scanner.resetTo(start, start + name.getStartPosition()+name.getLength());
+ int token;
+ try {
+ nextToken: while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF && token != TerminalTokens.TokenNameLPAREN) {
+ if (token == TerminalTokens.TokenNameERROR && this.scanner.currentCharacter == '#') {
+ start = this.scanner.getCurrentTokenEndPosition()+1;
+ break nextToken;
+ }
+ }
+ }
+ catch(InvalidInputException e) {
+ // ignore
+ }
+ // get compiler node and record nodes
+ org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+ // record nodes
+ if (compilerNode != null) {
+ recordNodes(methodRef, compilerNode);
+ // get type ref
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = null;
+ if (compilerNode instanceof org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression) {
+ typeRef = ((org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression)compilerNode).type;
+ if (typeRef != null) recordNodes(name, compilerNode);
+ }
+ else if (compilerNode instanceof org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend) {
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = ((org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend)compilerNode).receiver;
+ if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.jdt.internal.compiler.ast.TypeReference) expression;
+ }
+ // TODO (frederic) remove following line to fix bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=62650
+ recordNodes(name, compilerNode);
+ }
+ // record name and qualifier
+ if (typeRef != null && methodRef.getQualifier() != null) {
+ recordName(methodRef.getQualifier(), typeRef);
+ }
+ }
+ // Resolve parameters
+ Iterator parameters = methodRef.parameters().listIterator();
+ while (parameters.hasNext()) {
+ MethodRefParameter param = (MethodRefParameter) parameters.next();
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) javadoc.getNodeStartingAt(param.getStartPosition());
+ if (expression != null) {
+ recordNodes(param, expression);
+ if (expression instanceof JavadocArgumentExpression) {
+ JavadocArgumentExpression argExpr = (JavadocArgumentExpression) expression;
+ org.eclipse.jdt.internal.compiler.ast.TypeReference typeRef = argExpr.argument.type;
+ if (this.ast.apiLevel >= AST.JLS3) param.setVarargs(argExpr.argument.isVarArgs());
+ recordNodes(param.getType(), typeRef);
+ if (param.getType().isSimpleType()) {
+ recordName(((SimpleType)param.getType()).getName(), typeRef);
+ } else if (param.getType().isArrayType()) {
+ Type type = ((ArrayType) param.getType()).getElementType();
+ recordNodes(type, typeRef);
+ if (type.isSimpleType()) {
+ recordName(((SimpleType)type).getName(), typeRef);
+ }
+ }
+ }
+ }
+ }
+ } else if (node.getNodeType() == ASTNode.SIMPLE_NAME ||
+ node.getNodeType() == ASTNode.QUALIFIED_NAME) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(node.getStartPosition());
+ recordName((Name) node, compilerNode);
+ } else if (node.getNodeType() == ASTNode.TAG_ELEMENT) {
+ // resolve member and method references binding
+ recordNodes(javadoc, (TagElement) node);
+ }
+ }
+ }
+
+ protected void recordPendingNameScopeResolution(Name name) {
+ if (this.pendingNameScopeResolution == null) {
+ this.pendingNameScopeResolution = new HashSet();
+ }
+ this.pendingNameScopeResolution.add(name);
+ }
+
+ protected void recordPendingThisExpressionScopeResolution(ThisExpression thisExpression) {
+ if (this.pendingThisExpressionScopeResolution == null) {
+ this.pendingThisExpressionScopeResolution = new HashSet();
+ }
+ this.pendingThisExpressionScopeResolution.add(thisExpression);
+ }
+
+ /**
+ * Remove whitespaces and comments before and after the expression.
+ */
+ private void trimWhiteSpacesAndComments(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
+ int start = expression.sourceStart;
+ int end = expression.sourceEnd;
+ int token;
+ int trimLeftPosition = expression.sourceStart;
+ int trimRightPosition = expression.sourceEnd;
+ boolean first = true;
+ Scanner removeBlankScanner = this.ast.scanner;
+ try {
+ removeBlankScanner.setSource(this.compilationUnitSource);
+ removeBlankScanner.resetTo(start, end);
+ while (true) {
+ token = removeBlankScanner.getNextToken();
+ switch (token) {
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ if (first) {
+ trimLeftPosition = removeBlankScanner.currentPosition;
+ }
+ break;
+ case TerminalTokens.TokenNameWHITESPACE :
+ if (first) {
+ trimLeftPosition = removeBlankScanner.currentPosition;
+ }
+ break;
+ case TerminalTokens.TokenNameEOF :
+ expression.sourceStart = trimLeftPosition;
+ expression.sourceEnd = trimRightPosition;
+ return;
+ default :
+ /*
+ * if we find something else than a whitespace or a comment,
+ * then we reset the trimRigthPosition to the expression
+ * source end.
+ */
+ trimRightPosition = removeBlankScanner.currentPosition - 1;
+ first = false;
+ }
+ }
+ } catch (InvalidInputException e){
+ // ignore
+ }
+ }
+
+ /**
+ * Remove potential trailing comment by settings the source end on the closing parenthesis
+ */
+ protected void removeLeadingAndTrailingCommentsFromLiteral(ASTNode node) {
+ int start = node.getStartPosition();
+ this.scanner.resetTo(start, start + node.getLength());
+ int token;
+ int startPosition = -1;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameIntegerLiteral :
+ case TerminalTokens.TokenNameFloatingPointLiteral :
+ case TerminalTokens.TokenNameLongLiteral :
+ case TerminalTokens.TokenNameDoubleLiteral :
+ case TerminalTokens.TokenNameCharacterLiteral :
+ if (startPosition == -1) {
+ startPosition = this.scanner.startPosition;
+ }
+ int end = this.scanner.currentPosition;
+ node.setSourceRange(startPosition, end - startPosition);
+ return;
+ case TerminalTokens.TokenNameMINUS :
+ startPosition = this.scanner.startPosition;
+ break;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Remove potential trailing comment by settings the source end on the closing parenthesis
+ */
+ protected void removeTrailingCommentFromExpressionEndingWithAParen(ASTNode node) {
+ int start = node.getStartPosition();
+ this.scanner.resetTo(start, start + node.getLength());
+ int token;
+ int parenCounter = 0;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLPAREN :
+ parenCounter++;
+ break;
+ case TerminalTokens.TokenNameRPAREN :
+ parenCounter--;
+ if (parenCounter == 0) {
+ int end = this.scanner.currentPosition - 1;
+ node.setSourceRange(start, end - start + 1);
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * This method is used to retrieve the end position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveClosingAngleBracketPosition(int start) {
+ this.scanner.resetTo(start, this.compilationUnitSourceLength);
+ this.scanner.returnOnlyGreater = true;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameGREATER:
+ return this.scanner.currentPosition - 1;
+ default:
+ return start;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ this.scanner.returnOnlyGreater = false;
+ return start;
+ }
+
+ /**
+ * This method is used to set the right end position for expression
+ * statement. The actual AST nodes don't include the trailing semicolon.
+ * This method fixes the length of the corresponding node.
+ */
+ protected void retrieveColonPosition(ASTNode node) {
+ int start = node.getStartPosition();
+ int length = node.getLength();
+ int end = start + length;
+ this.scanner.resetTo(end, this.compilationUnitSourceLength);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOLON:
+ node.setSourceRange(start, this.scanner.currentPosition - start);
+ return;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ /**
+ * This method is used to retrieve the start position of the Ellipsis
+ */
+ protected int retrieveEllipsisStartPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameELLIPSIS:
+ return this.scanner.startPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+
+ }
+ /**
+ * This method is used to retrieve the end position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveEndBlockPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int count = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE://110
+ count++;
+ break;
+ case TerminalTokens.TokenNameRBRACE://95
+ count--;
+ if (count == 0) {
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ protected int retrieveSemiColonPosition(Expression node) {
+ int start = node.getStartPosition();
+ int length = node.getLength();
+ int end = start + length;
+ this.scanner.resetTo(end, this.compilationUnitSourceLength);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameSEMICOLON:
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
+ * name.
+ * For example:
+ * int[] i; => return 5, but int i[] => return -1;
+ * @return int the dimension found
+ */
+ protected int retrieveEndOfDimensionsPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int foundPosition = -1;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACKET:
+ case TerminalTokens.TokenNameCOMMENT_BLOCK:
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+ case TerminalTokens.TokenNameCOMMENT_LINE:
+ break;
+ case TerminalTokens.TokenNameRBRACKET://166
+ foundPosition = this.scanner.currentPosition - 1;
+ break;
+ default:
+ return foundPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return foundPosition;
+ }
+
+ /**
+ * This method is used to retrieve the position just before the left bracket.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveEndOfElementTypeNamePosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameIdentifier:
+ case TerminalTokens.TokenNamebyte:
+ case TerminalTokens.TokenNamechar:
+ case TerminalTokens.TokenNamedouble:
+ case TerminalTokens.TokenNamefloat:
+ case TerminalTokens.TokenNameint:
+ case TerminalTokens.TokenNamelong:
+ case TerminalTokens.TokenNameshort:
+ case TerminalTokens.TokenNameboolean:
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the position after the right parenthesis.
+ * @return int the position found
+ */
+ protected int retrieveEndOfRightParenthesisPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRPAREN:
+ return this.scanner.currentPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the array dimension declared after the
+ * name of a local or a field declaration.
+ * For example:
+ * int i, j[] = null, k[][] = {{}};
+ * It should return 0 for i, 1 for j and 2 for k.
+ * @return int the dimension found
+ */
+ protected int retrieveExtraDimension(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int dimensions = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACKET:
+ case TerminalTokens.TokenNameCOMMENT_BLOCK:
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+ case TerminalTokens.TokenNameCOMMENT_LINE:
+ break;
+ case TerminalTokens.TokenNameRBRACKET://166
+ dimensions++;
+ break;
+ default:
+ return dimensions;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return dimensions;
+ }
+
+ protected void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
+ this.scanner.resetTo(start, end);
+ int token;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ if (token == TerminalTokens.TokenNameIdentifier) {
+ int startName = this.scanner.startPosition;
+ int endName = this.scanner.currentPosition - 1;
+ name.setSourceRange(startName, endName - startName + 1);
+ return;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * This method is used to retrieve the start position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveIdentifierEndPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+//{ObjectTeams: treat like an Identifier:
+ case TerminalTokens.TokenNamewhen:
+//SH}
+ case TerminalTokens.TokenNameIdentifier://110
+ return this.scanner.getCurrentTokenEndPosition();
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next comma or semi-colon.
+ * @param initializerEnd the given initializer end exclusive
+ * @return int the position found.
+ */
+ protected int retrieveEndOfPotentialExtendedDimensions(int initializerEnd, int nameEnd, int end) {
+ this.scanner.resetTo(initializerEnd, end);
+ boolean hasTokens = false;
+ int balance = 0;
+ int pos = initializerEnd > nameEnd ? initializerEnd - 1 : nameEnd;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ hasTokens = true;
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE :
+ case TerminalTokens.TokenNameLBRACKET :
+ balance++;
+ break;
+ case TerminalTokens.TokenNameRBRACKET :
+ case TerminalTokens.TokenNameRBRACE :
+ balance --;
+ pos = this.scanner.currentPosition - 1;
+ break;
+ case TerminalTokens.TokenNameCOMMA :
+ if (balance == 0) return pos;
+ // case where a missing closing brace doesn't close an array initializer
+ pos = this.scanner.currentPosition - 1;
+ break;
+ case TerminalTokens.TokenNameSEMICOLON :
+ if (balance == 0) return pos;
+ return -pos;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ // no token, we simply return pos as the right position
+ return hasTokens ? Integer.MIN_VALUE : pos;
+ }
+
+ protected int retrieveProperRightBracketPosition(int bracketNumber, int start) {
+ this.scanner.resetTo(start, this.compilationUnitSourceLength);
+ try {
+ int token, count = 0;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACKET:
+ count++;
+ if (count == bracketNumber) {
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next right brace or semi-colon.
+ * @return int the position found.
+ */
+ protected int retrieveRightBraceOrSemiColonPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACE :
+ return this.scanner.currentPosition - 1;
+ case TerminalTokens.TokenNameSEMICOLON :
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next right brace or semi-colon.
+ * @return int the position found.
+ */
+ protected int retrieveRightBrace(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACE :
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the position of the right bracket.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveRightBracketPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ int balance = 0;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACKET :
+ balance++;
+ break;
+ case TerminalTokens.TokenNameRBRACKET :
+ balance--;
+ if (balance == 0) return this.scanner.currentPosition - 1;
+ break;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the start position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveStartBlockPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE://110
+ return this.scanner.startPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the starting position of the catch keyword.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveStartingCatchPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNamecatch://225
+ return this.scanner.startPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+//{ObjectTeams:
+ /**
+ * This method is used to retrieve the starting position of a '<-' token
+ * @return int the position found, -1 if none
+ */
+ protected int retrieveBINDINPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameBINDIN://225
+ return this.scanner.startPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+// SH}
+
+ public void setAST(AST ast) {
+//{ObjectTeams: transfer scanner mode
+ if (ast.scanner != null && this.scanner != null)
+ ast.scanner.copyOTFlags(this.scanner);
+// SH}
+ this.ast = ast;
+ this.docParser = new DocCommentParser(this.ast, this.scanner, this.insideComments);
+ }
+
+ protected void setModifiers(AnnotationTypeDeclaration typeDecl, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+ this.setModifiers(typeDecl, typeDeclaration.annotations, typeDeclaration.sourceStart);
+ }
+
+ protected void setModifiers(AnnotationTypeMemberDeclaration annotationTypeMemberDecl, org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+ this.scanner.resetTo(annotationTypeMemberDeclaration.declarationSourceStart, annotationTypeMemberDeclaration.sourceStart);
+ this.setModifiers(annotationTypeMemberDecl, annotationTypeMemberDeclaration.annotations, annotationTypeMemberDeclaration.sourceStart);
+ }
+
+ /**
+ * @param bodyDeclaration
+ */
+ protected void setModifiers(BodyDeclaration bodyDeclaration, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) {
+ this.scanner.tokenizeWhiteSpace = false;
+ try {
+ int token;
+ int indexInAnnotations = 0;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+//{ObjectTeams: callin team
+ case TerminalTokens.TokenNamecallin:
+ modifier = createModifier(Modifier.ModifierKeyword.CALLIN_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameteam:
+ modifier = createModifier(Modifier.ModifierKeyword.TEAM_KEYWORD);
+ break;
+// SH}
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, modifiersEnd);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ // there is some syntax errors in source code
+ break;
+ }
+ if (modifier != null) {
+ bodyDeclaration.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ protected void setModifiers(EnumDeclaration enumDeclaration, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enumDeclaration2) {
+ this.scanner.resetTo(enumDeclaration2.declarationSourceStart, enumDeclaration2.sourceStart);
+ this.setModifiers(enumDeclaration, enumDeclaration2.annotations, enumDeclaration2.sourceStart);
+ }
+
+ protected void setModifiers(EnumConstantDeclaration enumConstantDeclaration, org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ enumConstantDeclaration.internalSetModifiers(fieldDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (fieldDeclaration.annotations != null) {
+ enumConstantDeclaration.setFlags(enumConstantDeclaration.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(fieldDeclaration.declarationSourceStart, fieldDeclaration.sourceStart);
+ this.setModifiers(enumConstantDeclaration, fieldDeclaration.annotations, fieldDeclaration.sourceStart);
+ }
+ }
+
+ /**
+ * @param fieldDeclaration
+ * @param fieldDecl
+ */
+ protected void setModifiers(FieldDeclaration fieldDeclaration, org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ fieldDeclaration.internalSetModifiers(fieldDecl.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (fieldDecl.annotations != null) {
+ fieldDeclaration.setFlags(fieldDeclaration.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(fieldDecl.declarationSourceStart, fieldDecl.sourceStart);
+ this.setModifiers(fieldDeclaration, fieldDecl.annotations, fieldDecl.sourceStart);
+ }
+ }
+
+ /**
+ * @param initializer
+ * @param oldInitializer
+ */
+ protected void setModifiers(Initializer initializer, org.eclipse.jdt.internal.compiler.ast.Initializer oldInitializer) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL:
+ initializer.internalSetModifiers(oldInitializer.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (oldInitializer.annotations != null) {
+ initializer.setFlags(initializer.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(oldInitializer.declarationSourceStart, oldInitializer.bodyStart);
+ this.setModifiers(initializer, oldInitializer.annotations, oldInitializer.bodyStart);
+ }
+ }
+ /**
+ * @param methodDecl
+ * @param methodDeclaration
+ */
+ protected void setModifiers(MethodDeclaration methodDecl, AbstractMethodDeclaration methodDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDecl.internalSetModifiers(methodDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (methodDeclaration.annotations != null) {
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(methodDeclaration.declarationSourceStart, methodDeclaration.sourceStart);
+ this.setModifiers(methodDecl, methodDeclaration.annotations, methodDeclaration.sourceStart);
+ }
+ }
+//{ObjectTeams: annotations for method mappings:
+ /**
+ * @param methodDecl
+ * @param methodDeclaration
+ */
+ protected void setModifiers(org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration mappingDecl,
+ AbstractMethodMappingDeclaration mappingDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ if (mappingDeclaration.annotations != null) {
+ mappingDecl.setFlags(mappingDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(mappingDeclaration.declarationSourceStart, mappingDeclaration.sourceStart);
+ this.setModifiers(mappingDecl, mappingDeclaration.annotations, mappingDeclaration.sourceStart);
+ }
+ }
+// SH}
+ /**
+ * @param variableDecl
+ * @param argument
+ */
+ protected void setModifiers(SingleVariableDeclaration variableDecl, Argument argument) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.internalSetModifiers(argument.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (argument.annotations != null) {
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(argument.declarationSourceStart, argument.sourceStart);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = argument.annotations;
+ int indexInAnnotations = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDecl.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected void setModifiers(SingleVariableDeclaration variableDecl, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.internalSetModifiers(localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (localDeclaration.annotations != null) {
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+ int indexInAnnotations = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDecl.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * @param typeDecl
+ * @param typeDeclaration
+ */
+ protected void setModifiers(TypeDeclaration typeDecl, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = typeDeclaration.modifiers;
+ modifiers &= ~ClassFileConstants.AccInterface; // remove AccInterface flags
+ modifiers &= ExtraCompilerModifiers.AccJustFlag;
+ typeDecl.internalSetModifiers(modifiers);
+ if (typeDeclaration.annotations != null) {
+ typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+ this.setModifiers(typeDecl, typeDeclaration.annotations, typeDeclaration.sourceStart);
+ }
+ }
+
+ /**
+ * @param variableDeclarationExpression
+ * @param localDeclaration
+ */
+ protected void setModifiers(VariableDeclarationExpression variableDeclarationExpression, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+ modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+ variableDeclarationExpression.internalSetModifiers(modifiers);
+ if (localDeclaration.annotations != null) {
+ variableDeclarationExpression.setFlags(variableDeclarationExpression.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+ int indexInAnnotations = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDeclarationExpression.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * @param variableDeclarationStatement
+ * @param localDeclaration
+ */
+ protected void setModifiers(VariableDeclarationStatement variableDeclarationStatement, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+ modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+ variableDeclarationStatement.internalSetModifiers(modifiers);
+ if (localDeclaration.annotations != null) {
+ variableDeclarationStatement.setFlags(variableDeclarationStatement.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+ int indexInAnnotations = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDeclarationStatement.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
+ int length = typeName.length;
+ final SimpleName firstToken = new SimpleName(this.ast);
+ firstToken.internalSetIdentifier(new String(typeName[0]));
+ firstToken.index = 1;
+ int start0 = (int)(positions[0]>>>32);
+ int start = start0;
+ int end = (int)(positions[0] & 0xFFFFFFFF);
+ firstToken.setSourceRange(start, end - start + 1);
+ final SimpleName secondToken = new SimpleName(this.ast);
+ secondToken.internalSetIdentifier(new String(typeName[1]));
+ secondToken.index = 2;
+ start = (int)(positions[1]>>>32);
+ end = (int)(positions[1] & 0xFFFFFFFF);
+ secondToken.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName = new QualifiedName(this.ast);
+ qualifiedName.setQualifier(firstToken);
+ qualifiedName.setName(secondToken);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordNodes(firstToken, node);
+ recordNodes(secondToken, node);
+ recordPendingNameScopeResolution(firstToken);
+ recordPendingNameScopeResolution(secondToken);
+ }
+ qualifiedName.index = 2;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ SimpleName newPart = null;
+ for (int i = 2; i < length; i++) {
+ newPart = new SimpleName(this.ast);
+ newPart.internalSetIdentifier(new String(typeName[i]));
+ newPart.index = i + 1;
+ start = (int)(positions[i]>>>32);
+ end = (int)(positions[i] & 0xFFFFFFFF);
+ newPart.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+ qualifiedName2.setQualifier(qualifiedName);
+ qualifiedName2.setName(newPart);
+ qualifiedName = qualifiedName2;
+ qualifiedName.index = newPart.index;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordNodes(newPart, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordPendingNameScopeResolution(newPart);
+ }
+ }
+ QualifiedName name = qualifiedName;
+ if (this.resolveBindings) {
+ recordNodes(name, node);
+ recordPendingNameScopeResolution(name);
+ }
+ return name;
+ }
+
+ protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, int endingIndex, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
+ int length = endingIndex + 1;
+ final SimpleName firstToken = new SimpleName(this.ast);
+ firstToken.internalSetIdentifier(new String(typeName[0]));
+ firstToken.index = 1;
+ int start0 = (int)(positions[0]>>>32);
+ int start = start0;
+ int end = (int) positions[0];
+ firstToken.setSourceRange(start, end - start + 1);
+ final SimpleName secondToken = new SimpleName(this.ast);
+ secondToken.internalSetIdentifier(new String(typeName[1]));
+ secondToken.index = 2;
+ start = (int)(positions[1]>>>32);
+ end = (int) positions[1];
+ secondToken.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName = new QualifiedName(this.ast);
+ qualifiedName.setQualifier(firstToken);
+ qualifiedName.setName(secondToken);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordNodes(firstToken, node);
+ recordNodes(secondToken, node);
+ recordPendingNameScopeResolution(firstToken);
+ recordPendingNameScopeResolution(secondToken);
+ }
+ qualifiedName.index = 2;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ SimpleName newPart = null;
+ for (int i = 2; i < length; i++) {
+ newPart = new SimpleName(this.ast);
+ newPart.internalSetIdentifier(new String(typeName[i]));
+ newPart.index = i + 1;
+ start = (int)(positions[i]>>>32);
+ end = (int) positions[i];
+ newPart.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+ qualifiedName2.setQualifier(qualifiedName);
+ qualifiedName2.setName(newPart);
+ qualifiedName = qualifiedName2;
+ qualifiedName.index = newPart.index;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordNodes(newPart, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordPendingNameScopeResolution(newPart);
+ }
+ }
+ if (newPart == null && this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ }
+ return qualifiedName;
+ }
+
+ protected void setTypeNameForAnnotation(org.eclipse.jdt.internal.compiler.ast.Annotation compilerAnnotation, Annotation annotation) {
+ TypeReference typeReference = compilerAnnotation.type;
+ if (typeReference instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) typeReference;
+ char[][] tokens = qualifiedTypeReference.tokens;
+ long[] positions = qualifiedTypeReference.sourcePositions;
+ // QualifiedName
+ annotation.setTypeName(setQualifiedNameNameAndSourceRanges(tokens, positions, typeReference));
+ } else {
+ SingleTypeReference singleTypeReference = (SingleTypeReference) typeReference;
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(singleTypeReference.token));
+ int start = singleTypeReference.sourceStart;
+ int end = singleTypeReference.sourceEnd;
+ name.setSourceRange(start, end - start + 1);
+ name.index = 1;
+ annotation.setTypeName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, typeReference);
+ }
+ }
+ }
+
+ protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ fieldDeclaration.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ fieldDeclaration.setType(subarrayType);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ fieldDeclaration.setType(type);
+ }
+ } else {
+ if (type.isArrayType()) {
+ // update positions of the component types of the array type
+ int dimensions = ((ArrayType) type).getDimensions();
+ updateInnerPositions(type, dimensions);
+ }
+ fieldDeclaration.setType(type);
+ }
+ }
+
+ protected void setTypeForMethodDeclaration(MethodDeclaration methodDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(elementType);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(elementType);
+ break;
+ }
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(subarrayType);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(subarrayType);
+ break;
+ }
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(type);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(type);
+ break;
+ }
+ }
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(type);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(type);
+ break;
+ }
+ }
+ }
+
+ protected void setTypeForMethodDeclaration(AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration, Type type, int extraDimension) {
+ annotationTypeMemberDeclaration.setType(type);
+ }
+
+ protected void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ singleVariableDeclaration.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ singleVariableDeclaration.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ singleVariableDeclaration.setType(type);
+ }
+ } else {
+ singleVariableDeclaration.setType(type);
+ }
+ }
+
+ protected void setTypeForVariableDeclarationExpression(VariableDeclarationExpression variableDeclarationExpression, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ variableDeclarationExpression.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ variableDeclarationExpression.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ variableDeclarationExpression.setType(type);
+ }
+ } else {
+ variableDeclarationExpression.setType(type);
+ }
+ }
+
+ protected void setTypeForVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ variableDeclarationStatement.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ variableDeclarationStatement.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ variableDeclarationStatement.setType(type);
+ }
+ } else {
+ variableDeclarationStatement.setType(type);
+ }
+ }
+
+ protected void updateInnerPositions(Type type, int dimensions) {
+ if (dimensions > 1) {
+ // need to set positions for intermediate array type see 42839
+ int start = type.getStartPosition();
+ Type currentComponentType = ((ArrayType) type).getComponentType();
+ int searchedDimension = dimensions - 1;
+ int rightBracketEndPosition = start;
+ while (currentComponentType.isArrayType()) {
+ rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start);
+ currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
+ currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+ searchedDimension--;
+ }
+ }
+ }
+//{ObjectTeams: convert reused abstract methode declaration
+ private boolean isReusedAbstractMethodDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration,
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration)
+ {
+ return (methodDeclaration.isReusingSourceMethod && methodDeclaration.sourceStart > 0 );
+ }
+
+ public MethodDeclaration convertReusedAbstractMethodDeclaration(
+ org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration)
+ {
+ MethodDeclaration methodDecl = (MethodDeclaration) convert(methodDeclaration);
+ if(methodDecl.ast.apiLevel() == AST.JLS2)
+ methodDecl.setModifiers(methodDecl.getModifiers() | Modifier.ABSTRACT);
+ else
+ methodDecl.modifiers().addAll(ast.newModifiers(methodDecl.getModifiers() | Modifier.ABSTRACT));
+ return methodDecl;
+ }
+//jsv}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
new file mode 100644
index 000000000..412ec4183
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -0,0 +1,2843 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTMatcher.java 22567 2009-09-22 16:34:06Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Concrete superclass and default implementation of an AST subtree matcher.
+ * <p>
+ * For example, to compute whether two ASTs subtrees are structurally
+ * isomorphic, use <code>n1.subtreeMatch(new ASTMatcher(), n2)</code> where
+ * <code>n1</code> and <code>n2</code> are the AST root nodes of the subtrees.
+ * </p>
+ * <p>
+ * For each different concrete AST node type <i>T</i> there is a
+ * <code>public boolean match(<i>T</i> node, Object other)</code> method
+ * that matches the given node against another object (typically another
+ * AST node, although this is not essential). The default implementations
+ * provided by this class tests whether the other object is a node of the
+ * same type with structurally isomorphic child subtrees. For nodes with
+ * list-valued properties, the child nodes within the list are compared in
+ * order. For nodes with multiple properties, the child nodes are compared
+ * in the order that most closely corresponds to the lexical reading order
+ * of the source program. For instance, for a type declaration node, the
+ * child ordering is: name, superclass, superinterfaces, and body
+ * declarations.
+ * </p>
+ * <p>
+ * Subclasses may override (extend or reimplement) some or all of the
+ * <code>match</code> methods in order to define more specialized subtree
+ * matchers.
+ * </p>
+ *
+ * @see org.eclipse.jdt.core.dom.ASTNode#subtreeMatch(ASTMatcher, Object)
+ * @since 2.0
+ */
+@SuppressWarnings("unchecked")
+public class ASTMatcher {
+
+ /**
+ * Indicates whether doc tags should be matched.
+ * @since 3.0
+ */
+ private boolean matchDocTags;
+
+ /**
+ * Creates a new AST matcher instance.
+ * <p>
+ * For backwards compatibility, the matcher ignores tag
+ * elements below doc comments by default. Use
+ * {@link #ASTMatcher(boolean) ASTMatcher(true)}
+ * for a matcher that compares doc tags by default.
+ * </p>
+ */
+ public ASTMatcher() {
+ this(false);
+ }
+
+ /**
+ * Creates a new AST matcher instance.
+ *
+ * @param matchDocTags <code>true</code> if doc comment tags are
+ * to be compared by default, and <code>false</code> otherwise
+ * @see #match(Javadoc,Object)
+ * @since 3.0
+ */
+ public ASTMatcher(boolean matchDocTags) {
+ this.matchDocTags = matchDocTags;
+ }
+
+ /**
+ * Returns whether the given lists of AST nodes match pair wise according
+ * to <code>ASTNode.subtreeMatch</code>.
+ * <p>
+ * Note that this is a convenience method, useful for writing recursive
+ * subtree matchers.
+ * </p>
+ *
+ * @param list1 the first list of AST nodes
+ * (element type: <code>ASTNode</code>)
+ * @param list2 the second list of AST nodes
+ * (element type: <code>ASTNode</code>)
+ * @return <code>true</code> if the lists have the same number of elements
+ * and match pair-wise according to <code>ASTNode.subtreeMatch</code>
+ * @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
+ */
+ public final boolean safeSubtreeListMatch(List list1, List list2) {
+ int size1 = list1.size();
+ int size2 = list2.size();
+ if (size1 != size2) {
+ return false;
+ }
+ for (Iterator it1 = list1.iterator(), it2 = list2.iterator(); it1.hasNext();) {
+ ASTNode n1 = (ASTNode) it1.next();
+ ASTNode n2 = (ASTNode) it2.next();
+ if (!n1.subtreeMatch(this, n2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given nodes match according to
+ * <code>AST.subtreeMatch</code>. Returns <code>false</code> if one or
+ * the other of the nodes are <code>null</code>. Returns <code>true</code>
+ * if both nodes are <code>null</code>.
+ * <p>
+ * Note that this is a convenience method, useful for writing recursive
+ * subtree matchers.
+ * </p>
+ *
+ * @param node1 the first AST node, or <code>null</code>; must be an
+ * instance of <code>ASTNode</code>
+ * @param node2 the second AST node, or <code>null</code>; must be an
+ * instance of <code>ASTNode</code>
+ * @return <code>true</code> if the nodes match according
+ * to <code>AST.subtreeMatch</code> or both are <code>null</code>, and
+ * <code>false</code> otherwise
+ * @see ASTNode#subtreeMatch(ASTMatcher, Object)
+ */
+ public final boolean safeSubtreeMatch(Object node1, Object node2) {
+ if (node1 == null && node2 == null) {
+ return true;
+ }
+ if (node1 == null || node2 == null) {
+ return false;
+ }
+ // N.B. call subtreeMatch even node1==node2!=null
+ return ((ASTNode) node1).subtreeMatch(this, node2);
+ }
+
+ /**
+ * Returns whether the given objects are equal according to
+ * <code>equals</code>. Returns <code>false</code> if either
+ * node is <code>null</code>.
+ *
+ * @param o1 the first object, or <code>null</code>
+ * @param o2 the second object, or <code>null</code>
+ * @return <code>true</code> if the nodes are equal according to
+ * <code>equals</code> or both <code>null</code>, and
+ * <code>false</code> otherwise
+ */
+ public static boolean safeEquals(Object o1, Object o2) {
+ if (o1 == o2) {
+ return true;
+ }
+ if (o1 == null || o2 == null) {
+ return false;
+ }
+ return o1.equals(o2);
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(AnnotationTypeDeclaration node, Object other) {
+ if (!(other instanceof AnnotationTypeDeclaration)) {
+ return false;
+ }
+ AnnotationTypeDeclaration o = (AnnotationTypeDeclaration) other;
+ // node type added in JLS3 - ignore old JLS2-style modifiers
+ return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(AnnotationTypeMemberDeclaration node, Object other) {
+ if (!(other instanceof AnnotationTypeMemberDeclaration)) {
+ return false;
+ }
+ AnnotationTypeMemberDeclaration o = (AnnotationTypeMemberDeclaration) other;
+ // node type added in JLS3 - ignore old JLS2-style modifiers
+ return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+ && safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeMatch(node.getDefault(), o.getDefault()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(AnonymousClassDeclaration node, Object other) {
+ if (!(other instanceof AnonymousClassDeclaration)) {
+ return false;
+ }
+ AnonymousClassDeclaration o = (AnonymousClassDeclaration) other;
+ return safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ArrayAccess node, Object other) {
+ if (!(other instanceof ArrayAccess)) {
+ return false;
+ }
+ ArrayAccess o = (ArrayAccess) other;
+ return (
+ safeSubtreeMatch(node.getArray(), o.getArray())
+ && safeSubtreeMatch(node.getIndex(), o.getIndex()));
+ }
+
+ /**
+ * Returns whether the given node and the other object object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ArrayCreation node, Object other) {
+ if (!(other instanceof ArrayCreation)) {
+ return false;
+ }
+ ArrayCreation o = (ArrayCreation) other;
+ return (
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.dimensions(), o.dimensions())
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ArrayInitializer node, Object other) {
+ if (!(other instanceof ArrayInitializer)) {
+ return false;
+ }
+ ArrayInitializer o = (ArrayInitializer) other;
+ return safeSubtreeListMatch(node.expressions(), o.expressions());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ArrayType node, Object other) {
+ if (!(other instanceof ArrayType)) {
+ return false;
+ }
+ ArrayType o = (ArrayType) other;
+ return safeSubtreeMatch(node.getComponentType(), o.getComponentType());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(AssertStatement node, Object other) {
+ if (!(other instanceof AssertStatement)) {
+ return false;
+ }
+ AssertStatement o = (AssertStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getMessage(), o.getMessage()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(Assignment node, Object other) {
+ if (!(other instanceof Assignment)) {
+ return false;
+ }
+ Assignment o = (Assignment) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getLeftHandSide(), o.getLeftHandSide())
+ && safeSubtreeMatch(node.getRightHandSide(), o.getRightHandSide()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(Block node, Object other) {
+ if (!(other instanceof Block)) {
+ return false;
+ }
+ Block o = (Block) other;
+ return safeSubtreeListMatch(node.statements(), o.statements());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type. Subclasses may override
+ * this method as needed.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(BlockComment node, Object other) {
+ if (!(other instanceof BlockComment)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(BooleanLiteral node, Object other) {
+ if (!(other instanceof BooleanLiteral)) {
+ return false;
+ }
+ BooleanLiteral o = (BooleanLiteral) other;
+ return node.booleanValue() == o.booleanValue();
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(BreakStatement node, Object other) {
+ if (!(other instanceof BreakStatement)) {
+ return false;
+ }
+ BreakStatement o = (BreakStatement) other;
+ return safeSubtreeMatch(node.getLabel(), o.getLabel());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CastExpression node, Object other) {
+ if (!(other instanceof CastExpression)) {
+ return false;
+ }
+ CastExpression o = (CastExpression) other;
+ return (
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getExpression(), o.getExpression()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CatchClause node, Object other) {
+ if (!(other instanceof CatchClause)) {
+ return false;
+ }
+ CatchClause o = (CatchClause) other;
+ return (
+ safeSubtreeMatch(node.getException(), o.getException())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CharacterLiteral node, Object other) {
+ if (!(other instanceof CharacterLiteral)) {
+ return false;
+ }
+ CharacterLiteral o = (CharacterLiteral) other;
+ return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ClassInstanceCreation node, Object other) {
+ if (!(other instanceof ClassInstanceCreation)) {
+ return false;
+ }
+ ClassInstanceCreation o = (ClassInstanceCreation) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (!safeSubtreeMatch(node.internalGetName(), o.internalGetName())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getType(), o.getType())) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.arguments(), o.arguments())
+ && safeSubtreeMatch(
+ node.getAnonymousClassDeclaration(),
+ o.getAnonymousClassDeclaration());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CompilationUnit node, Object other) {
+ if (!(other instanceof CompilationUnit)) {
+ return false;
+ }
+ CompilationUnit o = (CompilationUnit) other;
+ return (
+ safeSubtreeMatch(node.getPackage(), o.getPackage())
+ && safeSubtreeListMatch(node.imports(), o.imports())
+ && safeSubtreeListMatch(node.types(), o.types()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ConditionalExpression node, Object other) {
+ if (!(other instanceof ConditionalExpression)) {
+ return false;
+ }
+ ConditionalExpression o = (ConditionalExpression) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getThenExpression(), o.getThenExpression())
+ && safeSubtreeMatch(node.getElseExpression(), o.getElseExpression()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ConstructorInvocation node, Object other) {
+ if (!(other instanceof ConstructorInvocation)) {
+ return false;
+ }
+ ConstructorInvocation o = (ConstructorInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return safeSubtreeListMatch(node.arguments(), o.arguments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ContinueStatement node, Object other) {
+ if (!(other instanceof ContinueStatement)) {
+ return false;
+ }
+ ContinueStatement o = (ContinueStatement) other;
+ return safeSubtreeMatch(node.getLabel(), o.getLabel());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(DoStatement node, Object other) {
+ if (!(other instanceof DoStatement)) {
+ return false;
+ }
+ DoStatement o = (DoStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(EmptyStatement node, Object other) {
+ if (!(other instanceof EmptyStatement)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(EnhancedForStatement node, Object other) {
+ if (!(other instanceof EnhancedForStatement)) {
+ return false;
+ }
+ EnhancedForStatement o = (EnhancedForStatement) other;
+ return (
+ safeSubtreeMatch(node.getParameter(), o.getParameter())
+ && safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(EnumConstantDeclaration node, Object other) {
+ if (!(other instanceof EnumConstantDeclaration)) {
+ return false;
+ }
+ EnumConstantDeclaration o = (EnumConstantDeclaration) other;
+ return (
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.arguments(), o.arguments())
+ && safeSubtreeMatch(
+ node.getAnonymousClassDeclaration(),
+ o.getAnonymousClassDeclaration()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(EnumDeclaration node, Object other) {
+ if (!(other instanceof EnumDeclaration)) {
+ return false;
+ }
+ EnumDeclaration o = (EnumDeclaration) other;
+ return (
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())
+ && safeSubtreeListMatch(node.enumConstants(), o.enumConstants())
+ && safeSubtreeListMatch(
+ node.bodyDeclarations(),
+ o.bodyDeclarations()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ExpressionStatement node, Object other) {
+ if (!(other instanceof ExpressionStatement)) {
+ return false;
+ }
+ ExpressionStatement o = (ExpressionStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(FieldAccess node, Object other) {
+ if (!(other instanceof FieldAccess)) {
+ return false;
+ }
+ FieldAccess o = (FieldAccess) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(FieldDeclaration node, Object other) {
+ if (!(other instanceof FieldDeclaration)) {
+ return false;
+ }
+ FieldDeclaration o = (FieldDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ForStatement node, Object other) {
+ if (!(other instanceof ForStatement)) {
+ return false;
+ }
+ ForStatement o = (ForStatement) other;
+ return (
+ safeSubtreeListMatch(node.initializers(), o.initializers())
+ && safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.updaters(), o.updaters())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(IfStatement node, Object other) {
+ if (!(other instanceof IfStatement)) {
+ return false;
+ }
+ IfStatement o = (IfStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getThenStatement(), o.getThenStatement())
+ && safeSubtreeMatch(node.getElseStatement(), o.getElseStatement()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ImportDeclaration node, Object other) {
+ if (!(other instanceof ImportDeclaration)) {
+ return false;
+ }
+ ImportDeclaration o = (ImportDeclaration) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (node.isStatic() != o.isStatic()) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getName(), o.getName())
+ && node.isOnDemand() == o.isOnDemand());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(InfixExpression node, Object other) {
+ if (!(other instanceof InfixExpression)) {
+ return false;
+ }
+ InfixExpression o = (InfixExpression) other;
+ // be careful not to trigger lazy creation of extended operand lists
+ if (node.hasExtendedOperands() && o.hasExtendedOperands()) {
+ if (!safeSubtreeListMatch(node.extendedOperands(), o.extendedOperands())) {
+ return false;
+ }
+ }
+ if (node.hasExtendedOperands() != o.hasExtendedOperands()) {
+ return false;
+ }
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+ && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(InstanceofExpression node, Object other) {
+ if (!(other instanceof InstanceofExpression)) {
+ return false;
+ }
+ InstanceofExpression o = (InstanceofExpression) other;
+ return (
+ safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+ && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(Initializer node, Object other) {
+ if (!(other instanceof Initializer)) {
+ return false;
+ }
+ Initializer o = (Initializer) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * Unlike other node types, the behavior of the default
+ * implementation is controlled by a constructor-supplied
+ * parameter {@link #ASTMatcher(boolean) ASTMatcher(boolean)}
+ * which is <code>false</code> if not specified.
+ * When this parameter is <code>true</code>, the implementation
+ * tests whether the other object is also a <code>Javadoc</code>
+ * with structurally isomorphic child subtrees; the comment string
+ * (<code>Javadoc.getComment()</code>) is ignored.
+ * Conversely, when the parameter is <code>false</code>, the
+ * implementation tests whether the other object is also a
+ * <code>Javadoc</code> with exactly the same comment string;
+ * the tag elements ({@link Javadoc#tags() Javadoc.tags} are
+ * ignored. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @see #ASTMatcher()
+ * @see #ASTMatcher(boolean)
+ */
+ public boolean match(Javadoc node, Object other) {
+ if (!(other instanceof Javadoc)) {
+ return false;
+ }
+ Javadoc o = (Javadoc) other;
+ if (this.matchDocTags) {
+ return safeSubtreeListMatch(node.tags(), o.tags());
+ } else {
+ return compareDeprecatedComment(node, o);
+ }
+ }
+
+ /**
+ * Return whether the deprecated comment strings of the given java doc are equals.
+ * <p>
+ * Note the only purpose of this method is to hide deprecated warnings.
+ * @deprecated mark deprecated to hide deprecated usage
+ */
+ private boolean compareDeprecatedComment(Javadoc first, Javadoc second) {
+ if (first.getAST().apiLevel == AST.JLS2_INTERNAL) {
+ return safeEquals(first.getComment(), second.getComment());
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(LabeledStatement node, Object other) {
+ if (!(other instanceof LabeledStatement)) {
+ return false;
+ }
+ LabeledStatement o = (LabeledStatement) other;
+ return (
+ safeSubtreeMatch(node.getLabel(), o.getLabel())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type. Subclasses may override
+ * this method as needed.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(LineComment node, Object other) {
+ if (!(other instanceof LineComment)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(MarkerAnnotation node, Object other) {
+ if (!(other instanceof MarkerAnnotation)) {
+ return false;
+ }
+ MarkerAnnotation o = (MarkerAnnotation) other;
+ return safeSubtreeMatch(node.getTypeName(), o.getTypeName());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(MemberRef node, Object other) {
+ if (!(other instanceof MemberRef)) {
+ return false;
+ }
+ MemberRef o = (MemberRef) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(MemberValuePair node, Object other) {
+ if (!(other instanceof MemberValuePair)) {
+ return false;
+ }
+ MemberValuePair o = (MemberValuePair) other;
+ return (safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeMatch(node.getValue(), o.getValue()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(MethodRef node, Object other) {
+ if (!(other instanceof MethodRef)) {
+ return false;
+ }
+ MethodRef o = (MethodRef) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.parameters(), o.parameters()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(MethodRefParameter node, Object other) {
+ if (!(other instanceof MethodRefParameter)) {
+ return false;
+ }
+ MethodRefParameter o = (MethodRefParameter) other;
+ int level = node.getAST().apiLevel;
+ if (level >= AST.JLS3) {
+ if (node.isVarargs() != o.isVarargs()) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ * <p>
+ * Note that extra array dimensions are compared since they are an
+ * important part of the method declaration.
+ * </p>
+ * <p>
+ * Note that the method return types are compared even for constructor
+ * declarations.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(MethodDeclaration node, Object other) {
+ if (!(other instanceof MethodDeclaration)) {
+ return false;
+ }
+ MethodDeclaration o = (MethodDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getReturnType2(), o.getReturnType2())) {
+ return false;
+ }
+ // n.b. compare type parameters even for constructors
+ if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) {
+ return false;
+ }
+ }
+ return ((node.isConstructor() == o.isConstructor())
+ && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ // n.b. compare return type even for constructors
+ && safeSubtreeListMatch(node.parameters(), o.parameters())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeListMatch(node.thrownExceptions(), o.thrownExceptions())
+//{ObjectTeams:
+ && safeSubtreeMatch(node.getGuardPredicate(), o.getGuardPredicate())
+// SH}
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(MethodInvocation node, Object other) {
+ if (!(other instanceof MethodInvocation)) {
+ return false;
+ }
+ MethodInvocation o = (MethodInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(Modifier node, Object other) {
+ if (!(other instanceof Modifier)) {
+ return false;
+ }
+ Modifier o = (Modifier) other;
+ return (node.getKeyword() == o.getKeyword());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(NormalAnnotation node, Object other) {
+ if (!(other instanceof NormalAnnotation)) {
+ return false;
+ }
+ NormalAnnotation o = (NormalAnnotation) other;
+ return (safeSubtreeMatch(node.getTypeName(), o.getTypeName())
+ && safeSubtreeListMatch(node.values(), o.values()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(NullLiteral node, Object other) {
+ if (!(other instanceof NullLiteral)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(NumberLiteral node, Object other) {
+ if (!(other instanceof NumberLiteral)) {
+ return false;
+ }
+ NumberLiteral o = (NumberLiteral) other;
+ return safeEquals(node.getToken(), o.getToken());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(PackageDeclaration node, Object other) {
+ if (!(other instanceof PackageDeclaration)) {
+ return false;
+ }
+ PackageDeclaration o = (PackageDeclaration) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())) {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.annotations(), o.annotations())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getName(), o.getName());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(ParameterizedType node, Object other) {
+ if (!(other instanceof ParameterizedType)) {
+ return false;
+ }
+ ParameterizedType o = (ParameterizedType) other;
+ return safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.typeArguments(), o.typeArguments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ParenthesizedExpression node, Object other) {
+ if (!(other instanceof ParenthesizedExpression)) {
+ return false;
+ }
+ ParenthesizedExpression o = (ParenthesizedExpression) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(PostfixExpression node, Object other) {
+ if (!(other instanceof PostfixExpression)) {
+ return false;
+ }
+ PostfixExpression o = (PostfixExpression) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(PrefixExpression node, Object other) {
+ if (!(other instanceof PrefixExpression)) {
+ return false;
+ }
+ PrefixExpression o = (PrefixExpression) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(PrimitiveType node, Object other) {
+ if (!(other instanceof PrimitiveType)) {
+ return false;
+ }
+ PrimitiveType o = (PrimitiveType) other;
+ return (node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(QualifiedName node, Object other) {
+ if (!(other instanceof QualifiedName)) {
+ return false;
+ }
+ QualifiedName o = (QualifiedName) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(QualifiedType node, Object other) {
+ if (!(other instanceof QualifiedType)) {
+ return false;
+ }
+ QualifiedType o = (QualifiedType) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ReturnStatement node, Object other) {
+ if (!(other instanceof ReturnStatement)) {
+ return false;
+ }
+ ReturnStatement o = (ReturnStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SimpleName node, Object other) {
+ if (!(other instanceof SimpleName)) {
+ return false;
+ }
+ SimpleName o = (SimpleName) other;
+ return node.getIdentifier().equals(o.getIdentifier());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SimpleType node, Object other) {
+ if (!(other instanceof SimpleType)) {
+ return false;
+ }
+ SimpleType o = (SimpleType) other;
+ return safeSubtreeMatch(node.getName(), o.getName());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(SingleMemberAnnotation node, Object other) {
+ if (!(other instanceof SingleMemberAnnotation)) {
+ return false;
+ }
+ SingleMemberAnnotation o = (SingleMemberAnnotation) other;
+ return (safeSubtreeMatch(node.getTypeName(), o.getTypeName())
+ && safeSubtreeMatch(node.getValue(), o.getValue()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ * <p>
+ * Note that extra array dimensions and the variable arity flag
+ * are compared since they are both important parts of the declaration.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SingleVariableDeclaration node, Object other) {
+ if (!(other instanceof SingleVariableDeclaration)) {
+ return false;
+ }
+ SingleVariableDeclaration o = (SingleVariableDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (node.isVarargs() != o.isVarargs()) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(StringLiteral node, Object other) {
+ if (!(other instanceof StringLiteral)) {
+ return false;
+ }
+ StringLiteral o = (StringLiteral) other;
+ return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SuperConstructorInvocation node, Object other) {
+ if (!(other instanceof SuperConstructorInvocation)) {
+ return false;
+ }
+ SuperConstructorInvocation o = (SuperConstructorInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SuperFieldAccess node, Object other) {
+ if (!(other instanceof SuperFieldAccess)) {
+ return false;
+ }
+ SuperFieldAccess o = (SuperFieldAccess) other;
+ return (
+ safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeMatch(node.getQualifier(), o.getQualifier()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SuperMethodInvocation node, Object other) {
+ if (!(other instanceof SuperMethodInvocation)) {
+ return false;
+ }
+ SuperMethodInvocation o = (SuperMethodInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SwitchCase node, Object other) {
+ if (!(other instanceof SwitchCase)) {
+ return false;
+ }
+ SwitchCase o = (SwitchCase) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SwitchStatement node, Object other) {
+ if (!(other instanceof SwitchStatement)) {
+ return false;
+ }
+ SwitchStatement o = (SwitchStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.statements(), o.statements()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(SynchronizedStatement node, Object other) {
+ if (!(other instanceof SynchronizedStatement)) {
+ return false;
+ }
+ SynchronizedStatement o = (SynchronizedStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(TagElement node, Object other) {
+ if (!(other instanceof TagElement)) {
+ return false;
+ }
+ TagElement o = (TagElement) other;
+ return (
+ safeEquals(node.getTagName(), o.getTagName())
+ && safeSubtreeListMatch(node.fragments(), o.fragments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.0
+ */
+ public boolean match(TextElement node, Object other) {
+ if (!(other instanceof TextElement)) {
+ return false;
+ }
+ TextElement o = (TextElement) other;
+ return safeEquals(node.getText(), o.getText());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ThisExpression node, Object other) {
+ if (!(other instanceof ThisExpression)) {
+ return false;
+ }
+ ThisExpression o = (ThisExpression) other;
+ return safeSubtreeMatch(node.getQualifier(), o.getQualifier());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(ThrowStatement node, Object other) {
+ if (!(other instanceof ThrowStatement)) {
+ return false;
+ }
+ ThrowStatement o = (ThrowStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TryStatement node, Object other) {
+ if (!(other instanceof TryStatement)) {
+ return false;
+ }
+ TryStatement o = (TryStatement) other;
+ return (
+ safeSubtreeMatch(node.getBody(), o.getBody())
+ && safeSubtreeListMatch(node.catchClauses(), o.catchClauses())
+ && safeSubtreeMatch(node.getFinally(), o.getFinally()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TypeDeclaration node, Object other) {
+ if (!(other instanceof TypeDeclaration)) {
+ return false;
+ }
+ TypeDeclaration o = (TypeDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.internalGetSuperclass(), o.internalGetSuperclass())) {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.internalSuperInterfaces(), o.internalSuperInterfaces())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getSuperclassType(), o.getSuperclassType())) {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())) {
+ return false;
+ }
+//{ObjectTeams:
+ if (node.isTeam() != o.isTeam())
+ return false;
+ if (node.isRole() != o.isRole())
+ return false;
+ if (!safeSubtreeListMatch(node.precedences(), o.precedences()))
+ return false;
+// SH}
+ }
+ return (
+ (node.isInterface() == o.isInterface())
+ && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TypeDeclarationStatement node, Object other) {
+ if (!(other instanceof TypeDeclarationStatement)) {
+ return false;
+ }
+ TypeDeclarationStatement o = (TypeDeclarationStatement) other;
+ return safeSubtreeMatch(node.getDeclaration(), o.getDeclaration());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TypeLiteral node, Object other) {
+ if (!(other instanceof TypeLiteral)) {
+ return false;
+ }
+ TypeLiteral o = (TypeLiteral) other;
+ return safeSubtreeMatch(node.getType(), o.getType());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(TypeParameter node, Object other) {
+ if (!(other instanceof TypeParameter)) {
+ return false;
+ }
+ TypeParameter o = (TypeParameter) other;
+ return safeSubtreeMatch(node.getName(), o.getName())
+//{ObjectTeams: value parameter & <B base R>:
+ && node.isValueParameter() == o.isValueParameter()
+ && node.hasBaseBound() == o.hasBaseBound()
+// SH}
+ && safeSubtreeListMatch(node.typeBounds(), o.typeBounds());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(VariableDeclarationExpression node, Object other) {
+ if (!(other instanceof VariableDeclarationExpression)) {
+ return false;
+ }
+ VariableDeclarationExpression o = (VariableDeclarationExpression) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ * <p>
+ * Note that extra array dimensions are compared since they are an
+ * important part of the type of the variable.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(VariableDeclarationFragment node, Object other) {
+ if (!(other instanceof VariableDeclarationFragment)) {
+ return false;
+ }
+ VariableDeclarationFragment o = (VariableDeclarationFragment) other;
+ return safeSubtreeMatch(node.getName(), o.getName())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(VariableDeclarationStatement node, Object other) {
+ if (!(other instanceof VariableDeclarationStatement)) {
+ return false;
+ }
+ VariableDeclarationStatement o = (VariableDeclarationStatement) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(WhileStatement node, Object other) {
+ if (!(other instanceof WhileStatement)) {
+ return false;
+ }
+ WhileStatement o = (WhileStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ * @since 3.1
+ */
+ public boolean match(WildcardType node, Object other) {
+ if (!(other instanceof WildcardType)) {
+ return false;
+ }
+ WildcardType o = (WildcardType) other;
+ return node.isUpperBound() == o.isUpperBound()
+ && safeSubtreeMatch(node.getBound(), o.getBound());
+ }
+
+//{ObjectTeams: match methods for OT-specific types
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(MethodSpec node, Object other)
+ {
+ if (!(other instanceof MethodSpec))
+ {
+ return false;
+ }
+ MethodSpec otherMethodSpec = (MethodSpec) other;
+ int level = node.getAST().apiLevel;
+
+ if (level == AST.JLS3)
+ {
+ if (!safeSubtreeMatch(node.getReturnType2(),
+ otherMethodSpec.getReturnType2()))
+ {
+ return false;
+ }
+ }
+ if (level == AST.JLS2)
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+ return safeSubtreeMatch(node.getName(), otherMethodSpec.getName())
+ && safeSubtreeListMatch(node.parameters(), otherMethodSpec.parameters())
+ && safeSubtreeListMatch(node.typeParameters(), otherMethodSpec.typeParameters())
+ && (node.hasSignature() == otherMethodSpec.hasSignature())
+ && (node.hasCovariantReturn() == otherMethodSpec.hasCovariantReturn());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CallinMappingDeclaration node, Object other)
+ {
+ if (!(other instanceof CallinMappingDeclaration))
+ {
+ return false;
+ }
+ CallinMappingDeclaration node2 = (CallinMappingDeclaration)other;
+ int level = node.getAST().apiLevel;
+
+ if (level == AST.JLS3)
+ {
+ if (!safeSubtreeMatch(node.getName(), node2.getName()))
+ {
+ return false;
+ }
+ if (node.getModifiers() != node2.getModifiers())
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getRoleMappingElement(),
+ node2.getRoleMappingElement()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.getBaseMappingElements(),
+ node2.getBaseMappingElements()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.getParameterMappings(),
+ node2.getParameterMappings()))
+ {
+ return false;
+ }
+ }
+ if (level >= AST.JLS2)
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+ return safeSubtreeMatch(node.getJavadoc(), node2.getJavadoc())
+ && safeSubtreeMatch(node.getGuardPredicate(), node2.getGuardPredicate());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(CalloutMappingDeclaration node, Object other)
+ {
+ if (!(other instanceof CalloutMappingDeclaration))
+ {
+ return false;
+ }
+ CalloutMappingDeclaration otherCalloutMappingDecl = (CalloutMappingDeclaration) other;
+ int level = node.getAST().apiLevel;
+
+ if (level == AST.JLS3)
+ {
+ if (!safeSubtreeMatch(node.getRoleMappingElement(),
+ otherCalloutMappingDecl.getRoleMappingElement()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getBaseMappingElement(),
+ otherCalloutMappingDecl.getBaseMappingElement()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.getParameterMappings(),
+ otherCalloutMappingDecl.getParameterMappings()))
+ {
+ return false;
+ }
+ }
+ if (level >= AST.JLS2)
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+ return (safeSubtreeMatch(node.getJavadoc(), otherCalloutMappingDecl.getJavadoc())
+ && (node.isCalloutOverride() == otherCalloutMappingDecl.isCalloutOverride())
+ && (node.hasSignature() == otherCalloutMappingDecl.hasSignature()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(LiftingType node, Object other)
+ {
+ if (!(other instanceof LiftingType))
+ {
+ return false;
+ }
+ LiftingType otherType = (LiftingType) other;
+ return (safeSubtreeMatch(node.getName(), otherType.getName())
+ && safeSubtreeMatch(node.getBaseType(), otherType.getBaseType())
+ && safeSubtreeMatch(node.getRoleType(), otherType.getRoleType())
+ );
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TypeAnchor node, Object other)
+ {
+ if (!(other instanceof TypeAnchor))
+ {
+ return false;
+ }
+ TypeAnchor otherType = (TypeAnchor) other;
+ return safeSubtreeMatch(node.getPath(), otherType.getPath());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(WithinStatement node, Object other)
+ {
+ if (!(other instanceof WithinStatement))
+ {
+ return false;
+ }
+ WithinStatement node2 = (WithinStatement) other;
+
+ return (safeSubtreeMatch(node.getBody(), node2.getBody())
+ && safeSubtreeMatch(node.getTeamExpression(), node2.getTeamExpression())
+ );
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TSuperMessageSend node, Object other)
+ {
+ if (!(other instanceof TSuperMessageSend))
+ {
+ return false;
+ }
+ TSuperMessageSend otherExpression = (TSuperMessageSend) other;
+ return ( safeSubtreeMatch(node.getName(), otherExpression.getName())
+ && safeSubtreeListMatch(node.getArguments(), otherExpression.getArguments())
+ );
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(TSuperConstructorInvocation node, Object other)
+ {
+ if (!(other instanceof TSuperConstructorInvocation))
+ {
+ return false;
+ }
+ TSuperConstructorInvocation otherExpression = (TSuperConstructorInvocation) other;
+ return (safeSubtreeListMatch(node.getArguments(),
+ otherExpression.getArguments())
+ );
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(BaseCallMessageSend node, Object other)
+ {
+ if (!(other instanceof BaseCallMessageSend))
+ {
+ return false;
+ }
+ BaseCallMessageSend otherExpression = (BaseCallMessageSend) other;
+ return ( safeSubtreeMatch(node.getName(), otherExpression.getName())
+ && safeSubtreeListMatch(node.getArguments(), otherExpression.getArguments())
+ );
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(BaseConstructorInvocation node, Object other)
+ {
+ if (!(other instanceof BaseConstructorInvocation))
+ {
+ return false;
+ }
+ BaseConstructorInvocation node2 = (BaseConstructorInvocation) other;
+ return safeSubtreeListMatch(node.getArguments(), node2.getArguments());
+
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
+ */
+ public boolean match(org.eclipse.jdt.core.dom.ParameterMapping node, Object other) {
+ if (!(other instanceof org.eclipse.jdt.core.dom.ParameterMapping))
+ {
+ return false;
+ }
+ org.eclipse.jdt.core.dom.ParameterMapping otherParameterMapping =
+ (org.eclipse.jdt.core.dom.ParameterMapping) other;
+ return safeSubtreeMatch(node.getExpression(), otherParameterMapping.getExpression());
+ }
+
+ public boolean match(org.eclipse.jdt.core.dom.RoleTypeDeclaration node, Object other) {
+ if (!(other instanceof org.eclipse.jdt.core.dom.RoleTypeDeclaration))
+ {
+ return false;
+ }
+
+ RoleTypeDeclaration o = (RoleTypeDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2)
+ {
+ if (node.getModifiers() != o.getModifiers())
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getSuperclass(), o.getSuperclass()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getBaseClass(), o.getBaseClass()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getTeamClass(), o.getTeamClass()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.superInterfaces(), o.superInterfaces()))
+ {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getSuperclassType(), o.getSuperclassType()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getBaseClassType(), o.getBaseClassType()))
+ {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getTeamClassType(), o.getTeamClassType()))
+ {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes()))
+ {
+ return false;
+ }
+ if (node.isTeam() != o.isTeam())
+ return false;
+ if (node.isRoleFile() != o.isRoleFile())
+ return false;
+ if (!safeSubtreeListMatch(node.precedences(), o.precedences()))
+ return false;
+ }
+ return (
+ (node.isInterface() == o.isInterface())
+ && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeMatch(node.getGuardPredicate(), o.getGuardPredicate())
+ && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+ }
+
+ public boolean match(FieldAccessSpec node, Object other) {
+ if (!(other instanceof FieldAccessSpec)) {
+ return false;
+ }
+ FieldAccessSpec otherFieldAccessSpec = (FieldAccessSpec) other;
+
+ if (!safeSubtreeMatch(node.getFieldType(), otherFieldAccessSpec.getFieldType())) {
+ return false;
+ }
+
+ return ((node.hasSignature() == otherFieldAccessSpec.hasSignature())
+ && safeSubtreeMatch(node.getName(), otherFieldAccessSpec.getName()));
+ }
+
+ public boolean match(PrecedenceDeclaration node, Object other) {
+ if (!(other instanceof PrecedenceDeclaration)) {
+ return false;
+ }
+ PrecedenceDeclaration otherPrecedence = (PrecedenceDeclaration) other;
+
+ return safeSubtreeMatch(node.elements(), otherPrecedence.elements());
+ }
+
+ public boolean match(GuardPredicateDeclaration node, Object other) {
+ if (!(other instanceof GuardPredicateDeclaration))
+ return false;
+ GuardPredicateDeclaration otherPredicate = (GuardPredicateDeclaration)other;
+ return
+ node.isBase() == otherPredicate.isBase()
+ && safeSubtreeMatch(node.getExpression(), otherPredicate.getExpression());
+ }
+//gbr, jsv, SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
new file mode 100644
index 000000000..974d92f15
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -0,0 +1,2880 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTNode.java 22573 2009-09-23 10:49:24Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener;
+
+/**
+ * Abstract superclass of all Abstract Syntax Tree (AST) node types.
+ * <p>
+ * An AST node represents a Java source code construct, such
+ * as a name, type, expression, statement, or declaration.
+ * </p>
+ * <p>
+ * Each AST node belongs to a unique AST instance, called the owning AST.
+ * The children of an AST node always have the same owner as their parent node.
+ * If a node from one AST is to be added to a different AST, the subtree must
+ * be cloned first to ensure that the added nodes have the correct owning AST.
+ * </p>
+ * <p>
+ * When an AST node is part of an AST, it has a unique parent node.
+ * Clients can navigate upwards, from child to parent, as well as downwards,
+ * from parent to child. Newly created nodes are unparented. When an
+ * unparented node is set as a child of a node (using a
+ * <code>set<i>CHILD</i></code> method), its parent link is set automatically
+ * and the parent link of the former child is set to <code>null</code>.
+ * For nodes with properties that include a list of children (for example,
+ * <code>Block</code> whose <code>statements</code> property is a list
+ * of statements), adding or removing an element to/for the list property
+ * automatically updates the parent links. These lists support the
+ * <code>List.set</code> method; however, the constraint that the same
+ * node cannot appear more than once means that this method cannot be used
+ * to swap elements without first removing the node.
+ * </p>
+ * <p>
+ * ASTs must not contain cycles. All operations that could create a cycle
+ * detect this possibility and fail.
+ * </p>
+ * <p>
+ * ASTs do not contain "holes" (missing subtrees). If a node is required to
+ * have a certain property, a syntactically plausible initial value is
+ * always supplied.
+ * </p>
+ * <p>
+ * The hierarchy of AST node types has some convenient groupings marked
+ * by abstract superclasses:
+ * <ul>
+ * <li>expressions - <code>Expression</code></li>
+ * <li>names - <code>Name</code> (a sub-kind of expression)</li>
+ * <li>statements - <code>Statement</code></li>
+ * <li>types - <code>Type</code></li>
+ * <li>type body declarations - <code>BodyDeclaration</code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
+ * create new nodes, and the various <code>set<i>CHILD</i></code> methods
+ * to connect them together.
+ * </p>
+ * <p>
+ * The class {@link ASTParser} parses a string
+ * containing a Java source code and returns an abstract syntax tree
+ * for it. The resulting nodes carry source ranges relating the node back to
+ * the original source characters. The source range covers the construct
+ * as a whole.
+ * </p>
+ * <p>
+ * Each AST node carries bit flags, which may convey additional information about
+ * the node. For instance, the parser uses a flag to indicate a syntax error.
+ * Newly created nodes have no flags set.
+ * </p>
+ * <p>
+ * Each AST node is capable of carrying an open-ended collection of
+ * client-defined properties. Newly created nodes have none.
+ * <code>getProperty</code> and <code>setProperty</code> are used to access
+ * these properties.
+ * </p>
+ * <p>
+ * AST nodes are thread-safe for readers provided there are no active writers.
+ * If one thread is modifying an AST, including creating new nodes or cloning
+ * existing ones, it is <b>not</b> safe for another thread to read, visit,
+ * write, create, or clone <em>any</em> of the nodes on the same AST.
+ * When synchronization is required, consider using the common AST
+ * object that owns the node; that is, use
+ * <code>synchronize (node.getAST()) {...}</code>.
+ * </p>
+ * <p>
+ * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
+ * for details. The <code>NodeFinder</code> class can be used to find a specific
+ * node inside a tree.
+ * </p>
+ * <p>
+ * Compilation units created by <code>ASTParser</code> from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. See
+ * {@link CompilationUnit#recordModifications()} for details.
+ * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
+ * an alternative way to describe and serialize changes to a
+ * read-only AST.
+ * </p>
+ *
+ * @see ASTParser
+ * @see ASTVisitor
+ * @see NodeFinder
+ * @since 2.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class ASTNode {
+ /*
+ * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
+ *
+ * There are several things that need to be changed when a
+ * new concrete AST node type (call it "FooBar"):
+ *
+ * 1. Create the FooBar AST node type class.
+ * The most effective way to do this is to copy a similar
+ * existing concrete node class to get a template that
+ * includes all the framework methods that must be implemented.
+ *
+ * 2. Add node type constant ASTNode.FOO_BAR.
+ * Node constants are numbered consecutively. Add the
+ * constant after the existing ones.
+ *
+ * 3. Add entry to ASTNode.nodeClassForType(int).
+ *
+ * 4. Add AST.newFooBar() factory method.
+ *
+ * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
+ *
+ * 6. Add ASTMatcher.match(FooBar,Object) method.
+ *
+ * 7. Ensure that SimpleName.isDeclaration() covers FooBar
+ * nodes if required.
+ *
+ * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
+ * how these nodes should be serialized.
+ *
+ * 9. Update the AST test suites.
+ *
+ * The next steps are to update AST.parse* to start generating
+ * the new type of nodes, and ASTRewrite to serialize them back out.
+ */
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>AnonymousClassDeclaration</code>.
+ * @see AnonymousClassDeclaration
+ */
+ public static final int ANONYMOUS_CLASS_DECLARATION = 1;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ArrayAccess</code>.
+ * @see ArrayAccess
+ */
+ public static final int ARRAY_ACCESS = 2;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ArrayCreation</code>.
+ * @see ArrayCreation
+ */
+ public static final int ARRAY_CREATION = 3;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ArrayInitializer</code>.
+ * @see ArrayInitializer
+ */
+ public static final int ARRAY_INITIALIZER = 4;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ArrayType</code>.
+ * @see ArrayType
+ */
+ public static final int ARRAY_TYPE = 5;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>AssertStatement</code>.
+ * @see AssertStatement
+ */
+ public static final int ASSERT_STATEMENT = 6;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>Assignment</code>.
+ * @see Assignment
+ */
+ public static final int ASSIGNMENT = 7;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>Block</code>.
+ * @see Block
+ */
+ public static final int BLOCK = 8;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>BooleanLiteral</code>.
+ * @see BooleanLiteral
+ */
+ public static final int BOOLEAN_LITERAL = 9;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>BreakStatement</code>.
+ * @see BreakStatement
+ */
+ public static final int BREAK_STATEMENT = 10;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CastExpression</code>.
+ * @see CastExpression
+ */
+ public static final int CAST_EXPRESSION = 11;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CatchClause</code>.
+ * @see CatchClause
+ */
+ public static final int CATCH_CLAUSE = 12;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CharacterLiteral</code>.
+ * @see CharacterLiteral
+ */
+ public static final int CHARACTER_LITERAL = 13;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ClassInstanceCreation</code>.
+ * @see ClassInstanceCreation
+ */
+ public static final int CLASS_INSTANCE_CREATION = 14;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CompilationUnit</code>.
+ * @see CompilationUnit
+ */
+ public static final int COMPILATION_UNIT = 15;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ConditionalExpression</code>.
+ * @see ConditionalExpression
+ */
+ public static final int CONDITIONAL_EXPRESSION = 16;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ConstructorInvocation</code>.
+ * @see ConstructorInvocation
+ */
+ public static final int CONSTRUCTOR_INVOCATION = 17;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ContinueStatement</code>.
+ * @see ContinueStatement
+ */
+ public static final int CONTINUE_STATEMENT = 18;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>DoStatement</code>.
+ * @see DoStatement
+ */
+ public static final int DO_STATEMENT = 19;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>EmptyStatement</code>.
+ * @see EmptyStatement
+ */
+ public static final int EMPTY_STATEMENT = 20;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ExpressionStatement</code>.
+ * @see ExpressionStatement
+ */
+ public static final int EXPRESSION_STATEMENT = 21;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>FieldAccess</code>.
+ * @see FieldAccess
+ */
+ public static final int FIELD_ACCESS = 22;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>FieldDeclaration</code>.
+ * @see FieldDeclaration
+ */
+ public static final int FIELD_DECLARATION = 23;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ForStatement</code>.
+ * @see ForStatement
+ */
+ public static final int FOR_STATEMENT = 24;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>IfStatement</code>.
+ * @see IfStatement
+ */
+ public static final int IF_STATEMENT = 25;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ImportDeclaration</code>.
+ * @see ImportDeclaration
+ */
+ public static final int IMPORT_DECLARATION = 26;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>InfixExpression</code>.
+ * @see InfixExpression
+ */
+ public static final int INFIX_EXPRESSION = 27;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>Initializer</code>.
+ * @see Initializer
+ */
+ public static final int INITIALIZER = 28;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>Javadoc</code>.
+ * @see Javadoc
+ */
+ public static final int JAVADOC = 29;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>LabeledStatement</code>.
+ * @see LabeledStatement
+ */
+ public static final int LABELED_STATEMENT = 30;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MethodDeclaration</code>.
+ * @see MethodDeclaration
+ */
+ public static final int METHOD_DECLARATION = 31;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MethodInvocation</code>.
+ * @see MethodInvocation
+ */
+ public static final int METHOD_INVOCATION = 32;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>NullLiteral</code>.
+ * @see NullLiteral
+ */
+ public static final int NULL_LITERAL = 33;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>NumberLiteral</code>.
+ * @see NumberLiteral
+ */
+ public static final int NUMBER_LITERAL = 34;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>PackageDeclaration</code>.
+ * @see PackageDeclaration
+ */
+ public static final int PACKAGE_DECLARATION = 35;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ParenthesizedExpression</code>.
+ * @see ParenthesizedExpression
+ */
+ public static final int PARENTHESIZED_EXPRESSION = 36;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>PostfixExpression</code>.
+ * @see PostfixExpression
+ */
+ public static final int POSTFIX_EXPRESSION = 37;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>PrefixExpression</code>.
+ * @see PrefixExpression
+ */
+ public static final int PREFIX_EXPRESSION = 38;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>PrimitiveType</code>.
+ * @see PrimitiveType
+ */
+ public static final int PRIMITIVE_TYPE = 39;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>QualifiedName</code>.
+ * @see QualifiedName
+ */
+ public static final int QUALIFIED_NAME = 40;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ReturnStatement</code>.
+ * @see ReturnStatement
+ */
+ public static final int RETURN_STATEMENT = 41;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SimpleName</code>.
+ * @see SimpleName
+ */
+ public static final int SIMPLE_NAME = 42;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SimpleType</code>.
+ * @see SimpleType
+ */
+ public static final int SIMPLE_TYPE = 43;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SingleVariableDeclaration</code>.
+ * @see SingleVariableDeclaration
+ */
+ public static final int SINGLE_VARIABLE_DECLARATION = 44;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>StringLiteral</code>.
+ * @see StringLiteral
+ */
+ public static final int STRING_LITERAL = 45;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SuperConstructorInvocation</code>.
+ * @see SuperConstructorInvocation
+ */
+ public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SuperFieldAccess</code>.
+ * @see SuperFieldAccess
+ */
+ public static final int SUPER_FIELD_ACCESS = 47;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SuperMethodInvocation</code>.
+ * @see SuperMethodInvocation
+ */
+ public static final int SUPER_METHOD_INVOCATION = 48;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SwitchCase</code>.
+ * @see SwitchCase
+ */
+ public static final int SWITCH_CASE = 49;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SwitchStatement</code>.
+ * @see SwitchStatement
+ */
+ public static final int SWITCH_STATEMENT = 50;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SynchronizedStatement</code>.
+ * @see SynchronizedStatement
+ */
+ public static final int SYNCHRONIZED_STATEMENT = 51;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ThisExpression</code>.
+ * @see ThisExpression
+ */
+ public static final int THIS_EXPRESSION = 52;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ThrowStatement</code>.
+ * @see ThrowStatement
+ */
+ public static final int THROW_STATEMENT = 53;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TryStatement</code>.
+ * @see TryStatement
+ */
+ public static final int TRY_STATEMENT = 54;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TypeDeclaration</code>.
+ * @see TypeDeclaration
+ */
+ public static final int TYPE_DECLARATION = 55;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TypeDeclarationStatement</code>.
+ * @see TypeDeclarationStatement
+ */
+ public static final int TYPE_DECLARATION_STATEMENT = 56;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TypeLiteral</code>.
+ * @see TypeLiteral
+ */
+ public static final int TYPE_LITERAL = 57;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>VariableDeclarationExpression</code>.
+ * @see VariableDeclarationExpression
+ */
+ public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>VariableDeclarationFragment</code>.
+ * @see VariableDeclarationFragment
+ */
+ public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>VariableDeclarationStatement</code>.
+ * @see VariableDeclarationStatement
+ */
+ public static final int VARIABLE_DECLARATION_STATEMENT = 60;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>WhileStatement</code>.
+ * @see WhileStatement
+ */
+ public static final int WHILE_STATEMENT = 61;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>InstanceofExpression</code>.
+ * @see InstanceofExpression
+ */
+ public static final int INSTANCEOF_EXPRESSION = 62;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>LineComment</code>.
+ * @see LineComment
+ * @since 3.0
+ */
+ public static final int LINE_COMMENT = 63;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>BlockComment</code>.
+ * @see BlockComment
+ * @since 3.0
+ */
+ public static final int BLOCK_COMMENT = 64;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TagElement</code>.
+ * @see TagElement
+ * @since 3.0
+ */
+ public static final int TAG_ELEMENT = 65;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TextElement</code>.
+ * @see TextElement
+ * @since 3.0
+ */
+ public static final int TEXT_ELEMENT = 66;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MemberRef</code>.
+ * @see MemberRef
+ * @since 3.0
+ */
+ public static final int MEMBER_REF = 67;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MethodRef</code>.
+ * @see MethodRef
+ * @since 3.0
+ */
+ public static final int METHOD_REF = 68;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MethodRefParameter</code>.
+ * @see MethodRefParameter
+ * @since 3.0
+ */
+ public static final int METHOD_REF_PARAMETER = 69;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>EnhancedForStatement</code>.
+ * @see EnhancedForStatement
+ * @since 3.1
+ */
+ public static final int ENHANCED_FOR_STATEMENT = 70;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>EnumDeclaration</code>.
+ * @see EnumDeclaration
+ * @since 3.1
+ */
+ public static final int ENUM_DECLARATION = 71;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>EnumConstantDeclaration</code>.
+ * @see EnumConstantDeclaration
+ * @since 3.1
+ */
+ public static final int ENUM_CONSTANT_DECLARATION = 72;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TypeParameter</code>.
+ * @see TypeParameter
+ * @since 3.1
+ */
+ public static final int TYPE_PARAMETER = 73;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ParameterizedType</code>.
+ * @see ParameterizedType
+ * @since 3.1
+ */
+ public static final int PARAMETERIZED_TYPE = 74;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>QualifiedType</code>.
+ * @see QualifiedType
+ * @since 3.1
+ */
+ public static final int QUALIFIED_TYPE = 75;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>WildcardType</code>.
+ * @see WildcardType
+ * @since 3.1
+ */
+ public static final int WILDCARD_TYPE = 76;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>NormalAnnotation</code>.
+ * @see NormalAnnotation
+ * @since 3.1
+ */
+ public static final int NORMAL_ANNOTATION = 77;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MarkerAnnotation</code>.
+ * @see MarkerAnnotation
+ * @since 3.1
+ */
+ public static final int MARKER_ANNOTATION = 78;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>SingleMemberAnnotation</code>.
+ * @see SingleMemberAnnotation
+ * @since 3.1
+ */
+ public static final int SINGLE_MEMBER_ANNOTATION = 79;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MemberValuePair</code>.
+ * @see MemberValuePair
+ * @since 3.1
+ */
+ public static final int MEMBER_VALUE_PAIR = 80;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>AnnotationTypeDeclaration</code>.
+ * @see AnnotationTypeDeclaration
+ * @since 3.1
+ */
+ public static final int ANNOTATION_TYPE_DECLARATION = 81;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>AnnotationTypeMemberDeclaration</code>.
+ * @see AnnotationTypeMemberDeclaration
+ * @since 3.1
+ */
+ public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>Modifier</code>.
+ * @see Modifier
+ * @since 3.1
+ */
+ public static final int MODIFIER = 83;
+
+//{ObjectTeams: required OT specific node type constants added
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>MethodSpec</code>.
+ * @see MethodSpec
+ */
+ public static final int METHOD_SPEC = 84;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CallinMappingDeclaration</code>.
+ * @see CallinMappingDeclaration
+ */
+ public static final int CALLIN_MAPPING_DECLARATION = 85;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>CalloutMappingDeclaration</code>.
+ * @see CalloutMappingDeclaration
+ */
+ public static final int CALLOUT_MAPPING_DECLARATION = 86;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>LiftingType</code>.
+ * @see LiftingType
+ */
+ public static final int LIFTING_TYPE = 87;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>WithinStatement</code>.
+ * @see WithinStatement
+ */
+ public static final int WITHIN_STATEMENT = 88;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>BaseConstructorMessageSend</code>.
+ * @see BaseConstructorMessageSend
+ */
+ public static final int BASE_CONSTRUCTOR_INVOCATION = 89;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>ParameterMapping</code>.
+ * @see ParameterMapping
+ */
+ public static final int PARAMETER_MAPPING = 90;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>BaseCallMessageSend</code>.
+ * @see BaseCallMessageSend
+ */
+ public static final int BASE_CALL_MESSAGE_SEND = 91;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>FieldAccessSpec</code>.
+ * @see FieldAccessSpec
+ */
+ public static final int FIELD_ACCESS_SPEC = 92;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>RoleTypeDelaration</code>.
+ * @see RoleTypeDelaration
+ */
+ public static final int ROLE_TYPE_DECLARATION = 93;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TSuperCallMessageSend</code>.
+ * @see TSuperCallMessageSend
+ */
+ public static final int TSUPER_MESSAGE_SEND = 94;
+
+ /**
+ * Node type constant indicating a node of type
+ * <code>TSuperCallMessageSend</code>.
+ * @see TSuperCallMessageSend
+ */
+ public static final int TSUPER_CONSTRUCTOR_INVOCATION = 95;
+
+ public static final int TYPE_ANCHOR = 96;
+
+ public static final int PRECEDENCE_DECLARATION = 97;
+
+ public static final int GUARD_PREDICATE_DECLARATION = 98;
+
+ /** @since 1.3.1 */
+ public static final int METHOD_BINDING_OPERATOR = 99;
+//gbr}
+
+ /**
+ * Returns the node class for the corresponding node type.
+ *
+ * @param nodeType AST node type
+ * @return the corresponding <code>ASTNode</code> subclass
+ * @exception IllegalArgumentException if <code>nodeType</code> is
+ * not a legal AST node type
+ * @see #getNodeType()
+ * @since 3.0
+ */
+ public static Class nodeClassForType(int nodeType) {
+ switch (nodeType) {
+ case ANNOTATION_TYPE_DECLARATION :
+ return AnnotationTypeDeclaration.class;
+ case ANNOTATION_TYPE_MEMBER_DECLARATION :
+ return AnnotationTypeMemberDeclaration.class;
+ case ANONYMOUS_CLASS_DECLARATION :
+ return AnonymousClassDeclaration.class;
+ case ARRAY_ACCESS :
+ return ArrayAccess.class;
+ case ARRAY_CREATION :
+ return ArrayCreation.class;
+ case ARRAY_INITIALIZER :
+ return ArrayInitializer.class;
+ case ARRAY_TYPE :
+ return ArrayType.class;
+ case ASSERT_STATEMENT :
+ return AssertStatement.class;
+ case ASSIGNMENT :
+ return Assignment.class;
+ case BLOCK :
+ return Block.class;
+ case BLOCK_COMMENT :
+ return BlockComment.class;
+ case BOOLEAN_LITERAL :
+ return BooleanLiteral.class;
+ case BREAK_STATEMENT :
+ return BreakStatement.class;
+ case CAST_EXPRESSION :
+ return CastExpression.class;
+ case CATCH_CLAUSE :
+ return CatchClause.class;
+ case CHARACTER_LITERAL :
+ return CharacterLiteral.class;
+ case CLASS_INSTANCE_CREATION :
+ return ClassInstanceCreation.class;
+ case COMPILATION_UNIT :
+ return CompilationUnit.class;
+ case CONDITIONAL_EXPRESSION :
+ return ConditionalExpression.class;
+ case CONSTRUCTOR_INVOCATION :
+ return ConstructorInvocation.class;
+ case CONTINUE_STATEMENT :
+ return ContinueStatement.class;
+ case DO_STATEMENT :
+ return DoStatement.class;
+ case EMPTY_STATEMENT :
+ return EmptyStatement.class;
+ case ENHANCED_FOR_STATEMENT :
+ return EnhancedForStatement.class;
+ case ENUM_CONSTANT_DECLARATION :
+ return EnumConstantDeclaration.class;
+ case ENUM_DECLARATION :
+ return EnumDeclaration.class;
+ case EXPRESSION_STATEMENT :
+ return ExpressionStatement.class;
+ case FIELD_ACCESS :
+ return FieldAccess.class;
+ case FIELD_DECLARATION :
+ return FieldDeclaration.class;
+ case FOR_STATEMENT :
+ return ForStatement.class;
+ case IF_STATEMENT :
+ return IfStatement.class;
+ case IMPORT_DECLARATION :
+ return ImportDeclaration.class;
+ case INFIX_EXPRESSION :
+ return InfixExpression.class;
+ case INITIALIZER :
+ return Initializer.class;
+ case INSTANCEOF_EXPRESSION :
+ return InstanceofExpression.class;
+ case JAVADOC :
+ return Javadoc.class;
+ case LABELED_STATEMENT :
+ return LabeledStatement.class;
+ case LINE_COMMENT :
+ return LineComment.class;
+ case MARKER_ANNOTATION :
+ return MarkerAnnotation.class;
+ case MEMBER_REF :
+ return MemberRef.class;
+ case MEMBER_VALUE_PAIR :
+ return MemberValuePair.class;
+ case METHOD_DECLARATION :
+ return MethodDeclaration.class;
+ case METHOD_INVOCATION :
+ return MethodInvocation.class;
+ case METHOD_REF :
+ return MethodRef.class;
+ case METHOD_REF_PARAMETER :
+ return MethodRefParameter.class;
+ case MODIFIER :
+ return Modifier.class;
+ case NORMAL_ANNOTATION :
+ return NormalAnnotation.class;
+ case NULL_LITERAL :
+ return NullLiteral.class;
+ case NUMBER_LITERAL :
+ return NumberLiteral.class;
+ case PACKAGE_DECLARATION :
+ return PackageDeclaration.class;
+ case PARAMETERIZED_TYPE :
+ return ParameterizedType.class;
+ case PARENTHESIZED_EXPRESSION :
+ return ParenthesizedExpression.class;
+ case POSTFIX_EXPRESSION :
+ return PostfixExpression.class;
+ case PREFIX_EXPRESSION :
+ return PrefixExpression.class;
+ case PRIMITIVE_TYPE :
+ return PrimitiveType.class;
+ case QUALIFIED_NAME :
+ return QualifiedName.class;
+ case QUALIFIED_TYPE :
+ return QualifiedType.class;
+ case RETURN_STATEMENT :
+ return ReturnStatement.class;
+ case SIMPLE_NAME :
+ return SimpleName.class;
+ case SIMPLE_TYPE :
+ return SimpleType.class;
+ case SINGLE_MEMBER_ANNOTATION :
+ return SingleMemberAnnotation.class;
+ case SINGLE_VARIABLE_DECLARATION :
+ return SingleVariableDeclaration.class;
+ case STRING_LITERAL :
+ return StringLiteral.class;
+ case SUPER_CONSTRUCTOR_INVOCATION :
+ return SuperConstructorInvocation.class;
+ case SUPER_FIELD_ACCESS :
+ return SuperFieldAccess.class;
+ case SUPER_METHOD_INVOCATION :
+ return SuperMethodInvocation.class;
+ case SWITCH_CASE:
+ return SwitchCase.class;
+ case SWITCH_STATEMENT :
+ return SwitchStatement.class;
+ case SYNCHRONIZED_STATEMENT :
+ return SynchronizedStatement.class;
+ case TAG_ELEMENT :
+ return TagElement.class;
+ case TEXT_ELEMENT :
+ return TextElement.class;
+ case THIS_EXPRESSION :
+ return ThisExpression.class;
+ case THROW_STATEMENT :
+ return ThrowStatement.class;
+ case TRY_STATEMENT :
+ return TryStatement.class;
+ case TYPE_DECLARATION :
+ return TypeDeclaration.class;
+ case TYPE_DECLARATION_STATEMENT :
+ return TypeDeclarationStatement.class;
+ case TYPE_LITERAL :
+ return TypeLiteral.class;
+ case TYPE_PARAMETER :
+ return TypeParameter.class;
+ case VARIABLE_DECLARATION_EXPRESSION :
+ return VariableDeclarationExpression.class;
+ case VARIABLE_DECLARATION_FRAGMENT :
+ return VariableDeclarationFragment.class;
+ case VARIABLE_DECLARATION_STATEMENT :
+ return VariableDeclarationStatement.class;
+ case WHILE_STATEMENT :
+ return WhileStatement.class;
+ case WILDCARD_TYPE :
+ return WildcardType.class;
+//{ObjectTeams: entries for OT specific node types added
+ case METHOD_SPEC :
+ return MethodSpec.class;
+ case CALLIN_MAPPING_DECLARATION :
+ return CallinMappingDeclaration.class;
+ case CALLOUT_MAPPING_DECLARATION :
+ return CalloutMappingDeclaration.class;
+ case LIFTING_TYPE :
+ return LiftingType.class;
+ case WITHIN_STATEMENT :
+ return WithinStatement.class;
+ case TSUPER_MESSAGE_SEND :
+ return TSuperMessageSend.class;
+ case TSUPER_CONSTRUCTOR_INVOCATION :
+ return TSuperConstructorInvocation.class;
+ case BASE_CONSTRUCTOR_INVOCATION :
+ return BaseConstructorInvocation.class;
+ case PARAMETER_MAPPING :
+ return ParameterMapping.class;
+ case BASE_CALL_MESSAGE_SEND :
+ return BaseCallMessageSend.class;
+ case FIELD_ACCESS_SPEC :
+ return FieldAccessSpec.class;
+ case ROLE_TYPE_DECLARATION :
+ return RoleTypeDeclaration.class;
+ case TYPE_ANCHOR :
+ return TypeAnchor.class;
+ case PRECEDENCE_DECLARATION :
+ return PrecedenceDeclaration.class;
+ case GUARD_PREDICATE_DECLARATION :
+ return GuardPredicateDeclaration.class;
+ case METHOD_BINDING_OPERATOR :
+ return MethodBindingOperator.class;
+//gbr}
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Owning AST.
+ * <p>
+ * N.B. This ia a private field, but declared as package-visible
+ * for more efficient access from inner classes.
+ * </p>
+ */
+ final AST ast;
+
+ /**
+ * Parent AST node, or <code>null</code> if this node is a root.
+ * Initially <code>null</code>.
+ */
+ private ASTNode parent = null;
+
+ /**
+ * An unmodifiable empty map (used to implement <code>properties()</code>).
+ */
+ private static final Map UNMODIFIABLE_EMPTY_MAP
+ = Collections.unmodifiableMap(new HashMap(1));
+
+ /**
+ * Primary field used in representing node properties efficiently.
+ * If <code>null</code>, this node has no properties.
+ * If a <code>String</code>, this is the name of this node's sole property,
+ * and <code>property2</code> contains its value.
+ * If a <code>HashMap</code>, this is the table of property name-value
+ * mappings; <code>property2</code>, if non-null is its unmodifiable
+ * equivalent.
+ * Initially <code>null</code>.
+ *
+ * @see #property2
+ */
+ private Object property1 = null;
+
+ /**
+ * Auxillary field used in representing node properties efficiently.
+ *
+ * @see #property1
+ */
+ private Object property2 = null;
+
+ /**
+ * A character index into the original source string,
+ * or <code>-1</code> if no source position information is available
+ * for this node; <code>-1</code> by default.
+ */
+ private int startPosition = -1;
+
+ /**
+ * A character length, or <code>0</code> if no source position
+ * information is recorded for this node; <code>0</code> by default.
+ */
+ private int length = 0;
+
+ /**
+ * Flag constant (bit mask, value 1) indicating that there is something
+ * not quite right with this AST node.
+ * <p>
+ * The standard parser (<code>ASTParser</code>) sets this
+ * flag on a node to indicate a syntax error detected in the vicinity.
+ * </p>
+ */
+ public static final int MALFORMED = 1;
+
+ /**
+ * Flag constant (bit mask, value 2) indicating that this is a node
+ * that was created by the parser (as opposed to one created by another
+ * party).
+ * <p>
+ * The standard parser (<code>ASTParser</code>) sets this
+ * flag on the nodes it creates.
+ * </p>
+ * @since 3.0
+ */
+ public static final int ORIGINAL = 2;
+
+ /**
+ * Flag constant (bit mask, value 4) indicating that this node
+ * is unmodifiable. When a node is marked unmodifiable, the
+ * following operations result in a runtime exception:
+ * <ul>
+ * <li>Change a simple property of this node.</li>
+ * <li>Add or remove a child node from this node.</li>
+ * <li>Parent (or reparent) this node.</li>
+ * </ul>
+ * <p>
+ * The standard parser (<code>ASTParser</code>) does not set
+ * this flag on the nodes it creates. However, clients may set
+ * this flag on a node to prevent further modification of the
+ * its structural properties.
+ * </p>
+ * @since 3.0
+ */
+ public static final int PROTECT = 4;
+
+ /**
+ * Flag constant (bit mask, value 8) indicating that this node
+ * or a part of this node is recovered from source that contains
+ * a syntax error detected in the vicinity.
+ * <p>
+ * The standard parser (<code>ASTParser</code>) sets this
+ * flag on a node to indicate a recovered node.
+ * </p>
+ * @since 3.2
+ */
+ public static final int RECOVERED = 8;
+
+ /**
+ * int containing the node type in the top 16 bits and
+ * flags in the bottom 16 bits; none set by default.
+ * <p>
+ * N.B. This is a private field, but declared as package-visible
+ * for more efficient access from inner classes.
+ * </p>
+ *
+ * @see #MALFORMED
+ */
+ int typeAndFlags = 0;
+
+ /**
+ * Property of parent in which this node is a child, or <code>null</code>
+ * if this node is a root. Initially <code>null</code>.
+ *
+ * @see #getLocationInParent
+ * @since 3.0
+ */
+ private StructuralPropertyDescriptor location = null;
+
+ /** Internal convenience constant indicating that there is definite risk of cycles.
+ * @since 3.0
+ */
+ static final boolean CYCLE_RISK = true;
+
+ /** Internal convenience constant indicating that there is no risk of cycles.
+ * @since 3.0
+ */
+ static final boolean NO_CYCLE_RISK = false;
+
+ /** Internal convenience constant indicating that a structural property is mandatory.
+ * @since 3.0
+ */
+ static final boolean MANDATORY = true;
+
+ /** Internal convenience constant indicating that a structural property is optional.
+ * @since 3.0
+ */
+ static final boolean OPTIONAL = false;
+
+ /**
+ * A specialized implementation of a list of ASTNodes. The
+ * implementation is based on an ArrayList.
+ */
+ class NodeList extends AbstractList {
+
+ /**
+ * The underlying list in which the nodes of this list are
+ * stored (element type: <code>ASTNode</code>).
+ * <p>
+ * Be stingy on storage - assume that list will be empty.
+ * </p>
+ * <p>
+ * This field declared default visibility (rather than private)
+ * so that accesses from <code>NodeList.Cursor</code> do not require
+ * a synthetic accessor method.
+ * </p>
+ */
+ ArrayList store = new ArrayList(0);
+
+ /**
+ * The property descriptor for this list.
+ */
+ ChildListPropertyDescriptor propertyDescriptor;
+
+ /**
+ * A cursor for iterating over the elements of the list.
+ * Does not lose its position if the list is changed during
+ * the iteration.
+ */
+ class Cursor implements Iterator {
+ /**
+ * The position of the cursor between elements. If the value
+ * is N, then the cursor sits between the element at positions
+ * N-1 and N. Initially just before the first element of the
+ * list.
+ */
+ private int position = 0;
+
+ /* (non-Javadoc)
+ * Method declared on <code>Iterator</code>.
+ */
+ public boolean hasNext() {
+ return this.position < NodeList.this.store.size();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on <code>Iterator</code>.
+ */
+ public Object next() {
+ Object result = NodeList.this.store.get(this.position);
+ this.position++;
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on <code>Iterator</code>.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Adjusts this cursor to accomodate an add/remove at the given
+ * index.
+ *
+ * @param index the position at which the element was added
+ * or removed
+ * @param delta +1 for add, and -1 for remove
+ */
+ void update(int index, int delta) {
+ if (this.position > index) {
+ // the cursor has passed the added or removed element
+ this.position += delta;
+ }
+ }
+ }
+
+ /**
+ * A list of currently active cursors (element type:
+ * <code>Cursor</code>), or <code>null</code> if there are no
+ * active cursors.
+ * <p>
+ * It is important for storage considerations to maintain the
+ * null-means-empty invariant; otherwise, every NodeList instance
+ * will waste a lot of space. A cursor is needed only for the duration
+ * of a visit to the child nodes. Under normal circumstances, only a
+ * single cursor is needed; multiple cursors are only required if there
+ * are multiple visits going on at the same time.
+ * </p>
+ */
+ private List cursors = null;
+
+ /**
+ * Creates a new empty list of nodes owned by this node.
+ * This node will be the common parent of all nodes added to
+ * this list.
+ *
+ * @param property the property descriptor
+ * @since 3.0
+ */
+ NodeList(ChildListPropertyDescriptor property) {
+ super();
+ this.propertyDescriptor = property;
+ }
+
+ /* (non-javadoc)
+ * @see java.util.AbstractCollection#size()
+ */
+ public int size() {
+ return this.store.size();
+ }
+
+ /* (non-javadoc)
+ * @see AbstractList#get(int)
+ */
+ public Object get(int index) {
+ return this.store.get(index);
+ }
+
+ /* (non-javadoc)
+ * @see List#set(int, java.lang.Object)
+ */
+ public Object set(int index, Object element) {
+ if (element == null) {
+ throw new IllegalArgumentException();
+ }
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // delink old child from parent, and link new child to parent
+ ASTNode newChild = (ASTNode) element;
+ ASTNode oldChild = (ASTNode) this.store.get(index);
+ if (oldChild == newChild) {
+ return oldChild;
+ }
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+ ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+
+ Object result = this.store.set(index, newChild);
+ // n.b. setParent will call ast.modifying()
+ oldChild.setParent(null, null);
+ newChild.setParent(ASTNode.this, this.propertyDescriptor);
+ ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+ return result;
+ }
+
+ /* (non-javadoc)
+ * @see List#add(int, java.lang.Object)
+ */
+ public void add(int index, Object element) {
+ if (element == null) {
+ throw new IllegalArgumentException();
+ }
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // link new child to parent
+ ASTNode newChild = (ASTNode) element;
+ ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+ ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+
+
+ this.store.add(index, element);
+ updateCursors(index, +1);
+ // n.b. setParent will call ast.modifying()
+ newChild.setParent(ASTNode.this, this.propertyDescriptor);
+ ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+ }
+
+ /* (non-javadoc)
+ * @see List#remove(int)
+ */
+ public Object remove(int index) {
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // delink old child from parent
+ ASTNode oldChild = (ASTNode) this.store.get(index);
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+
+ ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+ // n.b. setParent will call ast.modifying()
+ oldChild.setParent(null, null);
+ Object result = this.store.remove(index);
+ updateCursors(index, -1);
+ ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+ return result;
+
+ }
+
+ /**
+ * Allocate a cursor to use for a visit. The client must call
+ * <code>releaseCursor</code> when done.
+ * <p>
+ * This method is internally synchronized on this NodeList.
+ * It is thread-safe to create a cursor.
+ * </p>
+ *
+ * @return a new cursor positioned before the first element
+ * of the list
+ */
+ Cursor newCursor() {
+ synchronized (this) {
+ // serialize cursor management on this NodeList
+ if (this.cursors == null) {
+ // convert null to empty list
+ this.cursors = new ArrayList(1);
+ }
+ Cursor result = new Cursor();
+ this.cursors.add(result);
+ return result;
+ }
+ }
+
+ /**
+ * Releases the given cursor at the end of a visit.
+ * <p>
+ * This method is internally synchronized on this NodeList.
+ * It is thread-safe to release a cursor.
+ * </p>
+ *
+ * @param cursor the cursor
+ */
+ void releaseCursor(Cursor cursor) {
+ synchronized (this) {
+ // serialize cursor management on this NodeList
+ this.cursors.remove(cursor);
+ if (this.cursors.isEmpty()) {
+ // important: convert empty list back to null
+ // otherwise the node will hang on to needless junk
+ this.cursors = null;
+ }
+ }
+ }
+
+ /**
+ * Adjusts all cursors to accomodate an add/remove at the given
+ * index.
+ * <p>
+ * This method is only used when the list is being modified.
+ * The AST is not thread-safe if any of the clients are modifying it.
+ * </p>
+ *
+ * @param index the position at which the element was added
+ * or removed
+ * @param delta +1 for add, and -1 for remove
+ */
+ private synchronized void updateCursors(int index, int delta) {
+ if (this.cursors == null) {
+ // there are no cursors to worry about
+ return;
+ }
+ for (Iterator it = this.cursors.iterator(); it.hasNext(); ) {
+ Cursor c = (Cursor) it.next();
+ c.update(index, delta);
+ }
+ }
+
+ /**
+ * Returns an estimate of the memory footprint of this node list
+ * instance in bytes.
+ * <ul>
+ * <li>1 object header for the NodeList instance</li>
+ * <li>5 4-byte fields of the NodeList instance</li>
+ * <li>0 for cursors since null unless walk in progress</li>
+ * <li>1 object header for the ArrayList instance</li>
+ * <li>2 4-byte fields of the ArrayList instance</li>
+ * <li>1 object header for an Object[] instance</li>
+ * <li>4 bytes in array for each element</li>
+ * </ul>
+ *
+ * @return the size of this node list in bytes
+ */
+ int memSize() {
+ int result = HEADERS + 5 * 4;
+ result += HEADERS + 2 * 4;
+ result += HEADERS + 4 * size();
+ return result;
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of this node
+ * list and all its subtrees.
+ *
+ * @return the size of this list of subtrees in bytes
+ */
+ int listSize() {
+ int result = memSize();
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ ASTNode child = (ASTNode) it.next();
+ result += child.treeSize();
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Creates a new AST node owned by the given AST. Once established,
+ * the relationship between an AST node and its owning AST does not change
+ * over the lifetime of the node. The new node has no parent node,
+ * and no properties.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses my be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ASTNode(AST ast) {
+ if (ast == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.ast = ast;
+ setNodeType(getNodeType0());
+ setFlags(ast.getDefaultNodeFlag());
+ // setFlags calls modifying();
+ }
+
+ /**
+ * Returns this node's AST.
+ * <p>
+ * Note that the relationship between an AST node and its owing AST does
+ * not change over the lifetime of a node.
+ * </p>
+ *
+ * @return the AST that owns this node
+ */
+ public final AST getAST() {
+ return this.ast;
+ }
+
+ /**
+ * Returns this node's parent node, or <code>null</code> if this is the
+ * root node.
+ * <p>
+ * Note that the relationship between an AST node and its parent node
+ * may change over the lifetime of a node.
+ * </p>
+ *
+ * @return the parent of this node, or <code>null</code> if none
+ */
+ public final ASTNode getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Returns the location of this node within its parent,
+ * or <code>null</code> if this is a root node.
+ * <p>
+ * <pre>
+ * ASTNode node = ...;
+ * ASTNode parent = node.getParent();
+ * StructuralPropertyDescriptor location = node.getLocationInParent();
+ * assert (parent != null) == (location != null);
+ * if ((location != null) && location.isChildProperty())
+ * assert parent.getStructuralProperty(location) == node;
+ * if ((location != null) && location.isChildListProperty())
+ * assert ((List) parent.getStructuralProperty(location)).contains(node);
+ * </pre>
+ * </p>
+ * <p>
+ * Note that the relationship between an AST node and its parent node
+ * may change over the lifetime of a node.
+ * </p>
+ *
+ * @return the location of this node in its parent,
+ * or <code>null</code> if this node has no parent
+ * @since 3.0
+ */
+ public final StructuralPropertyDescriptor getLocationInParent() {
+ return this.location;
+ }
+
+ /**
+ * Returns the root node at or above this node; returns this node if
+ * it is a root.
+ *
+ * @return the root node at or above this node
+ */
+ public final ASTNode getRoot() {
+ ASTNode candidate = this;
+ while (true) {
+ ASTNode p = candidate.getParent();
+ if (p == null) {
+ // candidate has no parent - that's the guy
+ return candidate;
+ }
+ candidate = p;
+ }
+ }
+
+ /**
+ * Returns the value of the given structural property for this node. The value
+ * returned depends on the kind of property:
+ * <ul>
+ * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
+ * or <code>null</code> if none; primitive values are "boxed"</li>
+ * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
+ * or <code>null</code> if none</li>
+ * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
+ * </ul>
+ *
+ * @param property the property
+ * @return the value, or <code>null</code> if none
+ * @exception RuntimeException if this node does not have the given property
+ * @since 3.0
+ */
+ public final Object getStructuralProperty(StructuralPropertyDescriptor property) {
+ if (property instanceof SimplePropertyDescriptor) {
+ SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+ if (p.getValueType() == int.class) {
+ int result = internalGetSetIntProperty(p, true, 0);
+ return new Integer(result);
+ } else if (p.getValueType() == boolean.class) {
+ boolean result = internalGetSetBooleanProperty(p, true, false);
+ return Boolean.valueOf(result);
+ } else {
+ return internalGetSetObjectProperty(p, true, null);
+ }
+ }
+ if (property instanceof ChildPropertyDescriptor) {
+ return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
+ }
+ if (property instanceof ChildListPropertyDescriptor) {
+ return internalGetChildListProperty((ChildListPropertyDescriptor) property);
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets the value of the given structural property for this node. The value
+ * passed depends on the kind of property:
+ * <ul>
+ * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
+ * or <code>null</code> if none; primitive values are "boxed"</li>
+ * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
+ * or <code>null</code> if none</li>
+ * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
+ * </ul>
+ *
+ * @param property the property
+ * @param value the property value
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given property cannot be set
+ * @since 3.0
+ */
+ public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) {
+ if (property instanceof SimplePropertyDescriptor) {
+ SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+ if (p.getValueType() == int.class) {
+ int arg = ((Integer) value).intValue();
+ internalGetSetIntProperty(p, false, arg);
+ return;
+ } else if (p.getValueType() == boolean.class) {
+ boolean arg = ((Boolean) value).booleanValue();
+ internalGetSetBooleanProperty(p, false, arg);
+ return;
+ } else {
+ if (value == null && p.isMandatory()) {
+ throw new IllegalArgumentException();
+ }
+ internalGetSetObjectProperty(p, false, value);
+ return;
+ }
+ }
+ if (property instanceof ChildPropertyDescriptor) {
+ ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
+ ASTNode child = (ASTNode) value;
+ if (child == null && p.isMandatory()) {
+ throw new IllegalArgumentException();
+ }
+ internalGetSetChildProperty(p, false, child);
+ return;
+ }
+ if (property instanceof ChildListPropertyDescriptor) {
+ throw new IllegalArgumentException("Cannot set the list of child list property"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the value of the given int-valued property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is int.
+ *
+ * @param property the property
+ * @param get <code>true</code> for a get operation, and
+ * <code>false</code> for a set operation
+ * @param value the new property value; ignored for get operations
+ * @return the value; always returns
+ * <code>0</code> for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ * @since 3.0
+ */
+ int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the value of the given boolean-valued property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is boolean.
+ *
+ * @param property the property
+ * @param get <code>true</code> for a get operation, and
+ * <code>false</code> for a set operation
+ * @param value the new property value; ignored for get operations
+ * @return the value; always returns
+ * <code>false</code> for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ * @since 3.0
+ */
+ boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is a reference type.
+ *
+ * @param property the property
+ * @param get <code>true</code> for a get operation, and
+ * <code>false</code> for a set operation
+ * @param value the new property value, or <code>null</code> if none;
+ * ignored for get operations
+ * @return the value, or <code>null</code> if none; always returns
+ * <code>null</code> for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ * @since 3.0
+ */
+ Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the child value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one child property.
+ *
+ * @param property the property
+ * @param get <code>true</code> for a get operation, and
+ * <code>false</code> for a set operation
+ * @param child the new child value, or <code>null</code> if none;
+ * always <code>null</code> for get operations
+ * @return the child, or <code>null</code> if none; always returns
+ * <code>null</code> for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given child cannot be set as specified
+ * @since 3.0
+ */
+ ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this noed does not have such a property. This method should be
+ * extended in subclasses that have at leasy one child list property.
+ *
+ * @param property the property
+ * @return the list (element type: {@link ASTNode})
+ * @exception RuntimeException if the given node does not have the
+ * given property
+ * @since 3.0
+ */
+ List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns a list of structural property descriptors for nodes of the
+ * same type as this node. Clients must not modify the result.
+ * <p>
+ * Note that property descriptors are a meta-level mechanism
+ * for manipulating ASTNodes in a generic way. They are
+ * unrelated to <code>get/setProperty</code>.
+ * </p>
+ *
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public final List structuralPropertiesForType() {
+ return internalStructuralPropertiesForType(this.ast.apiLevel);
+ }
+
+ /**
+ * Returns a list of property descriptors for this node type.
+ * Clients must not modify the result. This abstract method
+ * must be implemented in each concrete AST node type.
+ * <p>
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ * </p>
+ *
+ * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ abstract List internalStructuralPropertiesForType(int apiLevel);
+
+ /**
+ * Internal helper method that starts the building a list of
+ * property descriptors for the given node type.
+ *
+ * @param nodeClass the class for a concrete node type
+ * @param propertyList empty list
+ */
+ static void createPropertyList(Class nodeClass, List propertyList) {
+ // stuff nodeClass at head of list for future ref
+ propertyList.add(nodeClass);
+ }
+
+ /**
+ * Internal helper method that adding a property descriptor.
+ *
+ * @param property the structural property descriptor
+ * @param propertyList list beginning with the AST node class
+ * followed by accumulated structural property descriptors
+ */
+ static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
+ Class nodeClass = (Class) propertyList.get(0);
+ if (property.getNodeClass() != nodeClass) {
+ // easily made cut-and-paste mistake
+ throw new RuntimeException("Structural property descriptor has wrong node class!"); //$NON-NLS-1$
+ }
+ propertyList.add(property);
+ }
+
+ /**
+ * Internal helper method that completes the building of
+ * a node type's structural property descriptor list.
+ *
+ * @param propertyList list beginning with the AST node class
+ * followed by accumulated structural property descriptors
+ * @return unmodifiable list of structural property descriptors
+ * (element type: <code>StructuralPropertyDescriptor</code>)
+ */
+ static List reapPropertyList(List propertyList) {
+ propertyList.remove(0); // remove nodeClass
+ // compact
+ ArrayList a = new ArrayList(propertyList.size());
+ a.addAll(propertyList);
+ return Collections.unmodifiableList(a);
+ }
+
+ /**
+ * Checks that this AST operation is not used when
+ * building JLS2 level ASTs.
+
+ * @exception UnsupportedOperationException
+ * @since 3.0
+ */
+ final void unsupportedIn2() {
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks that this AST operation is only used when
+ * building JLS2 level ASTs.
+
+ * @exception UnsupportedOperationException
+ * @since 3.0
+ */
+ final void supportedOnlyIn2() {
+ if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets or clears this node's parent node and location.
+ * <p>
+ * Note that this method is package-private. The pointer from a node
+ * to its parent is set implicitly as a side effect of inserting or
+ * removing the node as a child of another node. This method calls
+ * <code>ast.modifying()</code>.
+ * </p>
+ *
+ * @param parent the new parent of this node, or <code>null</code> if none
+ * @param property the location of this node in its parent,
+ * or <code>null</code> if <code>parent</code> is <code>null</code>
+ * @see #getLocationInParent
+ * @see #getParent
+ * @since 3.0
+ */
+ final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
+ this.ast.modifying();
+ this.parent = parent;
+ this.location = property;
+ }
+
+ /**
+ * Removes this node from its parent. Has no effect if this node
+ * is unparented. If this node appears as an element of a child list
+ * property of its parent, then this node is removed from the
+ * list using <code>List.remove</code>.
+ * If this node appears as the value of a child property of its
+ * parent, then this node is detached from its parent
+ * by passing <code>null</code> to the appropriate setter method;
+ * this operation fails if this node is in a mandatory property.
+ *
+ * @since 3.0
+ */
+ public final void delete() {
+ StructuralPropertyDescriptor p = getLocationInParent();
+ if (p == null) {
+ // node is unparented
+ return;
+ }
+ if (p.isChildProperty()) {
+ getParent().setStructuralProperty(this.location, null);
+ return;
+ }
+ if (p.isChildListProperty()) {
+ List l = (List) getParent().getStructuralProperty(this.location);
+ l.remove(this);
+ }
+ }
+
+ /**
+ * Checks whether the given new child node is a node
+ * in a different AST from its parent-to-be, whether it is
+ * already has a parent, whether adding it to its
+ * parent-to-be would create a cycle, and whether the child is of
+ * the right type. The parent-to-be is the enclosing instance.
+ *
+ * @param node the parent-to-be node
+ * @param newChild the new child of the parent
+ * @param cycleCheck <code>true</code> if cycles are possible and need
+ * to be checked, <code>false</code> if cycles are impossible and do
+ * not need to be checked
+ * @param nodeType a type constraint on child nodes, or <code>null</code>
+ * if no special check is required
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the child is null</li>
+ * <li>the node belongs to a different AST</li>
+ * <li>the child has the incorrect node type</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ static void checkNewChild(ASTNode node, ASTNode newChild,
+ boolean cycleCheck, Class nodeType) {
+ if (newChild.ast != node.ast) {
+ // new child is from a different AST
+ throw new IllegalArgumentException();
+ }
+ if (newChild.getParent() != null) {
+ // new child currently has a different parent
+ throw new IllegalArgumentException();
+ }
+ if (cycleCheck && newChild == node.getRoot()) {
+ // inserting new child would create a cycle
+ throw new IllegalArgumentException();
+ }
+ Class childClass = newChild.getClass();
+ if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
+ // new child is not of the right type
+ throw new ClassCastException();
+ }
+ if ((newChild.typeAndFlags & PROTECT) != 0) {
+ // new child node is protected => cannot be parented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Prelude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * Here is the code pattern found in all AST node subclasses:
+ * <pre>
+ * ASTNode oldChild = this.foo;
+ * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+ * this.foo = newFoo;
+ * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+ * </pre>
+ * The first part (preReplaceChild) does all the precondition checks,
+ * reports pre-delete events, and changes parent links.
+ * The old child is delinked from its parent (making it a root node),
+ * and the new child node is linked to its parent. The new child node
+ * must be a root node in the same AST as its new parent, and must not
+ * be an ancestor of this node. All three nodes must be
+ * modifiable (not PROTECTED). The replace operation must fail
+ * atomically; so it is crucial that all precondition checks
+ * be done before any linking and delinking happens.
+ * The final part (postReplaceChild )reports post-add events.
+ * <p>
+ * This method calls <code>ast.modifying()</code> for the nodes affected.
+ * </p>
+ *
+ * @param oldChild the old child of this node, or <code>null</code> if
+ * there was no old child to replace
+ * @param newChild the new child of this node, or <code>null</code> if
+ * there is no replacement child
+ * @param property the property descriptor of this node describing
+ * the relationship between node and child
+ * @exception RuntimeException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * <li>any of the nodes involved are unmodifiable</li>
+ * </ul>
+ * @since 3.0
+ */
+ final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ if (newChild != null) {
+ checkNewChild(this, newChild, property.cycleRisk, null);
+ }
+ // delink old child from parent
+ if (oldChild != null) {
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child node is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ if (newChild != null) {
+ this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
+ } else {
+ this.ast.preRemoveChildEvent(this, oldChild, property);
+ }
+ oldChild.setParent(null, null);
+ } else {
+ if(newChild != null) {
+ this.ast.preAddChildEvent(this, newChild, property);
+ }
+ }
+ // link new child to parent
+ if (newChild != null) {
+ newChild.setParent(this, property);
+ // cannot notify postAddChildEvent until parent is linked to child too
+ }
+ }
+
+ /**
+ * Postlude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
+ * for details.
+ * @since 3.0
+ */
+ final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+ // link new child to parent
+ if (newChild != null) {
+ if (oldChild != null) {
+ this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
+ } else {
+ this.ast.postAddChildEvent(this, newChild, property);
+ }
+ } else {
+ this.ast.postRemoveChildEvent(this, oldChild, property);
+ }
+ }
+
+ /**
+ * Prelude portion of the "3 step program" for changing the
+ * value of a simple property of this node.
+ * Here is the code pattern found in all AST node subclasses:
+ * <pre>
+ * preValueChange(FOO_PROPERTY);
+ * this.foo = newFoo;
+ * postValueChange(FOO_PROPERTY);
+ * </pre>
+ * The first part (preValueChange) does the precondition check
+ * to make sure the node is modifiable (not PROTECTED).
+ * The change operation must fail atomically; so it is crucial
+ * that the precondition checks are done before the field is
+ * hammered. The final part (postValueChange)reports post-change
+ * events.
+ * <p>
+ * This method calls <code>ast.modifying()</code> for the node affected.
+ * </p>
+ *
+ * @param property the property descriptor of this node
+ * @exception RuntimeException if:
+ * <ul>
+ * <li>this node is unmodifiable</li>
+ * </ul>
+ * @since 3.0
+ */
+ final void preValueChange(SimplePropertyDescriptor property) {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot change valure of properties
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ this.ast.preValueChangeEvent(this, property);
+ this.ast.modifying();
+ }
+
+ /**
+ * Postlude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
+ * @since 3.0
+ */
+ final void postValueChange(SimplePropertyDescriptor property) {
+ this.ast.postValueChangeEvent(this, property);
+ }
+
+ /**
+ * Ensures that this node is modifiable (that is, not marked PROTECTED).
+ * If successful, calls ast.modifying().
+ * @exception RuntimeException is not modifiable
+ */
+ final void checkModifiable() {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ this.ast.modifying();
+ }
+
+ /**
+ * Begin lazy initialization of this node.
+ * Here is the code pattern found in all AST
+ * node subclasses:
+ * <pre>
+ * if (this.foo == null) {
+ * // lazy init must be thread-safe for readers
+ * synchronized (this) {
+ * if (this.foo == null) {
+ * preLazyInit();
+ * this.foo = ...; // code to create new node
+ * postLazyInit(this.foo, FOO_PROPERTY);
+ * }
+ * }
+ * }
+ * </pre>
+ * @since 3.0
+ */
+ final void preLazyInit() {
+ // IMPORTANT: this method is called by readers
+ // ASTNode.this is locked at this point
+ this.ast.disableEvents();
+ // will turn events back on in postLasyInit
+ }
+
+ /**
+ * End lazy initialization of this node.
+ *
+ * @param newChild the new child of this node, or <code>null</code> if
+ * there is no replacement child
+ * @param property the property descriptor of this node describing
+ * the relationship between node and child
+ * @since 3.0
+ */
+ final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers
+ // ASTNode.this is locked at this point
+ // newChild is brand new (so no chance of concurrent access)
+ newChild.setParent(this, property);
+ // turn events back on (they were turned off in corresponding preLazyInit)
+ this.ast.reenableEvents();
+ }
+
+ /**
+ * Returns the named property of this node, or <code>null</code> if none.
+ *
+ * @param propertyName the property name
+ * @return the property value, or <code>null</code> if none
+ * @see #setProperty(String,Object)
+ */
+ public final Object getProperty(String propertyName) {
+ if (propertyName == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.property1 == null) {
+ // node has no properties at all
+ return null;
+ }
+ if (this.property1 instanceof String) {
+ // node has only a single property
+ if (propertyName.equals(this.property1)) {
+ return this.property2;
+ } else {
+ return null;
+ }
+ }
+ // otherwise node has table of properties
+ Map m = (Map) this.property1;
+ return m.get(propertyName);
+ }
+
+ /**
+ * Sets the named property of this node to the given value,
+ * or to <code>null</code> to clear it.
+ * <p>
+ * Clients should employ property names that are sufficiently unique
+ * to avoid inadvertent conflicts with other clients that might also be
+ * setting properties on the same node.
+ * </p>
+ * <p>
+ * Note that modifying a property is not considered a modification to the
+ * AST itself. This is to allow clients to decorate existing nodes with
+ * their own properties without jeopardizing certain things (like the
+ * validity of bindings), which rely on the underlying tree remaining static.
+ * </p>
+ *
+ * @param propertyName the property name
+ * @param data the new property value, or <code>null</code> if none
+ * @see #getProperty(String)
+ */
+ public final void setProperty(String propertyName, Object data) {
+ if (propertyName == null) {
+ throw new IllegalArgumentException();
+ }
+ // N.B. DO NOT CALL ast.modifying();
+
+ if (this.property1 == null) {
+ // node has no properties at all
+ if (data == null) {
+ // we already know this
+ return;
+ }
+ // node gets its fist property
+ this.property1 = propertyName;
+ this.property2 = data;
+ return;
+ }
+
+ if (this.property1 instanceof String) {
+ // node has only a single property
+ if (propertyName.equals(this.property1)) {
+ // we're in luck
+ this.property2 = data;
+ if (data == null) {
+ // just deleted last property
+ this.property1 = null;
+ this.property2 = null;
+ }
+ return;
+ }
+ if (data == null) {
+ // we already know this
+ return;
+ }
+ // node already has one property - getting its second
+ // convert to more flexible representation
+ HashMap m = new HashMap(2);
+ m.put(this.property1, this.property2);
+ m.put(propertyName, data);
+ this.property1 = m;
+ this.property2 = null;
+ return;
+ }
+
+ // node has two or more properties
+ HashMap m = (HashMap) this.property1;
+ if (data == null) {
+ m.remove(propertyName);
+ // check for just one property left
+ if (m.size() == 1) {
+ // convert to more efficient representation
+ Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]);
+ this.property1 = entries[0].getKey();
+ this.property2 = entries[0].getValue();
+ }
+ return;
+ } else {
+ m.put(propertyName, data);
+ // still has two or more properties
+ return;
+ }
+ }
+
+ /**
+ * Returns an unmodifiable table of the properties of this node with
+ * non-<code>null</code> values.
+ *
+ * @return the table of property values keyed by property name
+ * (key type: <code>String</code>; value type: <code>Object</code>)
+ */
+ public final Map properties() {
+ if (this.property1 == null) {
+ // node has no properties at all
+ return UNMODIFIABLE_EMPTY_MAP;
+ }
+ if (this.property1 instanceof String) {
+ // node has a single property
+ return Collections.singletonMap(this.property1, this.property2);
+ }
+
+ // node has two or more properties
+ if (this.property2 == null) {
+ this.property2 = Collections.unmodifiableMap((Map) this.property1);
+ }
+ // property2 is unmodifiable wrapper for map in property1
+ return (Map) this.property2;
+ }
+
+ /**
+ * Returns the flags associated with this node.
+ * <p>
+ * No flags are associated with newly created nodes.
+ * </p>
+ * <p>
+ * The flags are the bitwise-or of individual flags.
+ * The following flags are currently defined:
+ * <ul>
+ * <li>{@link #MALFORMED} - indicates node is syntactically
+ * malformed</li>
+ * <li>{@link #ORIGINAL} - indicates original node
+ * created by ASTParser</li>
+ * <li>{@link #PROTECT} - indicates node is protected
+ * from further modification</li>
+ * <li>{@link #RECOVERED} - indicates node or a part of this node
+ * is recovered from source that contains a syntax error</li>
+ * </ul>
+ * Other bit positions are reserved for future use.
+ * </p>
+ *
+ * @return the bitwise-or of individual flags
+ * @see #setFlags(int)
+ */
+ public final int getFlags() {
+ return this.typeAndFlags & 0xFFFF;
+ }
+
+ /**
+ * Sets the flags associated with this node to the given value.
+ * <p>
+ * The flags are the bitwise-or of individual flags.
+ * The following flags are currently defined:
+ * <ul>
+ * <li>{@link #MALFORMED} - indicates node is syntactically
+ * malformed</li>
+ * <li>{@link #ORIGINAL} - indicates original node
+ * created by ASTParser</li>
+ * <li>{@link #PROTECT} - indicates node is protected
+ * from further modification</li>
+ * <li>{@link #RECOVERED} - indicates node or a part of this node
+ * is recovered from source that contains a syntax error</li>
+ * </ul>
+ * Other bit positions are reserved for future use.
+ * </p>
+ * <p>
+ * Note that the flags are <em>not</em> considered a structural
+ * property of the node, and can be changed even if the
+ * node is marked as protected.
+ * </p>
+ *
+ * @param flags the bitwise-or of individual flags
+ * @see #getFlags()
+ */
+ public final void setFlags(int flags) {
+ this.ast.modifying();
+ int old = this.typeAndFlags & 0xFFFF0000;
+ this.typeAndFlags = old | (flags & 0xFFFF);
+ }
+
+ /**
+ * Returns an integer value identifying the type of this concrete AST node.
+ * The values are small positive integers, suitable for use in switch statements.
+ * <p>
+ * For each concrete node type there is a unique node type constant (name
+ * and value). The unique node type constant for a concrete node type such as
+ * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
+ * </p>
+ *
+ * @return one of the node type constants
+ */
+ public final int getNodeType() {
+ return this.typeAndFlags >>> 16;
+ }
+
+ /**
+ * Sets the integer value identifying the type of this concrete AST node.
+ * The values are small positive integers, suitable for use in switch statements.
+ *
+ * @param nodeType one of the node type constants
+ */
+ private void setNodeType(int nodeType) {
+ int old = this.typeAndFlags & 0xFFFF0000;
+ this.typeAndFlags = old | (nodeType << 16);
+ }
+
+ /**
+ * Returns an integer value identifying the type of this concrete AST node.
+ * <p>
+ * This internal method is implemented in each of the
+ * concrete node subclasses.
+ * </p>
+ *
+ * @return one of the node type constants
+ */
+ abstract int getNodeType0();
+
+ /**
+ * The <code>ASTNode</code> implementation of this <code>Object</code>
+ * method uses object identity (==). Use <code>subtreeMatch</code> to
+ * compare two subtrees for equality.
+ *
+ * @param obj {@inheritDoc}
+ * @return {@inheritDoc}
+ * @see #subtreeMatch(ASTMatcher matcher, Object other)
+ */
+ public final boolean equals(Object obj) {
+ return this == obj; // equivalent to Object.equals
+ }
+
+ /*
+ * (non-Javadoc)
+ * This makes it consistent with the fact that a equals methods has been provided.
+ * @see java.lang.Object#hashCode()
+ */
+ public final int hashCode() {
+ return super.hashCode();
+ }
+
+ /**
+ * Returns whether the subtree rooted at the given node matches the
+ * given other object as decided by the given matcher.
+ *
+ * @param matcher the matcher
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match
+ */
+ public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
+ return subtreeMatch0(matcher, other);
+ }
+
+ /**
+ * Returns whether the subtree rooted at the given node matches the
+ * given other object as decided by the given matcher.
+ * <p>
+ * This internal method is implemented in each of the
+ * concrete node subclasses.
+ * </p>
+ *
+ * @param matcher the matcher
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match
+ */
+ abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at the
+ * given node. The resulting nodes are owned by the given AST,
+ * which may be different from the ASTs of the given node.
+ * Even if the given node has a parent, the result node will be unparented.
+ * <p>
+ * Source range information on the original nodes is automatically copied to the new
+ * nodes. Client properties (<code>properties</code>) are not carried over.
+ * </p>
+ * <p>
+ * The node's <code>AST</code> and the target <code>AST</code> must support
+ * the same API level.
+ * </p>
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @param node the node to copy, or <code>null</code> if none
+ * @return the copied node, or <code>null</code> if <code>node</code>
+ * is <code>null</code>
+ */
+ public static ASTNode copySubtree(AST target, ASTNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (target == null) {
+ throw new IllegalArgumentException();
+ }
+ if (target.apiLevel() != node.getAST().apiLevel()) {
+ throw new UnsupportedOperationException();
+ }
+ ASTNode newNode = node.clone(target);
+ return newNode;
+ }
+
+ /**
+ * Returns a deep copy of the subtrees of AST nodes rooted at the
+ * given list of nodes. The resulting nodes are owned by the given AST,
+ * which may be different from the ASTs of the nodes in the list.
+ * Even if the nodes in the list have parents, the nodes in the result
+ * will be unparented.
+ * <p>
+ * Source range information on the original nodes is automatically copied to the new
+ * nodes. Client properties (<code>properties</code>) are not carried over.
+ * </p>
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @param nodes the list of nodes to copy
+ * (element type: <code>ASTNode</code>)
+ * @return the list of copied subtrees
+ * (element type: <code>ASTNode</code>)
+ */
+ public static List copySubtrees(AST target, List nodes) {
+ List result = new ArrayList(nodes.size());
+ for (Iterator it = nodes.iterator(); it.hasNext(); ) {
+ ASTNode oldNode = (ASTNode) it.next();
+ ASTNode newNode = oldNode.clone(target);
+ result.add(newNode);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at this node.
+ * The resulting nodes are owned by the given AST, which may be different
+ * from the AST of this node. Even if this node has a parent, the
+ * result node will be unparented.
+ * <p>
+ * This method reports pre- and post-clone events, and dispatches
+ * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
+ * </p>
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @return the root node of the copies subtree
+ */
+ final ASTNode clone(AST target) {
+ this.ast.preCloneNodeEvent(this);
+ ASTNode c = clone0(target);
+ this.ast.postCloneNodeEvent(this, c);
+ return c;
+ }
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at this node.
+ * The resulting nodes are owned by the given AST, which may be different
+ * from the AST of this node. Even if this node has a parent, the
+ * result node will be unparented.
+ * <p>
+ * This method must be implemented in subclasses.
+ * </p>
+ * <p>
+ * This method does not report pre- and post-clone events.
+ * All callers should instead call <code>clone(AST)</code>
+ * to ensure that pre- and post-clone events are reported.
+ * </p>
+ * <p>
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ * </p>
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @return the root node of the copies subtree
+ */
+ abstract ASTNode clone0(AST target);
+
+ /**
+ * Accepts the given visitor on a visit of the current node.
+ *
+ * @param visitor the visitor object
+ * @exception IllegalArgumentException if the visitor is null
+ */
+ public final void accept(ASTVisitor visitor) {
+ if (visitor == null) {
+ throw new IllegalArgumentException();
+ }
+ // begin with the generic pre-visit
+ if (visitor.preVisit2(this)) {
+ // dynamic dispatch to internal method for type-specific visit/endVisit
+ accept0(visitor);
+ }
+ // end with the generic post-visit
+ visitor.postVisit(this);
+ }
+
+ /**
+ * Accepts the given visitor on a type-specific visit of the current node.
+ * This method must be implemented in all concrete AST node types.
+ * <p>
+ * General template for implementation on each concrete ASTNode class:
+ * <pre>
+ * <code>
+ * boolean visitChildren = visitor.visit(this);
+ * if (visitChildren) {
+ * // visit children in normal left to right reading order
+ * acceptChild(visitor, getProperty1());
+ * acceptChildren(visitor, rawListProperty);
+ * acceptChild(visitor, getProperty2());
+ * }
+ * visitor.endVisit(this);
+ * </code>
+ * </pre>
+ * Note that the caller (<code>accept</code>) take cares of invoking
+ * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
+ * </p>
+ *
+ * @param visitor the visitor object
+ */
+ abstract void accept0(ASTVisitor visitor);
+
+ /**
+ * Accepts the given visitor on a visit of the current node.
+ * <p>
+ * This method should be used by the concrete implementations of
+ * <code>accept0</code> to traverse optional properties. Equivalent
+ * to <code>child.accept(visitor)</code> if <code>child</code>
+ * is not <code>null</code>.
+ * </p>
+ *
+ * @param visitor the visitor object
+ * @param child the child AST node to dispatch too, or <code>null</code>
+ * if none
+ */
+ final void acceptChild(ASTVisitor visitor, ASTNode child) {
+ if (child == null) {
+ return;
+ }
+ child.accept(visitor);
+ }
+
+ /**
+ * Accepts the given visitor on a visit of the given live list of
+ * child nodes.
+ * <p>
+ * This method must be used by the concrete implementations of
+ * <code>accept</code> to traverse list-values properties; it
+ * encapsulates the proper handling of on-the-fly changes to the list.
+ * </p>
+ *
+ * @param visitor the visitor object
+ * @param children the child AST node to dispatch too, or <code>null</code>
+ * if none
+ */
+ final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
+ // use a cursor to keep track of where we are up to
+ // (the list may be changing under foot)
+ if(children != null) {
+ NodeList.Cursor cursor = children.newCursor();
+ try {
+ while (cursor.hasNext()) {
+ ASTNode child = (ASTNode) cursor.next();
+ child.accept(visitor);
+ }
+ } finally {
+ children.releaseCursor(cursor);
+ }
+ }
+ }
+
+ /**
+ * Returns the character index into the original source file indicating
+ * where the source fragment corresponding to this node begins.
+ * <p>
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ * See {@link ASTParser#setKind(int)} for details
+ * on precisely where source ranges begin and end.
+ * </p>
+ *
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is recorded for this node
+ * @see #getLength()
+ * @see ASTParser
+ */
+ public final int getStartPosition() {
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the length in characters of the original source file indicating
+ * where the source fragment corresponding to this node ends.
+ * <p>
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ * See {@link ASTParser#setKind(int)} methods for details
+ * on precisely where source ranges begin and end.
+ * </p>
+ *
+ * @return a (possibly 0) length, or <code>0</code>
+ * if no source position information is recorded for this node
+ * @see #getStartPosition()
+ * @see ASTParser
+ */
+ public final int getLength() {
+ return this.length;
+ }
+
+ /**
+ * Sets the source range of the original source file where the source
+ * fragment corresponding to this node was found.
+ * <p>
+ * See {@link ASTParser#setKind(int)} for details
+ * on precisely where source ranges are supposed to begin and end.
+ * </p>
+ *
+ * @param startPosition a 0-based character index,
+ * or <code>-1</code> if no source position information is
+ * available for this node
+ * @param length a (possibly 0) length,
+ * or <code>0</code> if no source position information is recorded
+ * for this node
+ * @see #getStartPosition()
+ * @see #getLength()
+ * @see ASTParser
+ */
+ public final void setSourceRange(int startPosition, int length) {
+ if (startPosition >= 0 && length < 0) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < 0 && length != 0) {
+ throw new IllegalArgumentException();
+ }
+ // source positions are not considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.startPosition = startPosition;
+ this.length = length;
+ }
+
+ /**
+ * Returns a string representation of this node suitable for debugging
+ * purposes only.
+ *
+ * @return a debug string
+ */
+ public final String toString() {
+ StringBuffer buffer = new StringBuffer();
+ int p = buffer.length();
+ try {
+ appendDebugString(buffer);
+ } catch (RuntimeException e) {
+ // since debugger sometimes call toString methods, problems can easily happen when
+ // toString is called on an instance that is being initialized
+ buffer.setLength(p);
+ buffer.append("!"); //$NON-NLS-1$
+ buffer.append(standardToString());
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the string representation of this node produced by the standard
+ * <code>Object.toString</code> method.
+ *
+ * @return a debug string
+ */
+ final String standardToString() {
+ return super.toString();
+ }
+
+ /**
+ * Appends a debug representation of this node to the given string buffer.
+ * <p>
+ * The <code>ASTNode</code> implementation of this method prints out the entire
+ * subtree. Subclasses may override to provide a more succinct representation.
+ * </p>
+ *
+ * @param buffer the string buffer to append to
+ */
+ void appendDebugString(StringBuffer buffer) {
+ // print the subtree by default
+ appendPrintString(buffer);
+ }
+
+ /**
+ * Appends a standard Java source code representation of this subtree to the given
+ * string buffer.
+ *
+ * @param buffer the string buffer to append to
+ */
+ final void appendPrintString(StringBuffer buffer) {
+ NaiveASTFlattener printer = new NaiveASTFlattener();
+ accept(printer);
+ buffer.append(printer.getResult());
+ }
+
+ /**
+ * Estimate of size of an object header in bytes.
+ */
+ static final int HEADERS = 12;
+
+ /**
+ * Approximate base size of an AST node instance in bytes,
+ * including object header and instance fields.
+ * That is, HEADERS + (# instance vars in ASTNode)*4.
+ */
+ static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
+
+ /**
+ * Returns an estimate of the memory footprint, in bytes,
+ * of the given string.
+ *
+ * @param string the string to measure, or <code>null</code>
+ * @return the size of this string object in bytes, or
+ * 0 if the string is <code>null</code>
+ * @since 3.0
+ */
+ static int stringSize(String string) {
+ int size = 0;
+ if (string != null) {
+ // Strings usually have 4 instance fields, one of which is a char[]
+ size += HEADERS + 4 * 4;
+ // char[] has 2 bytes per character
+ size += HEADERS + 2 * string.length();
+ }
+ return size;
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of the entire
+ * subtree rooted at this node.
+ *
+ * @return the size of this subtree in bytes
+ */
+ public final int subtreeBytes() {
+ return treeSize();
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of the entire
+ * subtree rooted at this node.
+ * <p>
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ * </p>
+ *
+ * @return the size of this subtree in bytes
+ */
+ abstract int treeSize();
+
+ /**
+ * Returns an estimate of the memory footprint of this node in bytes.
+ * The estimate does not include the space occupied by child nodes.
+ *
+ * @return the size of this node in bytes
+ */
+ abstract int memSize();
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
new file mode 100644
index 000000000..9da9740d1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -0,0 +1,1252 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTParser.java 23401 2010-02-02 23:56:05Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
+import org.eclipse.jdt.internal.core.util.RecordedParsingInformation;
+import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+
+/**
+ * A Java language parser for creating abstract syntax trees (ASTs).
+ * <p>
+ * Example: Create basic AST from source string
+ * <pre>
+ * char[] source = ...;
+ * ASTParser parser = ASTParser.newParser(AST.JLS3); // handles JDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
+ * parser.setSource(source);
+ * CompilationUnit result = (CompilationUnit) parser.createAST(null);
+ * </pre>
+ * Once a configured parser instance has been used to create an AST,
+ * the settings are automatically reset to their defaults,
+ * ready for the parser instance to be reused.
+ * </p>
+ * <p>
+ * There are a number of configurable features:
+ * <ul>
+ * <li>Source string from {@link #setSource(char[]) char[]},
+ * {@link #setSource(ICompilationUnit) ICompilationUnit},
+ * or {@link #setSource(IClassFile) IClassFile}, and limited
+ * to a specified {@linkplain #setSourceRange(int,int) subrange}.</li>
+ * <li>Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.</li>
+ * <li>Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
+ * working copy owner} to use when resolving bindings.</li>
+ * <li>A hypothetical {@linkplain #setUnitName(String) compilation unit file name}
+ * and {@linkplain #setProject(IJavaProject) Java project}
+ * for locating a raw source string in the Java model (when
+ * resolving bindings)</li>
+ * <li>Which {@linkplain #setCompilerOptions(Map) compiler options}
+ * to use. This is especially important to use if the parsing/scanning of the source code requires a
+ * different version than the default of the workspace. For example, the workspace defaults are 1.4 and
+ * you want to create an AST for a source code that is using 1.5 constructs.</li>
+ * <li>Whether to parse just {@linkplain #setKind(int) an expression, statements,
+ * or body declarations} rather than an entire compilation unit.</li>
+ * <li>Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
+ * focused on the declaration containing a given source position.</li>
+ * </ul>
+ * </p>
+ *
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings("unchecked")
+public class ASTParser {
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a single expression.
+ */
+ public static final int K_EXPRESSION = 0x01;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a sequence of statements.
+ */
+ public static final int K_STATEMENTS = 0x02;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a sequence of class body declarations.
+ */
+ public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a compilation unit.
+ */
+ public static final int K_COMPILATION_UNIT = 0x08;
+
+ /**
+ * Creates a new object for creating a Java abstract syntax tree
+ * (AST) following the specified set of API rules.
+ *
+ * @param level the API level; one of the LEVEL constants
+ * declared on <code>AST</code>
+ * @return new ASTParser instance
+ */
+ public static ASTParser newParser(int level) {
+ return new ASTParser(level);
+ }
+
+ /**
+ * Level of AST API desired.
+ */
+ private final int apiLevel;
+
+ /**
+ * Kind of parse requested. Defaults to an entire compilation unit.
+ */
+ private int astKind;
+
+ /**
+ * Compiler options. Defaults to JavaCore.getOptions().
+ */
+ private Map compilerOptions;
+
+ /**
+ * Request for bindings. Defaults to <code>false</code>.
+ */
+ private boolean resolveBindings;
+
+ /**
+ * Request for a partial AST. Defaults to <code>false</code>.
+ */
+ private boolean partial = false;
+
+ /**
+ * Request for a statements recovery. Defaults to <code>false</code>.
+ */
+ private boolean statementsRecovery;
+
+ /**
+ * Request to ignore parsing the method bodies. Defaults to <code>false</code>.
+ */
+ private boolean ignoreMethodBodies;
+ /**
+ * Request for a bindings recovery. Defaults to <code>false</code>.
+ */
+ private boolean bindingsRecovery;
+
+ /**
+ * The focal point for a partial AST request.
+ * Only used when <code>partial</code> is <code>true</code>.
+ */
+ private int focalPointPosition;
+
+ /**
+ * Source string.
+ */
+ private char[] rawSource = null;
+
+ /**
+ * Java model class file or compilation unit supplying the source.
+ */
+ private ITypeRoot typeRoot = null;
+
+ /**
+ * Character-based offset into the source string where parsing is to
+ * begin. Defaults to 0.
+ */
+ private int sourceOffset = 0;
+
+ /**
+ * Character-based length limit, or -1 if unlimited.
+ * All characters in the source string between <code>offset</code>
+ * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1,
+ * which means the rest of the source string.
+ */
+ private int sourceLength = -1;
+
+ /**
+ * Working copy owner. Defaults to primary owner.
+ */
+ private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+
+ /**
+ * Java project used to resolve names, or <code>null</code> if none.
+ * Defaults to none.
+ */
+ private IJavaProject project = null;
+
+ /**
+ * Name of the compilation unit for resolving bindings, or
+ * <code>null</code> if none. Defaults to none.
+ */
+ private String unitName = null;
+
+ /**
+ * Creates a new AST parser for the given API level.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param level the API level; one of the LEVEL constants
+ * declared on <code>AST</code>
+ */
+ ASTParser(int level) {
+ if ((level != AST.JLS2_INTERNAL)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ this.apiLevel = level;
+ initializeDefaults();
+ }
+
+ /**
+ * Sets all the setting to their default values.
+ */
+ private void initializeDefaults() {
+ this.astKind = K_COMPILATION_UNIT;
+ this.rawSource = null;
+ this.typeRoot = null;
+ this.resolveBindings = false;
+ this.ignoreMethodBodies = false;
+ this.sourceLength = -1;
+ this.sourceOffset = 0;
+ this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+ this.unitName = null;
+ this.project = null;
+ this.partial = false;
+ Map options = JavaCore.getOptions();
+ options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+
+ /**
+ * Requests that the compiler should perform bindings recovery.
+ * When bindings recovery is enabled the compiler returns incomplete bindings.
+ * <p>
+ * Default to <code>false</code>.
+ * </p>
+ * <p>This should be set to true only if bindings are resolved. It has no effect if there is no binding
+ * resolution.</p>
+ *
+ * @param enabled <code>true</code> if incomplete bindings are expected,
+ * and <code>false</code> if only complete bindings are expected.
+ *
+ * @see IBinding#isRecovered()
+ * @since 3.3
+ */
+ public void setBindingsRecovery(boolean enabled) {
+ this.bindingsRecovery = enabled;
+ }
+ /**
+ * Sets the compiler options to be used when parsing.
+ * <p>
+ * Note that {@link #setSource(IClassFile)},
+ * {@link #setSource(ICompilationUnit)},
+ * and {@link #setProject(IJavaProject)} reset the compiler options
+ * based on the Java project. In other cases, compiler options default
+ * to {@link JavaCore#getOptions()}. In either case, and especially
+ * in the latter, the caller should carefully weight the consequences of
+ * allowing compiler options to be defaulted as opposed to being
+ * explicitly specified for the <code>ASTParser</code> instance.
+ * For instance, there is a compiler option called "Source Compatibility Mode"
+ * which determines which JDK level the source code is expected to meet.
+ * If you specify "1.4", then "assert" is treated as a keyword and disallowed
+ * as an identifier; if you specify "1.3", then "assert" is allowed as an
+ * identifier. So this particular setting has a major bearing on what is
+ * considered syntactically legal. By explicitly specifying the setting,
+ * the client control exactly how the parser works. On the other hand,
+ * allowing default settings means the parsing behaves like other JDT tools.
+ * </p>
+ *
+ * @param options the table of options (key type: <code>String</code>;
+ * value type: <code>String</code>), or <code>null</code>
+ * to set it back to the default
+ */
+ public void setCompilerOptions(Map options) {
+ if (options == null) {
+ options = JavaCore.getOptions();
+ } else {
+ // copy client's options so as to not do any side effect on them
+ options = new HashMap(options);
+ }
+ options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+
+ /**
+ * Requests that the compiler should provide binding information for
+ * the AST nodes it creates.
+ * <p>
+ * Default to <code>false</code> (no bindings).
+ * </p>
+ * <p>
+ * If <code>setResolveBindings(true)</code>, the various names
+ * and types appearing in the AST can be resolved to "bindings"
+ * by calling the <code>resolveBinding</code> methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * <code>resolveBinding</code> methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If <code>setResolveBindings(false)</code> (the default), the analysis
+ * does not go beyond parsing and building the tree, and all
+ * <code>resolveBinding</code> methods return <code>null</code> from the
+ * outset.
+ * </p>
+ * <p>
+ * When bindings are requested, instead of considering compilation units on disk only
+ * one can supply a <code>WorkingCopyOwner</code>. Working copies owned
+ * by this owner take precedence over the underlying compilation units when looking
+ * up names and drawing the connections.
+ * </p>
+ * <p>
+ * Binding information is obtained from the Java model.
+ * This means that the compilation unit must be located relative to the
+ * Java model. This happens automatically when the source code comes from
+ * either {@link #setSource(ICompilationUnit) setSource(ICompilationUnit)}
+ * or {@link #setSource(IClassFile) setSource(IClassFile)}.
+ * When source is supplied by {@link #setSource(char[]) setSource(char[])},
+ * the location must be extablished explicitly by calling
+ * {@link #setProject(IJavaProject)} and {@link #setUnitName(String)}.
+ * Note that the compiler options that affect doc comment checking may also
+ * affect whether any bindings are resolved for nodes within doc comments.
+ * </p>
+ *
+ * @param bindings <code>true</code> if bindings are wanted,
+ * and <code>false</code> if bindings are not of interest
+ */
+ public void setResolveBindings(boolean bindings) {
+ this.resolveBindings = bindings;
+ }
+
+ /**
+ * Requests an abridged abstract syntax tree.
+ * By default, complete ASTs are returned.
+ * <p>
+ * When <code>true</code> the resulting AST does not have nodes for
+ * the entire compilation unit. Rather, the AST is only fleshed out
+ * for the node that include the given source position. This kind of limited
+ * AST is sufficient for certain purposes but totally unsuitable for others.
+ * In places where it can be used, the limited AST offers the advantage of
+ * being smaller and faster to construct.
+ * </p>
+ * <p>
+ * The AST will include nodes for all of the compilation unit's
+ * package, import, and top-level type declarations. It will also always contain
+ * nodes for all the body declarations for those top-level types, as well
+ * as body declarations for any member types. However, some of the body
+ * declarations may be abridged. In particular, the statements ordinarily
+ * found in the body of a method declaration node will not be included
+ * (the block will be empty) unless the source position falls somewhere
+ * within the source range of that method declaration node. The same is true
+ * for initializer declarations; the statements ordinarily found in the body
+ * of initializer node will not be included unless the source position falls
+ * somewhere within the source range of that initializer declaration node.
+ * Field declarations are never abridged. Note that the AST for the body of
+ * that one unabridged method (or initializer) is 100% complete; it has all
+ * its statements, including any local or anonymous type declarations
+ * embedded within them. When the the given position is not located within
+ * the source range of any body declaration of a top-level type, the AST
+ * returned will be a skeleton that includes nodes for all and only the major
+ * declarations; this kind of AST is still quite useful because it contains
+ * all the constructs that introduce names visible to the world outside the
+ * compilation unit.
+ * </p>
+ *
+ * <p>This focal position is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param position a position into the corresponding body declaration
+ */
+ public void setFocalPosition(int position) {
+ this.partial = true;
+ this.focalPointPosition = position;
+ }
+
+ /**
+ * Sets the kind of constructs to be parsed from the source.
+ * Defaults to an entire compilation unit.
+ * <p>
+ * When the parse is successful the result returned includes the ASTs for the
+ * requested source:
+ * <ul>
+ * <li>{@link #K_COMPILATION_UNIT K_COMPILATION_UNIT}: The result node
+ * is a {@link CompilationUnit}.</li>
+ * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+ * is a {@link TypeDeclaration} whose
+ * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+ * are the new trees. Other aspects of the type declaration are unspecified.</li>
+ * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+ * {@link Block Block} whose {@link Block#statements() statements}
+ * are the new trees. Other aspects of the block are unspecified.</li>
+ * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+ * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
+ * </ul>
+ * The resulting AST node is rooted under (possibly contrived)
+ * {@link CompilationUnit CompilationUnit} node, to allow the
+ * client to retrieve the following pieces of information
+ * available there:
+ * <ul>
+ * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
+ * numbers start at 1 and only cover the subrange scanned
+ * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
+ * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
+ * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
+ * Character positions are relative to the start of
+ * <code>source</code>; line positions are for the subrange scanned.</li>
+ * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
+ * for the subrange scanned.</li>
+ * </ul>
+ * The contrived nodes do not have source positions. Other aspects of the
+ * {@link CompilationUnit CompilationUnit} node are unspecified, including
+ * the exact arrangement of intervening nodes.
+ * </p>
+ * <p>
+ * Lexical or syntax errors detected while parsing can result in
+ * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+ * In more severe failure cases where the parser is unable to
+ * recognize the input, this method returns
+ * a {@link CompilationUnit CompilationUnit} node with at least the
+ * compiler messages.
+ * </p>
+ * <p>Each node in the subtree (other than the contrived nodes)
+ * carries source range(s) information relating back
+ * to positions in the given source (the given source itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * </p>
+ * <p>
+ * Binding information is only computed when <code>kind</code> is
+ * <code>K_COMPILATION_UNIT</code>.
+ * </p>
+ *
+ * <p>This kind is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param kind the kind of construct to parse: one of
+ * {@link #K_COMPILATION_UNIT},
+ * {@link #K_CLASS_BODY_DECLARATIONS},
+ * {@link #K_EXPRESSION},
+ * {@link #K_STATEMENTS}
+ */
+ public void setKind(int kind) {
+ if ((kind != K_COMPILATION_UNIT)
+ && (kind != K_CLASS_BODY_DECLARATIONS)
+ && (kind != K_EXPRESSION)
+ && (kind != K_STATEMENTS)) {
+ throw new IllegalArgumentException();
+ }
+ this.astKind = kind;
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ *
+ * <p>This source is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param source the source string to be parsed,
+ * or <code>null</code> if none
+ */
+ public void setSource(char[] source) {
+ this.rawSource = source;
+ // clear the type root
+ this.typeRoot = null;
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * This method automatically sets the project (and compiler
+ * options) based on the given compilation unit, in a manner
+ * equivalent to <code>setProject(source.getJavaProject())</code>
+ *
+ * <p>This source is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param source the Java model compilation unit whose source code
+ * is to be parsed, or <code>null</code> if none
+ */
+ public void setSource(ICompilationUnit source) {
+ setSource((ITypeRoot)source);
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * <p>This method automatically sets the project (and compiler
+ * options) based on the given compilation unit, in a manner
+ * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
+ * <p>If the given class file has no source attachment, the creation of the
+ * ast will fail with an IllegalStateException.</p>
+ *
+ * <p>This source is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param source the Java model class file whose corresponding source code
+ * is to be parsed, or <code>null</code> if none
+ */
+ public void setSource(IClassFile source) {
+ setSource((ITypeRoot)source);
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * <p>This method automatically sets the project (and compiler
+ * options) based on the given compilation unit of class file, in a manner
+ * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
+ * <p>If the source is a class file without source attachment, the creation of the
+ * ast will fail with an IllegalStateException.</p>
+ *
+ * <p>This source is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param source the Java model compilation unit or class file whose corresponding source code
+ * is to be parsed, or <code>null</code> if none
+ * @since 3.3
+ */
+ public void setSource(ITypeRoot source) {
+ this.typeRoot = source;
+ // clear the raw source
+ this.rawSource = null;
+ if (source != null) {
+ this.project = source.getJavaProject();
+ Map options = this.project.getOptions(true);
+ options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+ }
+
+ /**
+ * Sets the subrange of the source code to be parsed.
+ * By default, the entire source string will be parsed
+ * (<code>offset</code> 0 and <code>length</code> -1).
+ *
+ * <p>This range is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param offset the index of the first character to parse
+ * @param length the number of characters to parse, or -1 if
+ * the remainder of the source string is to be parsed
+ */
+ public void setSourceRange(int offset, int length) {
+ if (offset < 0 || length < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.sourceOffset = offset;
+ this.sourceLength = length;
+ }
+
+ /**
+ * Requests that the compiler should perform statements recovery.
+ * When statements recovery is enabled the compiler tries to create statement nodes
+ * from code containing syntax errors
+ * <p>
+ * Default to <code>false</code>.
+ * </p>
+ *
+ * @param enabled <code>true</code> if statements containing syntax errors are wanted,
+ * and <code>false</code> if these statements aren't wanted.
+ *
+ * @since 3.2
+ */
+ public void setStatementsRecovery(boolean enabled) {
+ this.statementsRecovery = enabled;
+ }
+
+ /**
+ * Requests an abstract syntax tree without method bodies.
+ *
+ * <p>When ignore method bodies is enabled, all method bodies are discarded.
+ * This has no impact on the binding resolution.</p>
+ *
+ * <p>This setting is not used when the kind used in {@link #setKind(int)} is either
+ * {@link #K_EXPRESSION} or {@link #K_STATEMENTS}.</p>
+ * @since 3.5.2
+ */
+ public void setIgnoreMethodBodies(boolean enabled) {
+ this.ignoreMethodBodies = enabled;
+ }
+
+ /**
+ * Sets the working copy owner using when resolving bindings, where
+ * <code>null</code> means the primary owner. Defaults to the primary owner.
+ *
+ * @param owner the owner of working copies that take precedence over underlying
+ * compilation units, or <code>null</code> if the primary owner should be used
+ */
+ public void setWorkingCopyOwner(WorkingCopyOwner owner) {
+ if (owner == null) {
+ this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+ } else {
+ this.workingCopyOwner = owner;
+ }
+ }
+
+ /**
+ * Sets the name of the compilation unit that would hypothetically contains
+ * the source string. This is used in conjunction with {@link #setSource(char[])}
+ * and {@link #setProject(IJavaProject) } to locate the compilation unit relative to a Java project.
+ * Defaults to none (<code>null</code>).
+ * <p>
+ * The name of the compilation unit must be supplied for resolving bindings.
+ * This name should be suffixed by a dot ('.') followed by one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
+ * and match the name of the main (public) class or interface declared in the source.</p>
+ *
+ * <p>This name must represent the full path of the unit inside the given project. For example, if the source
+ * declares a public class named "Foo" in a project "P" where the source folder is the project itself, the name
+ * of the compilation unit must be "/P/Foo.java".
+ * If the source declares a public class name "Bar" in a package "p1.p2" in a project "P" in a source folder "src",
+ * the name of the compilation unit must be "/P/src/p1/p2/Bar.java".</p>
+ *
+ * <p>This unit name is not used when the AST is built using
+ * {@link #createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor)}.</p>
+ *
+ * @param unitName the name of the compilation unit that would contain the source
+ * string, or <code>null</code> if none
+ */
+ public void setUnitName(String unitName) {
+ this.unitName = unitName;
+ }
+
+ /**
+ * Sets the Java project used when resolving bindings.
+ * This method automatically sets the compiler
+ * options based on the given project:
+ * <pre>
+ * setCompilerOptions(project.getOptions(true));
+ * </pre>
+ * See {@link #setCompilerOptions(Map)} for a discussion of
+ * the pros and cons of using these options vs specifying
+ * compiler options explicitly.
+ * This setting is used in conjunction with <code>setSource(char[])</code>.
+ * For the purposes of resolving bindings, types declared in the
+ * source string will hide types by the same name available
+ * through the classpath of the given project.
+ * Defaults to none (<code>null</code>).
+ *
+ * @param project the Java project used to resolve names, or
+ * <code>null</code> if none
+ */
+ public void setProject(IJavaProject project) {
+ this.project = project;
+ if (project != null) {
+ Map options = project.getOptions(true);
+ options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+ }
+
+ /**
+ * Creates an abstract syntax tree.
+ * <p>
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ * </p>
+ *
+ * @param monitor the progress monitor used to report progress and request cancelation,
+ * or <code>null</code> if none
+ * @return an AST node whose type depends on the kind of parse
+ * requested, with a fallback to a <code>CompilationUnit</code>
+ * in the case of severe parsing errors
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ */
+ public ASTNode createAST(IProgressMonitor monitor) {
+ ASTNode result = null;
+ if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
+ try {
+ if (this.rawSource == null && this.typeRoot == null) {
+ throw new IllegalStateException("source not specified"); //$NON-NLS-1$
+ }
+ result = internalCreateAST(monitor);
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ if (monitor != null) monitor.done();
+ }
+ return result;
+ }
+
+ /**
+ * Creates ASTs for a batch of compilation units.
+ * When bindings are being resolved, processing a
+ * batch of compilation units is more efficient because much
+ * of the work involved in resolving bindings can be shared.
+ * <p>
+ * When bindings are being resolved, all compilation units must
+ * come from the same Java project, which must be set beforehand
+ * with <code>setProject</code>.
+ * The compilation units are processed one at a time in no
+ * specified order. For each of the compilation units in turn,
+ * <ul>
+ * <li><code>ASTParser.createAST</code> is called to parse it
+ * and create a corresponding AST. The calls to
+ * <code>ASTParser.createAST</code> all employ the same settings.</li>
+ * <li><code>ASTRequestor.acceptAST</code> is called passing
+ * the compilation unit and the corresponding AST to
+ * <code>requestor</code>.
+ * </li>
+ * </ul>
+ * Note only ASTs from the given compilation units are reported
+ * to the requestor. If additional compilation units are required to
+ * resolve the original ones, the corresponding ASTs are <b>not</b>
+ * reported to the requestor.
+ * </p>
+ * <p>
+ * Note also the following parser parameters are used, regardless of what
+ * may have been specified:
+ * <ul>
+ * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
+ * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
+ * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The <code>bindingKeys</code> parameter specifies bindings keys
+ * ({@link IBinding#getKey()}) that are to be looked up. These keys may
+ * be for elements either inside or outside the set of compilation
+ * units being processed. When bindings are being resolved,
+ * the keys and corresponding bindings (or <code>null</code> if none) are
+ * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
+ * for elements outside the set of compilation units being processed are looked up
+ * after all <code>ASTRequestor.acceptAST</code> callbacks have been made.
+ * Binding keys for elements inside the set of compilation units being processed
+ * are looked up and reported right after the corresponding
+ * <code>ASTRequestor.acceptAST</code> callback has been made.
+ * No <code>ASTRequestor.acceptBinding</code> callbacks are made unless
+ * bindings are being resolved.
+ * </p>
+ * <p>
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ * </p>
+ *
+ * @param compilationUnits the compilation units to create ASTs for
+ * @param bindingKeys the binding keys to create bindings for
+ * @param requestor the AST requestor that collects abstract syntax trees and bindings
+ * @param monitor the progress monitor used to report progress and request cancellation,
+ * or <code>null</code> if none
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ * @since 3.1
+ */
+ public void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
+ try {
+ int flags = 0;
+ if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
+ if (this.resolveBindings) {
+ if (this.project == null)
+ throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+ if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+ CompilationUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
+ } else {
+ CompilationUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, flags, monitor);
+ }
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ }
+ }
+
+ /**
+ * Creates bindings for a batch of Java elements. These elements are either
+ * enclosed in {@link ICompilationUnit}s or in {@link IClassFile}s.
+ * <p>
+ * All enclosing compilation units and class files must
+ * come from the same Java project, which must be set beforehand
+ * with <code>setProject</code>.
+ * </p>
+ * <p>
+ * All elements must exist. If one doesn't exist, an <code>IllegalStateException</code>
+ * is thrown.
+ * </p>
+ * <p>
+ * The returned array has the same size as the given elements array. At a given position
+ * it contains the binding of the corresponding Java element, or <code>null</code>
+ * if no binding could be created.
+ * </p>
+ * <p>
+ * Note also the following parser parameters are used, regardless of what
+ * may have been specified:
+ * <ul>
+ * <li>The {@linkplain #setResolveBindings(boolean) binding resolution flag} is <code>true</code></li>
+ * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
+ * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
+ * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
+ * </ul>
+ * </p>
+ * <p>
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ * </p>
+ *
+ * @param elements the Java elements to create bindings for
+ * @return the bindings for the given Java elements, possibly containing <code>null</code>s
+ * if some bindings could not be created
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ * @since 3.1
+ */
+ public IBinding[] createBindings(IJavaElement[] elements, IProgressMonitor monitor) {
+ try {
+ if (this.project == null)
+ throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+ int flags = 0;
+ if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+ if (this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
+ return CompilationUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ }
+ }
+
+ private ASTNode internalCreateAST(IProgressMonitor monitor) {
+ boolean needToResolveBindings = this.resolveBindings;
+ switch(this.astKind) {
+ case K_CLASS_BODY_DECLARATIONS :
+ case K_EXPRESSION :
+ case K_STATEMENTS :
+ if (this.rawSource == null) {
+ if (this.typeRoot != null) {
+ // get the source from the type root
+ if (this.typeRoot instanceof ICompilationUnit) {
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
+ this.rawSource = sourceUnit.getContents();
+ } else if (this.typeRoot instanceof IClassFile) {
+ try {
+ String sourceString = this.typeRoot.getSource();
+ if (sourceString != null) {
+ this.rawSource = sourceString.toCharArray();
+ }
+ } catch(JavaModelException e) {
+ // an error occured accessing the java element
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(stringWriter);
+ e.printStackTrace(writer);
+ } finally {
+ if (writer != null) writer.close();
+ }
+ throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
+ }
+ }
+ }
+ }
+ if (this.rawSource != null) {
+ if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
+ throw new IllegalStateException();
+ }
+ return internalCreateASTForKind();
+ }
+ break;
+ case K_COMPILATION_UNIT :
+ CompilationUnitDeclaration compilationUnitDeclaration = null;
+ try {
+ NodeSearcher searcher = null;
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
+ WorkingCopyOwner wcOwner = this.workingCopyOwner;
+ if (this.typeRoot instanceof ICompilationUnit) {
+ /*
+ * this.compilationUnitSource is an instance of org.eclipse.jdt.internal.core.CompilationUnit that implements
+ * both org.eclipse.jdt.core.ICompilationUnit and org.eclipse.jdt.internal.compiler.env.ICompilationUnit
+ */
+ sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
+ /*
+ * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
+ * (if it is a working copy, the source can change between the parse and the AST convertion)
+ * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
+ */
+ sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
+ wcOwner = ((ICompilationUnit) this.typeRoot).getOwner();
+ } else if (this.typeRoot instanceof IClassFile) {
+ try {
+ String sourceString = this.typeRoot.getSource();
+ if (sourceString == null) {
+ throw new IllegalStateException();
+ }
+ PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent();
+ BinaryType type = (BinaryType) this.typeRoot.findPrimaryType();
+ IBinaryType binaryType = (IBinaryType) type.getElementInfo();
+ // file name is used to recreate the Java element, so it has to be the toplevel .class file name
+ char[] fileName = binaryType.getFileName();
+ int firstDollar = CharOperation.indexOf('$', fileName);
+ if (firstDollar != -1) {
+ char[] suffix = SuffixConstants.SUFFIX_class;
+ int suffixLength = suffix.length;
+ char[] newFileName = new char[firstDollar + suffixLength];
+ System.arraycopy(fileName, 0, newFileName, 0, firstDollar);
+ System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength);
+ fileName = newFileName;
+ }
+ sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project);
+ } catch(JavaModelException e) {
+ // an error occured accessing the java element
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(stringWriter);
+ e.printStackTrace(writer);
+ } finally {
+ if (writer != null) writer.close();
+ }
+ throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
+ }
+ } else if (this.rawSource != null) {
+ needToResolveBindings = this.resolveBindings && this.unitName != null && this.project != null && this.compilerOptions != null;
+ sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
+ } else {
+ throw new IllegalStateException();
+ }
+ if (this.partial) {
+ searcher = new NodeSearcher(this.focalPointPosition);
+ }
+ int flags = 0;
+ if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (searcher == null && this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
+ if (needToResolveBindings) {
+ if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+ try {
+ // parse and resolve
+ compilationUnitDeclaration =
+ CompilationUnitResolver.resolve(
+ sourceUnit,
+ this.project,
+ searcher,
+ this.compilerOptions,
+ this.workingCopyOwner,
+ flags,
+ monitor);
+ } catch (JavaModelException e) {
+ flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+ compilationUnitDeclaration = CompilationUnitResolver.parse(
+ sourceUnit,
+ searcher,
+ this.compilerOptions,
+ flags);
+ needToResolveBindings = false;
+//{ObjectTeams: one more error to catch:
+ } catch (InternalCompilerError ice) {
+ flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+ compilationUnitDeclaration = CompilationUnitResolver.parse(
+ sourceUnit,
+ searcher,
+ this.compilerOptions,
+ flags);
+ needToResolveBindings = false;
+// SH}
+ }
+ } else {
+ compilationUnitDeclaration = CompilationUnitResolver.parse(
+ sourceUnit,
+ searcher,
+ this.compilerOptions,
+ flags);
+ needToResolveBindings = false;
+ }
+ CompilationUnit result = CompilationUnitResolver.convert(
+ compilationUnitDeclaration,
+ sourceUnit.getContents(),
+ this.apiLevel,
+ this.compilerOptions,
+ needToResolveBindings,
+ wcOwner,
+ needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
+ flags,
+ monitor);
+ result.setTypeRoot(this.typeRoot);
+ return result;
+ } finally {
+ if (compilationUnitDeclaration != null && this.resolveBindings) {
+ compilationUnitDeclaration.cleanUp();
+ }
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * Parses the given source between the bounds specified by the given offset (inclusive)
+ * and the given length and creates and returns a corresponding abstract syntax tree.
+ * <p>
+ * When the parse is successful the result returned includes the ASTs for the
+ * requested source:
+ * <ul>
+ * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+ * is a {@link TypeDeclaration TypeDeclaration} whose
+ * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+ * are the new trees. Other aspects of the type declaration are unspecified.</li>
+ * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+ * {@link Block Block} whose {@link Block#statements() statements}
+ * are the new trees. Other aspects of the block are unspecified.</li>
+ * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+ * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
+ * </ul>
+ * The resulting AST node is rooted under an contrived
+ * {@link CompilationUnit CompilationUnit} node, to allow the
+ * client to retrieve the following pieces of information
+ * available there:
+ * <ul>
+ * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
+ * numbers start at 1 and only cover the subrange scanned
+ * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
+ * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
+ * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
+ * Character positions are relative to the start of
+ * <code>source</code>; line positions are for the subrange scanned.</li>
+ * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
+ * for the subrange scanned.</li>
+ * </ul>
+ * The contrived nodes do not have source positions. Other aspects of the
+ * {@link CompilationUnit CompilationUnit} node are unspecified, including
+ * the exact arrangment of intervening nodes.
+ * </p>
+ * <p>
+ * Lexical or syntax errors detected while parsing can result in
+ * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+ * In more severe failure cases where the parser is unable to
+ * recognize the input, this method returns
+ * a {@link CompilationUnit CompilationUnit} node with at least the
+ * compiler messages.
+ * </p>
+ * <p>Each node in the subtree (other than the contrived nodes)
+ * carries source range(s) information relating back
+ * to positions in the given source (the given source itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are <b>not</b>
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are <b>not</b> included. There are a handful of exceptions
+ * (including the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * </p>
+ * <p>
+ * This method does not compute binding information; all <code>resolveBinding</code>
+ * methods applied to nodes of the resulting AST return <code>null</code>.
+ * </p>
+ *
+ * @return an AST node whose type depends on the kind of parse
+ * requested, with a fallback to a <code>CompilationUnit</code>
+ * in the case of severe parsing errors
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ */
+ private ASTNode internalCreateASTForKind() {
+ final ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
+ converter.compilationUnitSource = this.rawSource;
+ converter.compilationUnitSourceLength = this.rawSource.length;
+ converter.scanner.setSource(this.rawSource);
+
+ AST ast = AST.newAST(this.apiLevel);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ ast.setBindingResolver(new BindingResolver());
+ if (this.statementsRecovery) {
+ ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
+ }
+ converter.setAST(ast);
+ CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil(this.ignoreMethodBodies);
+ CompilationUnit compilationUnit = ast.newCompilationUnit();
+ if (this.sourceLength == -1) {
+ this.sourceLength = this.rawSource.length;
+ }
+ switch(this.astKind) {
+ case K_STATEMENTS :
+ ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
+ RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
+ if(data != null) {
+ Scanner scanner = converter.scanner;
+ converter.scanner = new RecoveryScanner(scanner, data.removeUnused());
+ converter.docParser.scanner = converter.scanner;
+ converter.scanner.setSource(scanner.source);
+
+ compilationUnit.setStatementsRecoveryData(data);
+ }
+ RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ int[][] comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ Block block = ast.newBlock();
+ block.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+ org.eclipse.jdt.internal.compiler.ast.Statement[] statements = constructorDeclaration.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+ converter.checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+ } else {
+ Statement statement = converter.convert(statements[i]);
+ if (statement != null) {
+ block.statements().add(statement);
+ }
+ }
+ }
+ }
+ rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return block;
+ case K_EXPRESSION :
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
+ recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ if (expression != null) {
+ Expression expression2 = converter.convert(expression);
+ rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return expression2;
+ } else {
+ CategorizedProblem[] problems = recordedParsingInformation.problems;
+ if (problems != null) {
+ compilationUnit.setProblems(problems);
+ }
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+ case K_CLASS_BODY_DECLARATIONS :
+ final org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
+ recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ if (nodes != null) {
+ // source has no syntax error or the statement recovery is enabled
+ TypeDeclaration typeDeclaration = converter.convert(nodes);
+ typeDeclaration.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+ rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return typeDeclaration;
+ } else {
+ // source has syntax error and the statement recovery is disabled
+ CategorizedProblem[] problems = recordedParsingInformation.problems;
+ if (problems != null) {
+ compilationUnit.setProblems(problems);
+ }
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+ private void propagateErrors(ASTNode astNode, CategorizedProblem[] problems, RecoveryScannerData data) {
+ astNode.accept(new ASTSyntaxErrorPropagator(problems));
+ if (data != null) {
+ astNode.accept(new ASTRecoveryPropagator(problems, data));
+ }
+ }
+
+ private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
+ final int problemsCount = recordedParsingInformation.problemsCount;
+ switch(node.getNodeType()) {
+ case ASTNode.BLOCK :
+ {
+ Block block = (Block) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(block, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+ Initializer initializer = ast.newInitializer();
+ initializer.setBody(block);
+ typeDeclaration.bodyDeclarations().add(initializer);
+ compilationUnit.types().add(typeDeclaration);
+ }
+ break;
+ case ASTNode.TYPE_DECLARATION :
+ {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(typeDeclaration, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ compilationUnit.types().add(typeDeclaration);
+ }
+ break;
+ default :
+ if (node instanceof Expression) {
+ Expression expression = (Expression) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(expression, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
+ Block block = ast.newBlock();
+ block.statements().add(expressionStatement);
+ Initializer initializer = ast.newInitializer();
+ initializer.setBody(block);
+ TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+ typeDeclaration.bodyDeclarations().add(initializer);
+ compilationUnit.types().add(typeDeclaration);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
new file mode 100644
index 000000000..641356c05
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
@@ -0,0 +1,449 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToIntArray;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTRecoveryPropagator extends DefaultASTVisitor {
+ private static final int NOTHING = -1;
+ HashtableOfObjectToIntArray endingTokens = new HashtableOfObjectToIntArray();
+ {
+ this.endingTokens.put(AnonymousClassDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(ArrayAccess.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(ArrayCreation.class, new int[]{NOTHING, TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(ArrayInitializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(ArrayType.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(AssertStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(Block.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(BooleanLiteral.class, new int[]{TerminalTokens.TokenNamefalse, TerminalTokens.TokenNametrue});
+ this.endingTokens.put(BreakStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(CharacterLiteral.class, new int[]{TerminalTokens.TokenNameCharacterLiteral});
+ this.endingTokens.put(ClassInstanceCreation.class, new int[]{TerminalTokens.TokenNameRBRACE, TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(ConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ContinueStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(DoStatement.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(EmptyStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ExpressionStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(FieldDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ImportDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(MethodDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(MethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull});
+ this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral});
+ this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ParenthesizedExpression.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(PostfixExpression.class, new int[]{TerminalTokens.TokenNamePLUS_PLUS, TerminalTokens.TokenNameMINUS_MINUS});
+ this.endingTokens.put(PrimitiveType.class, new int[]{TerminalTokens.TokenNamebyte, TerminalTokens.TokenNameshort, TerminalTokens.TokenNamechar, TerminalTokens.TokenNameint, TerminalTokens.TokenNamelong, TerminalTokens.TokenNamefloat, TerminalTokens.TokenNameboolean, TerminalTokens.TokenNamedouble, TerminalTokens.TokenNamevoid});
+ this.endingTokens.put(ReturnStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(SimpleName.class, new int[]{TerminalTokens.TokenNameIdentifier});
+ this.endingTokens.put(SingleVariableDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(StringLiteral.class, new int[]{TerminalTokens.TokenNameStringLiteral});
+ this.endingTokens.put(SuperConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(SuperMethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(SwitchCase.class, new int[]{TerminalTokens.TokenNameCOLON});
+ this.endingTokens.put(SwitchStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(SynchronizedStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(ThisExpression.class, new int[]{TerminalTokens.TokenNamethis});
+ this.endingTokens.put(ThrowStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(TypeDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(TypeLiteral.class, new int[]{TerminalTokens.TokenNameclass});
+ this.endingTokens.put(VariableDeclarationStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ }
+
+ private CategorizedProblem[] problems;
+ private boolean[] usedOrIrrelevantProblems;
+
+ private RecoveryScannerData data;
+ private int blockDepth = 0;
+ private int lastEnd;
+
+ private int[] insertedTokensKind;
+ private int[] insertedTokensPosition;
+ private boolean[] insertedTokensFlagged;
+
+ private boolean[] removedTokensFlagged;
+ private boolean[] replacedTokensFlagged;
+
+ private Vector stack = new Vector();
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ ASTRecoveryPropagator(CategorizedProblem[] problems, RecoveryScannerData data) {
+ // visit Javadoc.tags() as well
+ this.problems = problems;
+ this.usedOrIrrelevantProblems = new boolean[problems.length];
+
+ this.data = data;
+
+ if(this.data != null) {
+
+ int length = 0;
+ for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+ length += data.insertedTokens[i].length;
+ }
+ this.insertedTokensKind = new int[length];
+ this.insertedTokensPosition = new int[length];
+ this.insertedTokensFlagged = new boolean[length];
+ int tokenCount = 0;
+ for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+ for (int j = 0; j < data.insertedTokens[i].length; j++) {
+ this.insertedTokensKind[tokenCount] = data.insertedTokens[i][j];
+ this.insertedTokensPosition[tokenCount] = data.insertedTokensPosition[i];
+ tokenCount++;
+ }
+ }
+
+ if(data.removedTokensPtr != -1) {
+ this.removedTokensFlagged = new boolean[data.removedTokensPtr + 1];
+ }
+ if(data.replacedTokensPtr != -1) {
+ this.replacedTokensFlagged = new boolean[data.replacedTokensPtr + 1];
+ }
+ }
+ }
+
+ public void endVisit(Block node) {
+ this.blockDepth--;
+ if(this.blockDepth <= 0) {
+ flagNodeWithInsertedTokens();
+ }
+ super.endVisit(node);
+ }
+
+
+
+ public boolean visit(Block node) {
+ boolean visitChildren = super.visit(node);
+ this.blockDepth++;
+ return visitChildren;
+ }
+
+ protected boolean visitNode(ASTNode node) {
+ if(this.blockDepth > 0) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ // continue to visit the node only if it contains tokens modifications
+
+ if(this.insertedTokensFlagged != null) {
+ for (int i = 0; i < this.insertedTokensFlagged.length; i++) {
+ if(this.insertedTokensPosition[i] >= start &&
+ this.insertedTokensPosition[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ if(this.removedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+ if(this.data.removedTokensStart[i] >= start &&
+ this.data.removedTokensEnd[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ if(this.replacedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+ if(this.data.replacedTokensStart[i] >= start &&
+ this.data.replacedTokensEnd[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ return true;
+ }
+
+ protected void endVisitNode(ASTNode node) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ // is inside diet part of the ast
+ if(this.blockDepth < 1) {
+ switch (node.getNodeType()) {
+ case ASTNode.ANNOTATION_TYPE_DECLARATION:
+ case ASTNode.COMPILATION_UNIT:
+ case ASTNode.ENUM_DECLARATION:
+ case ASTNode.FIELD_DECLARATION:
+ case ASTNode.IMPORT_DECLARATION:
+ case ASTNode.INITIALIZER:
+ case ASTNode.METHOD_DECLARATION:
+ case ASTNode.PACKAGE_DECLARATION:
+ case ASTNode.TYPE_DECLARATION:
+ case ASTNode.MARKER_ANNOTATION:
+ case ASTNode.NORMAL_ANNOTATION:
+ case ASTNode.SINGLE_MEMBER_ANNOTATION:
+ case ASTNode.BLOCK:
+ if(markIncludedProblems(start, end)) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ }
+ break;
+ }
+ } else {
+ markIncludedProblems(start, end);
+
+ if(this.insertedTokensFlagged != null) {
+ if(this.lastEnd != end) {
+ flagNodeWithInsertedTokens();
+ }
+ this.stack.add(node);
+ }
+
+ if(this.removedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+ if(!this.removedTokensFlagged[i] &&
+ this.data.removedTokensStart[i] >= start &&
+ this.data.removedTokensEnd[i] <= end) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.removedTokensFlagged[i] = true;
+ }
+ }
+ }
+
+ if(this.replacedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+ if(!this.replacedTokensFlagged[i] &&
+ this.data.replacedTokensStart[i] >= start &&
+ this.data.replacedTokensEnd[i] <= end) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.replacedTokensFlagged[i] = true;
+ }
+ }
+ }
+ }
+ this.lastEnd = end;
+ }
+
+ private void flagNodeWithInsertedTokens() {
+ if(this.insertedTokensKind != null && this.insertedTokensKind.length > 0) {
+ int s = this.stack.size();
+ for (int i = s - 1; i > -1; i--) {
+ flagNodesWithInsertedTokensAtEnd((ASTNode)this.stack.get(i));
+ }
+ for (int i = 0; i < s; i++) {
+ flagNodesWithInsertedTokensInside((ASTNode)this.stack.get(i));
+ }
+ this.stack = new Vector();
+ }
+ }
+
+ private boolean flagNodesWithInsertedTokensAtEnd(ASTNode node) {
+ int[] expectedEndingToken = this.endingTokens.get(node.getClass());
+ if (expectedEndingToken != null) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ boolean flagParent = false;
+ done : for (int i = this.insertedTokensKind.length - 1; i > -1 ; i--) {
+ if(!this.insertedTokensFlagged[i] &&
+ this.insertedTokensPosition[i] == end){
+ this.insertedTokensFlagged[i] = true;
+ for (int j = 0; j < expectedEndingToken.length; j++) {
+ if(expectedEndingToken[j] == this.insertedTokensKind[i]) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ break done;
+ }
+ }
+ flagParent = true;
+ }
+ }
+
+ if(flagParent) {
+ ASTNode parent = node.getParent();
+ while (parent != null) {
+ parent.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ if((parent.getStartPosition() + parent.getLength() - 1) != end) {
+ parent = null;
+ } else {
+ parent = parent.getParent();
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean flagNodesWithInsertedTokensInside(ASTNode node) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+ for (int i = 0; i < this.insertedTokensKind.length; i++) {
+ if(!this.insertedTokensFlagged[i] &&
+ start <= this.insertedTokensPosition[i] &&
+ this.insertedTokensPosition[i] < end){
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.insertedTokensFlagged[i] = true;
+ }
+ }
+ return true;
+ }
+
+ private boolean markIncludedProblems(int start, int end) {
+ boolean foundProblems = false;
+ next: for (int i = 0, max = this.problems.length; i < max; i++) {
+ CategorizedProblem problem = this.problems[i];
+
+ if(this.usedOrIrrelevantProblems[i]) continue next;
+
+ switch(problem.getID()) {
+ case IProblem.ParsingErrorOnKeywordNoSuggestion :
+ case IProblem.ParsingErrorOnKeyword :
+ case IProblem.ParsingError :
+ case IProblem.ParsingErrorNoSuggestion :
+ case IProblem.ParsingErrorInsertTokenBefore :
+ case IProblem.ParsingErrorInsertTokenAfter :
+ case IProblem.ParsingErrorDeleteToken :
+ case IProblem.ParsingErrorDeleteTokens :
+ case IProblem.ParsingErrorMergeTokens :
+ case IProblem.ParsingErrorInvalidToken :
+ case IProblem.ParsingErrorMisplacedConstruct :
+ case IProblem.ParsingErrorReplaceTokens :
+ case IProblem.ParsingErrorNoSuggestionForTokens :
+ case IProblem.ParsingErrorUnexpectedEOF :
+ case IProblem.ParsingErrorInsertToComplete :
+ case IProblem.ParsingErrorInsertToCompleteScope :
+ case IProblem.ParsingErrorInsertToCompletePhrase :
+ case IProblem.EndOfSource :
+ case IProblem.InvalidHexa :
+ case IProblem.InvalidOctal :
+ case IProblem.InvalidCharacterConstant :
+ case IProblem.InvalidEscape :
+ case IProblem.InvalidInput :
+ case IProblem.InvalidUnicodeEscape :
+ case IProblem.InvalidFloat :
+ case IProblem.NullSourceString :
+ case IProblem.UnterminatedString :
+ case IProblem.UnterminatedComment :
+ case IProblem.InvalidDigit :
+ break;
+ default:
+ this.usedOrIrrelevantProblems[i] = true;
+ continue next;
+
+ }
+
+ int problemStart = problem.getSourceStart();
+ int problemEnd = problem.getSourceEnd();
+ if ((start <= problemStart) && (problemStart <= end) ||
+ (start <= problemEnd) && (problemEnd <= end)) {
+ this.usedOrIrrelevantProblems[i] = true;
+ foundProblems = true;
+ }
+ }
+ return foundProblems;
+ }
+
+ public void endVisit(ExpressionStatement node) {
+ endVisitNode(node);
+ if ((node.getFlags() & ASTNode.RECOVERED) == 0) return;
+ Expression expression = node.getExpression();
+ if (expression.getNodeType() == ASTNode.ASSIGNMENT) {
+ Assignment assignment = (Assignment) expression;
+ Expression rightHandSide = assignment.getRightHandSide();
+ if (rightHandSide.getNodeType() == ASTNode.SIMPLE_NAME) {
+ SimpleName simpleName = (SimpleName) rightHandSide;
+ if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+ Expression expression2 = assignment.getLeftHandSide();
+ // unparent the expression to add it in the expression stateemnt
+ expression2.setParent(null, null);
+ expression2.setFlags(expression2.getFlags() | ASTNode.RECOVERED);
+ node.setExpression(expression2);
+ }
+ }
+ }
+ }
+
+ public void endVisit(ForStatement node) {
+ endVisitNode(node);
+ List initializers = node.initializers();
+ if (initializers.size() == 1) {
+ Expression expression = (Expression) initializers.get(0);
+ if (expression.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
+ List fragments = variableDeclarationExpression.fragments();
+ for (int i = 0, max = fragments.size(); i <max; i++) {
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
+ SimpleName simpleName = fragment.getName();
+ if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+ fragments.remove(fragment);
+ variableDeclarationExpression.setFlags(variableDeclarationExpression.getFlags() | ASTNode.RECOVERED);
+ }
+ }
+ }
+ }
+ }
+
+ public void endVisit(VariableDeclarationStatement node) {
+ endVisitNode(node);
+ List fragments = node.fragments();
+ for (int i = 0, max = fragments.size(); i <max; i++) {
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
+ Expression expression = fragment.getInitializer();
+ if (expression == null) continue;
+ if ((expression.getFlags() & ASTNode.RECOVERED) == 0) continue;
+ if (expression.getNodeType() == ASTNode.SIMPLE_NAME) {
+ SimpleName simpleName = (SimpleName) expression;
+ if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+ fragment.setInitializer(null);
+ fragment.setFlags(fragment.getFlags() | ASTNode.RECOVERED);
+ }
+ }
+ }
+ }
+
+ public void endVisit(NormalAnnotation node) {
+ endVisitNode(node);
+ // is inside diet part of the ast
+ if(this.blockDepth < 1) {
+ List values = node.values();
+ int size = values.size();
+ if (size > 0) {
+ MemberValuePair lastMemberValuePair = (MemberValuePair)values.get(size - 1);
+
+ int annotationEnd = node.getStartPosition() + node.getLength();
+ int lastMemberValuePairEnd = lastMemberValuePair.getStartPosition() + lastMemberValuePair.getLength();
+ if (annotationEnd == lastMemberValuePairEnd) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ }
+ }
+ }
+ }
+
+ public void endVisit(SingleMemberAnnotation node) {
+ endVisitNode(node);
+ // is inside diet part of the ast
+ if(this.blockDepth < 1) {
+ Expression value = node.getValue();
+ int annotationEnd = node.getStartPosition() + node.getLength();
+ int valueEnd = value.getStartPosition() + value.getLength();
+ if (annotationEnd == valueEnd) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java
new file mode 100644
index 000000000..e493b1586
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRequestor.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+
+/**
+ * An AST requestor handles ASTs for compilation units passed to
+ * <code>ASTParser.createASTs</code>.
+ * <p>
+ * <code>ASTRequestor.acceptAST</code> is called for each of the
+ * compilation units passed to <code>ASTParser.createASTs</code>.
+ * After all the compilation units have been processed,
+ * <code>ASTRequestor.acceptBindings</code> is called for each
+ * of the binding keys passed to <code>ASTParser.createASTs</code>.
+ * </p>
+ * <p>
+ * This class is intended to be subclassed by clients.
+ * AST requestors are serially reusable, but neither reentrant nor
+ * thread-safe.
+ * </p>
+ *
+ * @see ASTParser#createASTs(ICompilationUnit[], String[], ASTRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.1
+ */
+public abstract class ASTRequestor {
+
+ /**
+ * The compilation unit resolver used to resolve bindings, or
+ * <code>null</code> if none. Note that this field is non-null
+ * only within the dynamic scope of a call to
+ * <code>ASTParser.createASTs</code>.
+ */
+ CompilationUnitResolver compilationUnitResolver = null;
+
+ /**
+ * Creates a new instance.
+ */
+ protected ASTRequestor() {
+ // do nothing
+ }
+
+ /**
+ * Accepts an AST corresponding to the compilation unit.
+ * That is, <code>ast</code> is an AST for <code>source</code>.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Clients should override to process the resulting AST.
+ * </p>
+ *
+ * @param source the compilation unit the ast is coming from
+ * @param ast the requested abtract syntax tree
+ */
+ public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
+ // do nothing
+ }
+
+ /**
+ * Accepts a binding corresponding to the binding key.
+ * That is, <code>binding</code> is the binding for
+ * <code>bindingKey</code>; <code>binding</code> is <code>null</code>
+ * if the key cannot be resolved.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Clients should override to process the resulting binding.
+ * </p>
+ *
+ * @param bindingKey the key of the requested binding
+ * @param binding the requested binding, or <code>null</code> if none
+ */
+ public void acceptBinding(String bindingKey, IBinding binding) {
+ // do nothing
+ }
+
+ /**
+ * Resolves bindings for the given binding keys.
+ * The given binding keys must have been obtained earlier
+ * using {@link IBinding#getKey()}.
+ * <p>
+ * If a binding key cannot be resolved, <code>null</code> is put in the resulting array.
+ * Bindings can only be resolved in the dynamic scope of a <code>ASTParser.createASTs</code>,
+ * and only if <code>ASTParser.resolveBindings(true)</code> was specified.
+ * </p>
+ * <p>
+ * Caveat: During an <code>acceptAST</code> callback, there are implementation
+ * limitations concerning the look up of binding keys representing local elements.
+ * In some cases, the binding is unavailable, and <code>null</code> will be returned.
+ * This is only an issue during an <code>acceptAST</code> callback, and only
+ * when the binding key represents a local element (e.g., local variable,
+ * local class, method declared in anonymous class). There is no such limitation
+ * outside of <code>acceptAST</code> callbacks, or for top-level types and their
+ * members even within <code>acceptAST</code> callbacks.
+ * </p>
+ *
+ * @param bindingKeys the binding keys to look up
+ * @return a list of bindings paralleling the <code>bindingKeys</code> parameter,
+ * with <code>null</code> entries for keys that could not be resolved
+ */
+ public final IBinding[] createBindings(String[] bindingKeys) {
+ int length = bindingKeys.length;
+ IBinding[] result = new IBinding[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = null;
+ if (this.compilationUnitResolver != null) {
+ result[i] = this.compilationUnitResolver.createBinding(bindingKeys[i]);
+ }
+ }
+ return result;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
new file mode 100644
index 000000000..437d9c197
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.IProblem;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTSyntaxErrorPropagator extends ASTVisitor {
+
+ private CategorizedProblem[] problems;
+
+ ASTSyntaxErrorPropagator(CategorizedProblem[] problems) {
+ // visit Javadoc.tags() as well
+ super(true);
+ this.problems = problems;
+ }
+
+ private boolean checkAndTagAsMalformed(ASTNode node) {
+ boolean tagWithErrors = false;
+ search: for (int i = 0, max = this.problems.length; i < max; i++) {
+ CategorizedProblem problem = this.problems[i];
+ switch(problem.getID()) {
+ case IProblem.ParsingErrorOnKeywordNoSuggestion :
+ case IProblem.ParsingErrorOnKeyword :
+ case IProblem.ParsingError :
+ case IProblem.ParsingErrorNoSuggestion :
+ case IProblem.ParsingErrorInsertTokenBefore :
+ case IProblem.ParsingErrorInsertTokenAfter :
+ case IProblem.ParsingErrorDeleteToken :
+ case IProblem.ParsingErrorDeleteTokens :
+ case IProblem.ParsingErrorMergeTokens :
+ case IProblem.ParsingErrorInvalidToken :
+ case IProblem.ParsingErrorMisplacedConstruct :
+ case IProblem.ParsingErrorReplaceTokens :
+ case IProblem.ParsingErrorNoSuggestionForTokens :
+ case IProblem.ParsingErrorUnexpectedEOF :
+ case IProblem.ParsingErrorInsertToComplete :
+ case IProblem.ParsingErrorInsertToCompleteScope :
+ case IProblem.ParsingErrorInsertToCompletePhrase :
+ case IProblem.EndOfSource :
+ case IProblem.InvalidHexa :
+ case IProblem.InvalidOctal :
+ case IProblem.InvalidCharacterConstant :
+ case IProblem.InvalidEscape :
+ case IProblem.InvalidInput :
+ case IProblem.InvalidUnicodeEscape :
+ case IProblem.InvalidFloat :
+ case IProblem.NullSourceString :
+ case IProblem.UnterminatedString :
+ case IProblem.UnterminatedComment :
+ case IProblem.InvalidDigit :
+ break;
+ default:
+ continue search;
+ }
+ int position = problem.getSourceStart();
+ int start = node.getStartPosition();
+ int end = start + node.getLength();
+ if ((start <= position) && (position <= end)) {
+ node.setFlags(node.getFlags() | ASTNode.MALFORMED);
+ // clear the bits on parent
+ ASTNode currentNode = node.getParent();
+ while (currentNode != null) {
+ currentNode.setFlags(currentNode.getFlags() & ~ASTNode.MALFORMED);
+ currentNode = currentNode.getParent();
+ }
+ tagWithErrors = true;
+ }
+ }
+ return tagWithErrors;
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(FieldDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(MethodDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(PackageDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(ImportDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(CompilationUnit node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(AnnotationTypeDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(EnumDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(TypeDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(Initializer node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
new file mode 100644
index 000000000..39ed372fb
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
@@ -0,0 +1,3052 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTVisitor.java 22741 2009-10-13 22:23:05Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * A visitor for abstract syntax trees.
+ * <p>
+ * For each different concrete AST node type <i>T</i> there are
+ * a pair of methods:
+ * <ul>
+ * <li><code>public boolean visit(<i>T</i> node)</code> - Visits
+ * the given node to perform some arbitrary operation. If <code>true</code>
+ * is returned, the given node's child nodes will be visited next; however,
+ * if <code>false</code> is returned, the given node's child nodes will
+ * not be visited. The default implementation provided by this class does
+ * nothing and returns <code>true</code> (with the exception of
+ * {@link #visit(Javadoc) ASTVisitor.visit(Javadoc)}).
+ * Subclasses may reimplement this method as needed.</li>
+ * <li><code>public void endVisit(<i>T</i> node)</code> - Visits
+ * the given node to perform some arbitrary operation. When used in the
+ * conventional way, this method is called after all of the given node's
+ * children have been visited (or immediately, if <code>visit</code> returned
+ * <code>false</code>). The default implementation provided by this class does
+ * nothing. Subclasses may reimplement this method as needed.</li>
+ * </ul>
+ * </p>
+ * In addition, there are a pair of methods for visiting AST nodes in the
+ * abstract, regardless of node type:
+ * <ul>
+ * <li><code>public void preVisit(ASTNode node)</code> - Visits
+ * the given node to perform some arbitrary operation.
+ * This method is invoked prior to the appropriate type-specific
+ * <code>visit</code> method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.</li>
+ * <li><code>public void postVisit(ASTNode node)</code> - Visits
+ * the given node to perform some arbitrary operation.
+ * This method is invoked after the appropriate type-specific
+ * <code>endVisit</code> method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.</li>
+ * </ul>
+ * <p>
+ * For nodes with list-valued properties, the child nodes within the list
+ * are visited in order. For nodes with multiple properties, the child nodes
+ * are visited in the order that most closely corresponds to the lexical
+ * reading order of the source program. For instance, for a type declaration
+ * node, the child ordering is: name, superclass, superinterfaces, and
+ * body declarations.
+ * </p>
+ * <p>
+ * While it is possible to modify the tree in the visitor, care is required to
+ * ensure that the consequences are as expected and desirable.
+ * During the course of an ordinary visit starting at a given node, every node
+ * in the subtree is visited exactly twice, first with <code>visit</code> and
+ * then with <code>endVisit</code>. During a traversal of a stationary tree,
+ * each node is either behind (after <code>endVisit</code>), ahead (before
+ * <code>visit</code>), or in progress (between <code>visit</code> and
+ * the matching <code>endVisit</code>). Changes to the "behind" region of the
+ * tree are of no consequence to the visit in progress. Changes to the "ahead"
+ * region will be taken in stride. Changes to the "in progress" portion are
+ * the more interesting cases. With a node, the various properties are arranged
+ * in a linear list, with a cursor that separates the properties that have
+ * been visited from the ones that are still to be visited (the cursor
+ * is between the elements, rather than on an element). The cursor moves from
+ * the head to the tail of this list, advancing to the next position just
+ * <i>before</i> <code>visit</code> if called for that child. After the child
+ * subtree has been completely visited, the visit moves on the child
+ * immediately after the cursor. Removing a child while it is being visited
+ * does not alter the course of the visit. But any children added at positions
+ * after the cursor are considered in the "ahead" portion and will be visited.
+ * </p>
+ * <p>
+ * Cases to watch out for:
+ * <ul>
+ * <li>Moving a child node further down the list. This could result in the
+ * child subtree being visited multiple times; these visits are sequential.</li>
+ * <li>Moving a child node up into an ancestor. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited
+ * a second time; again, these visits are sequential.</li>
+ * <li>Moving a node down into a child. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited
+ * a second time; in this case, the visits will be nested. In some cases,
+ * this can lead to a stack overflow or out of memory condition.</li>
+ * </ul>
+ * <p>Note that {@link LineComment} and {@link BlockComment} nodes are
+ * not normally visited in an AST because they are not considered
+ * part of main structure of the AST. Use
+ * {@link CompilationUnit#getCommentList()} to find these additional
+ * comments nodes.
+ * </p>
+ *
+ * @see org.eclipse.jdt.core.dom.ASTNode#accept(ASTVisitor)
+ */
+public abstract class ASTVisitor {
+
+ /**
+ * Indicates whether doc tags should be visited by default.
+ * @since 3.0
+ */
+ private boolean visitDocTags;
+
+ /**
+ * Creates a new AST visitor instance.
+ * <p>
+ * For backwards compatibility, the visitor does not visit tag
+ * elements below doc comments by default. Use
+ * {@link #ASTVisitor(boolean) ASTVisitor(true)}
+ * for an visitor that includes doc comments by default.
+ * </p>
+ */
+ public ASTVisitor() {
+ this(false);
+ }
+
+ /**
+ * Creates a new AST visitor instance.
+ *
+ * @param visitDocTags <code>true</code> if doc comment tags are
+ * to be visited by default, and <code>false</code> otherwise
+ * @see Javadoc#tags()
+ * @see #visit(Javadoc)
+ * @since 3.0
+ */
+ public ASTVisitor(boolean visitDocTags) {
+ this.visitDocTags = visitDocTags;
+ }
+
+ /**
+ * Visits the given AST node prior to the type-specific visit
+ * (before <code>visit</code>).
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ *
+ * @see #preVisit2(ASTNode)
+ */
+ public void preVisit(ASTNode node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Visits the given AST node prior to the type-specific visit (before <code>visit</code>).
+ * <p>
+ * The default implementation calls {@link #preVisit(ASTNode)} and then
+ * returns true. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if <code>visit(node)</code> should be called,
+ * and <code>false</code> otherwise.
+ * @see #preVisit(ASTNode)
+ * @since 3.5
+ */
+ public boolean preVisit2(ASTNode node) {
+ preVisit(node);
+ return true;
+ }
+
+ /**
+ * Visits the given AST node following the type-specific visit
+ * (after <code>endVisit</code>).
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void postVisit(ASTNode node) {
+ // default implementation: do nothing
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(AnnotationTypeDeclaration node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayCreation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayInitializer node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(AssertStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Assignment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Block node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(BlockComment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BooleanLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BreakStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CastExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CatchClause node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CharacterLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CompilationUnit node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ConditionalExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ConstructorInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ContinueStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(DoStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(EmptyStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(EnhancedForStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(EnumConstantDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(EnumDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ExpressionStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FieldAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FieldDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ForStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(IfStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ImportDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(InfixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(InstanceofExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Initializer node) {
+ return true;
+ }
+
+ /**
+ * Visits the given AST node.
+ * <p>
+ * Unlike other node types, the boolean returned by the default
+ * implementation is controlled by a constructor-supplied
+ * parameter {@link #ASTVisitor(boolean) ASTVisitor(boolean)}
+ * which is <code>false</code> by default.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @see #ASTVisitor()
+ * @see #ASTVisitor(boolean)
+ */
+ public boolean visit(Javadoc node) {
+ // visit tag elements inside doc comments only if requested
+ return this.visitDocTags;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(LabeledStatement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(LineComment node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(MarkerAnnotation node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(MemberRef node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(MemberValuePair node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(MethodRef node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(MethodRefParameter node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(MethodDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(MethodInvocation node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(Modifier node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(NormalAnnotation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(NullLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(NumberLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PackageDeclaration node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(ParameterizedType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PostfixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PrefixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PrimitiveType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(QualifiedName node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(QualifiedType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ReturnStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SimpleName node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SimpleType node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(SingleMemberAnnotation node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(StringLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperFieldAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SwitchCase node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SwitchStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SynchronizedStatement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(TagElement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(TextElement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ThisExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ThrowStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TryStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(TypeParameter node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(WhileStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.1
+ */
+ public boolean visit(WildcardType node) {
+ return true;
+ }
+
+//{ObjectTeams: visit methods for OT-specific types
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(MethodSpec node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FieldAccessSpec node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CallinMappingDeclaration node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CalloutMappingDeclaration node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and returns true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 1.3.1
+ */
+ public boolean visit(MethodBindingOperator node) {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(LiftingType node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeAnchor node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(ParameterMapping node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ * @since 3.0
+ */
+ public boolean visit(RoleTypeDeclaration node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(WithinStatement node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TSuperMessageSend node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TSuperConstructorInvocation node)
+ {
+ return visitNode(node);
+ }
+
+
+
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BaseCallMessageSend node)
+ {
+ return visitNode(node);
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BaseConstructorInvocation node)
+ {
+ return visitNode(node);
+ }
+
+ public boolean visit(PrecedenceDeclaration node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(GuardPredicateDeclaration node) {
+ return visitNode(node);
+ }
+//gbr}
+
+//{ObjectTeams: adapt subclass org.eclipse.jdt.internal.corext.dom.GenericVisitor:
+ // introduce method to which others will be mapped
+ protected boolean visitNode(ASTNode node) {
+ return true;
+ }
+
+// SH}
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(AnnotationTypeDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(AnnotationTypeMemberDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(AnonymousClassDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayCreation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayInitializer node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(AssertStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Assignment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Block node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(BlockComment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BooleanLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BreakStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CastExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CatchClause node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CharacterLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ClassInstanceCreation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CompilationUnit node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ConditionalExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ConstructorInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ContinueStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(DoStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(EmptyStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(EnhancedForStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(EnumConstantDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(EnumDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ExpressionStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FieldAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FieldDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ForStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(IfStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ImportDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(InfixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(InstanceofExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Initializer node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Javadoc node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(LabeledStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(LineComment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(MarkerAnnotation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(MemberRef node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(MemberValuePair node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(MethodRef node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(MethodRefParameter node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(MethodDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(MethodInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(Modifier node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(NormalAnnotation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(NullLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(NumberLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PackageDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(ParameterizedType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ParenthesizedExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PostfixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PrefixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PrimitiveType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(QualifiedName node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(QualifiedType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ReturnStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SimpleName node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SimpleType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(SingleMemberAnnotation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SingleVariableDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(StringLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperConstructorInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperFieldAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperMethodInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SwitchCase node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SwitchStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SynchronizedStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(TagElement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.0
+ */
+ public void endVisit(TextElement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ThisExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ThrowStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TryStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeDeclarationStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(TypeParameter node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationFragment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(WhileStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 3.1
+ */
+ public void endVisit(WildcardType node) {
+ // default implementation: do nothing
+ }
+
+//{ObjectTeams: endVisit methods for OT-specific types
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(MethodSpec node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FieldAccessSpec node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CallinMappingDeclaration node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CalloutMappingDeclaration node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @since 1.3.1
+ */
+ public void endVisit(MethodBindingOperator node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ParameterMapping node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(RoleTypeDeclaration node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(LiftingType node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeAnchor node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(WithinStatement node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TSuperMessageSend node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TSuperConstructorInvocation node)
+ {
+ // default implementation: do nothing
+ }
+
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BaseConstructorInvocation node)
+ {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BaseCallMessageSend node)
+ {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(PrecedenceDeclaration declaration)
+ {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(GuardPredicateDeclaration predicate) {
+ // default implementation: do nothing
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractMethodMappingDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractMethodMappingDeclaration.java
new file mode 100644
index 000000000..bc1c86e3e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractMethodMappingDeclaration.java
@@ -0,0 +1,205 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: AbstractMethodMappingDeclaration.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+
+/**
+ * NEW for OTDT.
+ *
+ * Super class for callin/callout method mappings
+ * @author brcan
+ *
+ * $Id: AbstractMethodMappingDeclaration.java 23416 2010-02-03 19:59:31Z stephan $
+ */
+public abstract class AbstractMethodMappingDeclaration extends BodyDeclaration
+{
+
+ protected MethodMappingElement roleMappingElement = null;
+
+ // includes info about binding kind and binding modifiers
+ protected MethodBindingOperator bindingOperator = null;
+
+ /**
+ * Creates a new AST node for an abstract method mapping declaration node owned by
+ * the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AbstractMethodMappingDeclaration(AST ast)
+ {
+ super(ast);
+ }
+
+ /**
+ * The list of parameter mappings (element type: <code>ParameterMapping</code>).
+ * Defaults to an empty list.
+ */
+ ASTNode.NodeList _parameterMappings =
+ new ASTNode.NodeList(internalParameterMappingsProperty());
+
+ /** Return the structural property descriptor for the roleMappingElement property of this node. */
+ abstract ChildPropertyDescriptor internalGetRoleElementProperty();
+
+ /** Return the structural property descriptor for the bindingOperator property of this node. */
+ abstract ChildPropertyDescriptor internalGetBindingOperatorProperty();
+
+ /**
+ * Returns structural property descriptor for the "parameterMappings" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildListPropertyDescriptor internalParameterMappingsProperty();
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "parameterMappings" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildListPropertyDescriptor internalParameterMappingPropertyFactory(Class nodeClass)
+ {
+ return new ChildListPropertyDescriptor(nodeClass, "parameterMappings", ParameterMapping.class, CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == internalGetRoleElementProperty())
+ {
+ if (get) {
+ return getRoleMappingElement();
+ } else {
+ setRoleMappingElement((MethodSpec) child);
+ return null;
+ }
+ }
+ if (property == internalGetBindingOperatorProperty())
+ {
+ if (get) {
+ return bindingOperator();
+ } else {
+ setBindingOperator((MethodBindingOperator)child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+
+ /**
+ * Returns the method spec left of the callout/in arrow.
+ * @return the left method spec, i.e. the declaring role method
+ */
+ public MethodMappingElement getRoleMappingElement()
+ {
+ if (this.roleMappingElement == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.roleMappingElement == null) {
+ preLazyInit();
+ this.roleMappingElement = new MethodSpec(this.ast);
+ postLazyInit(this.roleMappingElement, internalGetRoleElementProperty());
+ }
+ }
+ }
+ return this.roleMappingElement;
+ }
+
+ /**
+ * Sets the left method spec (role method spec) declared in this callout
+ * mapping declaration to the given method spec.
+ *
+ * @param roleMappingElement
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setRoleMappingElement(MethodMappingElement roleMappingElement)
+ {
+ if (roleMappingElement == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = roleMappingElement;
+ preReplaceChild(oldChild, roleMappingElement, internalGetRoleElementProperty());
+ this.roleMappingElement = roleMappingElement;
+ postReplaceChild(oldChild, roleMappingElement, internalGetRoleElementProperty());
+ }
+
+
+ public void setBindingOperator(MethodBindingOperator bindingOp) {
+ ChildPropertyDescriptor propertyDescriptor = internalGetBindingOperatorProperty();
+ MethodBindingOperator oldOperator = this.bindingOperator;
+ preReplaceChild(oldOperator, bindingOp, propertyDescriptor);
+ this.bindingOperator = bindingOp;
+ postReplaceChild(oldOperator, bindingOp, propertyDescriptor);
+ }
+
+ public MethodBindingOperator bindingOperator() {
+ if (this.bindingOperator == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this.bindingOperator == null)
+ {
+ preLazyInit();
+ this.bindingOperator = new MethodBindingOperator(this.ast);
+ postLazyInit(this.bindingOperator, internalGetBindingOperatorProperty());
+ }
+ }
+ }
+ return this.bindingOperator;
+ }
+
+ /**
+ * Returns the live ordered list of parameter mappings for this
+ * callin mapping declaration.
+ *
+ * @return the live list of parameter mappings
+ * (element type: <code>ParameterMapping</code>)
+ */
+ public List getParameterMappings()
+ {
+ return _parameterMappings;
+ }
+
+ public boolean hasParameterMapping()
+ {
+ return (! _parameterMappings.isEmpty());
+ }
+
+ public boolean hasSignature() {
+ return getRoleMappingElement().hasSignature();
+ }
+
+ public IMethodMappingBinding resolveBinding()
+ {
+ return this.ast.getBindingResolver().resolveMethodMapping(this);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java
new file mode 100644
index 000000000..031f49882
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTypeDeclaration.java
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+
+/**
+ * Abstract subclass for type declaration, enum declaration,
+ * and annotation type declaration AST node types.
+ * <pre>
+ * AbstractTypeDeclaration:
+ * TypeDeclaration
+ * EnumDeclaration
+ * AnnotationTypeDeclaration
+ * </pre>
+ *
+ * @since 3.0
+ */
+public abstract class AbstractTypeDeclaration extends BodyDeclaration {
+
+ /**
+ * The type name; lazily initialized; defaults to a unspecified,
+ * legal Java class identifier.
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ SimpleName typeName = null;
+
+ /**
+ * The body declarations (element type: <code>BodyDeclaration</code>).
+ * Defaults to an empty list.
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ ASTNode.NodeList bodyDeclarations;
+
+ /**
+ * Returns structural property descriptor for the "bodyDeclarations" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildListPropertyDescriptor internalBodyDeclarationsProperty();
+
+ /**
+ * Returns structural property descriptor for the "bodyDeclarations" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildListPropertyDescriptor getBodyDeclarationsProperty() {
+ return internalBodyDeclarationsProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalNameProperty();
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildPropertyDescriptor getNameProperty() {
+ return internalNameProperty();
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "bodyDeclaration" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildListPropertyDescriptor internalBodyDeclarationPropertyFactory(Class nodeClass) {
+ return new ChildListPropertyDescriptor(nodeClass, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "name" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new AST node for an abstract type declaration owned by the given
+ * AST.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AbstractTypeDeclaration(AST ast) {
+ super(ast);
+ this.bodyDeclarations = new ASTNode.NodeList(internalBodyDeclarationsProperty());
+ }
+
+ /**
+ * Returns the name of the type declared in this type declaration.
+ *
+ * @return the type name node
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public SimpleName getName() {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, internalNameProperty());
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of the type declared in this type declaration to the
+ * given name.
+ *
+ * @param typeName the new type name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public void setName(SimpleName typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ChildPropertyDescriptor p = internalNameProperty();
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, p);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, p);
+ }
+
+ /**
+ * Returns the live ordered list of body declarations of this type
+ * declaration.
+ *
+ * @return the live list of body declarations
+ * (element type: <code>BodyDeclaration</code>)
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public List bodyDeclarations() {
+ return this.bodyDeclarations;
+ }
+
+ /**
+ * Returns whether this type declaration is a package member (that is,
+ * a top-level type).
+ * <p>
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a compilation unit node.
+ * </p>
+ *
+ * @return <code>true</code> if this type declaration is a child of
+ * a compilation unit node, and <code>false</code> otherwise
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public boolean isPackageMemberTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof CompilationUnit);
+ }
+
+ /**
+ * Returns whether this type declaration is a type member.
+ * <p>
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a type declaration node or an anonymous
+ * class declaration.
+ * </p>
+ *
+ * @return <code>true</code> if this type declaration is a child of
+ * a type declaration node or an anonymous class declaration node,
+ * and <code>false</code> otherwise
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public boolean isMemberTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof AbstractTypeDeclaration)
+ || (parent instanceof AnonymousClassDeclaration);
+ }
+
+ /**
+ * Returns whether this type declaration is a local type.
+ * <p>
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a type declaration statement node.
+ * </p>
+ *
+ * @return <code>true</code> if this type declaration is a child of
+ * a type declaration statement node, and <code>false</code> otherwise
+ * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+ */
+ public boolean isLocalTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof TypeDeclarationStatement);
+ }
+
+//{ObjectTeams: additional queries:
+ /**
+ * Returns whether this type declaration is a team type.
+ *
+ * @return <code>true</code> if this type declaration is a team declaration,
+ * and <code>false</code> otherwise
+ * @since OTDT_1.2.3
+ */
+ public boolean isTeam() {
+ return false;
+ }
+
+ /**
+ * Returns whether this type declaration is a role type.
+ *
+ * @return <code>true</code> if this type declaration is a role declaration,
+ * and <code>false</code> otherwise
+ * @since OTDT_1.2.3
+ */
+ public boolean isRole() {
+ return false;
+ }
+// SH}
+
+ /**
+ * Resolves and returns the binding for the type declared in this type
+ * declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ * @since 3.1 Declared in 3.0 on the individual subclasses.
+ */
+ public final ITypeBinding resolveBinding() {
+ return internalResolveBinding();
+ }
+
+ /**
+ * Resolves and returns the binding for the type declared in this type
+ * declaration. This method must be implemented by subclasses.
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ abstract ITypeBinding internalResolveBinding();
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java
new file mode 100644
index 000000000..6d22f007a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Annotation.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent annotations.
+ * <p>
+ * <pre>
+ * Annotation:
+ * NormalAnnotation
+ * MarkerAnnotation
+ * SingleMemberAnnotation
+ * </pre>
+ * </p>
+ * @since 3.1
+ */
+public abstract class Annotation extends Expression implements IExtendedModifier {
+
+ /**
+ * Returns structural property descriptor for the "typeName" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalTypeNameProperty();
+
+ /**
+ * Returns structural property descriptor for the "typeName" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ public final ChildPropertyDescriptor getTypeNameProperty() {
+ return internalTypeNameProperty();
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "typeName" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalTypeNamePropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "typeName", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * The annotation type name; lazily initialized; defaults to an unspecified,
+ * legal Java identifier.
+ */
+ Name typeName = null;
+
+ /**
+ * Creates a new AST node for an annotation node owned by the
+ * given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Annotation(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * @see IExtendedModifier#isModifier()
+ */
+ public boolean isModifier() {
+ return false;
+ }
+
+ /**
+ * @see IExtendedModifier#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return true;
+ }
+
+ /**
+ * Returns the annotation type name of this annotation.
+ *
+ * @return the annotation type name
+ */
+ public Name getTypeName() {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, internalTypeNameProperty());
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the annotation type name of this annotation.
+ *
+ * @param typeName the annotation type name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setTypeName(Name typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ChildPropertyDescriptor p = internalTypeNameProperty();
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, p);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, p);
+ }
+
+ /**
+ * Returns whether this is a normal annotation
+ * ({@link NormalAnnotation}).
+ *
+ * @return <code>true</code> if this is a normal annotation,
+ * and <code>false</code> otherwise
+ */
+ public boolean isNormalAnnotation() {
+ return (this instanceof NormalAnnotation);
+ }
+
+ /**
+ * Returns whether this is a marker annotation
+ * ({@link MarkerAnnotation}).
+ *
+ * @return <code>true</code> if this is a marker annotation,
+ * and <code>false</code> otherwise
+ */
+ public boolean isMarkerAnnotation() {
+ return (this instanceof MarkerAnnotation);
+ }
+
+ /**
+ * Returns whether this is a single member annotation.
+ * ({@link SingleMemberAnnotation}).
+ *
+ * @return <code>true</code> if this is a single member annotation,
+ * and <code>false</code> otherwise
+ */
+ public boolean isSingleMemberAnnotation() {
+ return (this instanceof SingleMemberAnnotation);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /**
+ * Resolves and returns the resolved annotation for this annotation.
+ * <p>
+ * Note that bindings (which includes resolved annotations) are generally unavailable unless
+ * requested when the AST is being built.
+ * </p>
+ *
+ * @return the resolved annotation, or <code>null</code> if the annotation cannot be resolved
+ * @since 3.2
+ */
+ public IAnnotationBinding resolveAnnotationBinding() {
+ return this.ast.getBindingResolver().resolveAnnotation(this);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
new file mode 100644
index 000000000..106cf7b41
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ * IBM Corporation - implemented methods from IBinding
+ * IBM Corporation - renamed from ResolvedAnnotation to AnnotationBinding
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IAnnotatable;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+/**
+ * Internal class
+ */
+class AnnotationBinding implements IAnnotationBinding {
+ static final AnnotationBinding[] NoAnnotations = new AnnotationBinding[0];
+ private org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding binding;
+ private BindingResolver bindingResolver;
+ private String key;
+
+ AnnotationBinding(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding annotation, BindingResolver resolver) {
+ if (annotation == null)
+ throw new IllegalStateException();
+ this.binding = annotation;
+ this.bindingResolver = resolver;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ return NoAnnotations;
+ }
+
+ public ITypeBinding getAnnotationType() {
+ ITypeBinding typeBinding = this.bindingResolver.getTypeBinding(this.binding.getAnnotationType());
+ if (typeBinding == null)
+ return null;
+ return typeBinding;
+ }
+
+ public IMemberValuePairBinding[] getDeclaredMemberValuePairs() {
+ ReferenceBinding typeBinding = this.binding.getAnnotationType();
+ if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) {
+ return MemberValuePairBinding.NoPair;
+ }
+ ElementValuePair[] internalPairs = this.binding.getElementValuePairs();
+ int length = internalPairs.length;
+ IMemberValuePairBinding[] pairs = length == 0 ? MemberValuePairBinding.NoPair : new MemberValuePairBinding[length];
+ int counter = 0;
+ for (int i = 0; i < length; i++) {
+ ElementValuePair valuePair = internalPairs[i];
+ if (valuePair.binding == null) continue;
+ pairs[counter++] = this.bindingResolver.getMemberValuePairBinding(valuePair);
+ }
+ if (counter == 0) return MemberValuePairBinding.NoPair;
+ if (counter != length) {
+ // resize
+ System.arraycopy(pairs, 0, (pairs = new MemberValuePairBinding[counter]), 0, counter);
+ }
+ return pairs;
+ }
+
+ public IMemberValuePairBinding[] getAllMemberValuePairs() {
+ IMemberValuePairBinding[] pairs = getDeclaredMemberValuePairs();
+ ReferenceBinding typeBinding = this.binding.getAnnotationType();
+ if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) return pairs;
+ MethodBinding[] methods = typeBinding.availableMethods(); // resilience
+ int methodLength = methods == null ? 0 : methods.length;
+ if (methodLength == 0) return pairs;
+
+ int declaredLength = pairs.length;
+ if (declaredLength == methodLength)
+ return pairs;
+
+ HashtableOfObject table = new HashtableOfObject(declaredLength);
+ for (int i = 0; i < declaredLength; i++) {
+ char[] internalName = ((MemberValuePairBinding) pairs[i]).internalName();
+ if (internalName == null) continue;
+ table.put(internalName, pairs[i]);
+ }
+
+ // handle case of more methods than declared members
+ IMemberValuePairBinding[] allPairs = new IMemberValuePairBinding[methodLength];
+ for (int i = 0; i < methodLength; i++) {
+ Object pair = table.get(methods[i].selector);
+ allPairs[i] = pair == null ? new DefaultValuePairBinding(methods[i], this.bindingResolver) : (IMemberValuePairBinding) pair;
+ }
+ return allPairs;
+ }
+
+ public IJavaElement getJavaElement() {
+ if (!(this.bindingResolver instanceof DefaultBindingResolver)) return null;
+ ASTNode node = (ASTNode) ((DefaultBindingResolver) this.bindingResolver).bindingsToAstNodes.get(this);
+ if (!(node instanceof Annotation)) return null;
+ ASTNode parent = node.getParent();
+ IJavaElement parentElement = null;
+ switch (parent.getNodeType()) {
+ case ASTNode.PACKAGE_DECLARATION:
+ IJavaElement cu = ((CompilationUnit) parent.getParent()).getJavaElement();
+ if (cu instanceof ICompilationUnit) {
+ String pkgName = ((PackageDeclaration) parent).getName().getFullyQualifiedName();
+ parentElement = ((ICompilationUnit) cu).getPackageDeclaration(pkgName);
+ }
+ break;
+ case ASTNode.ENUM_DECLARATION:
+ case ASTNode.TYPE_DECLARATION:
+ case ASTNode.ANNOTATION_TYPE_DECLARATION:
+ parentElement = ((AbstractTypeDeclaration) parent).resolveBinding().getJavaElement();
+ break;
+ case ASTNode.FIELD_DECLARATION:
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) parent).fragments().get(0);
+ parentElement = fragment.resolveBinding().getJavaElement();
+ break;
+ case ASTNode.METHOD_DECLARATION:
+ parentElement = ((MethodDeclaration) parent).resolveBinding().getJavaElement();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) parent).fragments().get(0);
+ parentElement = fragment.resolveBinding().getJavaElement();
+ break;
+ default:
+ return null;
+ }
+ if (! (parentElement instanceof IAnnotatable)) return null;
+ if ((parentElement instanceof IMember) && ((IMember) parentElement).isBinary()) {
+ return ((IAnnotatable) parentElement).getAnnotation(getAnnotationType().getQualifiedName());
+ }
+ return ((IAnnotatable) parentElement).getAnnotation(getName());
+ }
+
+ public String getKey() {
+ if (this.key == null) {
+ String recipientKey = getRecipientKey();
+ this.key = new String(this.binding.computeUniqueKey(recipientKey.toCharArray()));
+ }
+ return this.key;
+ }
+
+ private String getRecipientKey() {
+ if (!(this.bindingResolver instanceof DefaultBindingResolver)) return ""; //$NON-NLS-1$
+ DefaultBindingResolver resolver = (DefaultBindingResolver) this.bindingResolver;
+ ASTNode node = (ASTNode) resolver.bindingsToAstNodes.get(this);
+ if (node == null) {
+ // Can happen if annotation bindings have been resolved before having parsed the declaration
+ return ""; //$NON-NLS-1$
+ }
+ ASTNode recipient = node.getParent();
+ switch (recipient.getNodeType()) {
+ case ASTNode.PACKAGE_DECLARATION:
+ String pkgName = ((PackageDeclaration) recipient).getName().getFullyQualifiedName();
+ return pkgName.replace('.', '/');
+ case ASTNode.TYPE_DECLARATION:
+ return ((TypeDeclaration) recipient).resolveBinding().getKey();
+ case ASTNode.FIELD_DECLARATION:
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) recipient).fragments().get(0);
+ return fragment.resolveBinding().getKey();
+ case ASTNode.METHOD_DECLARATION:
+ return ((MethodDeclaration) recipient).resolveBinding().getKey();
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) recipient).fragments().get(0);
+ return fragment.resolveBinding().getKey();
+ default:
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ public int getKind() {
+ return IBinding.ANNOTATION;
+ }
+
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ public String getName() {
+ ITypeBinding annotationType = getAnnotationType();
+ if (annotationType == null) {
+ return new String(this.binding.getAnnotationType().sourceName());
+ } else {
+ return annotationType.getName();
+ }
+ }
+
+ public boolean isDeprecated() {
+ ReferenceBinding typeBinding = this.binding.getAnnotationType();
+ if (typeBinding == null) return false;
+ return typeBinding.isDeprecated();
+ }
+
+ public boolean isEqualTo(IBinding otherBinding) {
+ if (this == otherBinding)
+ return true;
+ if (otherBinding.getKind() != IBinding.ANNOTATION)
+ return false;
+ IAnnotationBinding other = (IAnnotationBinding) otherBinding;
+ if (!getAnnotationType().isEqualTo(other.getAnnotationType()))
+ return false;
+ IMemberValuePairBinding[] memberValuePairs = getDeclaredMemberValuePairs();
+ IMemberValuePairBinding[] otherMemberValuePairs = other.getDeclaredMemberValuePairs();
+ if (memberValuePairs.length != otherMemberValuePairs.length)
+ return false;
+ for (int i = 0, length = memberValuePairs.length; i < length; i++) {
+ if (!memberValuePairs[i].isEqualTo(otherMemberValuePairs[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ ReferenceBinding annotationType = this.binding.getAnnotationType();
+ return annotationType == null || (annotationType.tagBits & TagBits.HasMissingType) != 0; }
+
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ public String toString() {
+ ITypeBinding type = getAnnotationType();
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append('@');
+ if (type != null)
+ buffer.append(type.getName());
+ buffer.append('(');
+ IMemberValuePairBinding[] pairs = getDeclaredMemberValuePairs();
+ for (int i = 0, len = pairs.length; i < len; i++) {
+ if (i != 0)
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(pairs[i].toString());
+ }
+ buffer.append(')');
+ return buffer.toString();
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java
new file mode 100644
index 000000000..4924c2b9e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeDeclaration.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Annotation type declaration AST node type (added in JLS3 API).
+ * <pre>
+ * AnnotationTypeDeclaration:
+ * [ Javadoc ] { ExtendedModifier } <b>@</b> <b>interface</b> Identifier
+ * <b>{</b> { AnnotationTypeBodyDeclaration | <b>;</b> } <b>}</b>
+ * AnnotationTypeBodyDeclaration:
+ * AnnotationTypeMemberDeclaration
+ * FieldDeclaration
+ * TypeDeclaration
+ * EnumDeclaration
+ * AnnotationTypeDeclaration
+ * </pre>
+ * <p>
+ * The thing to note is that method declaration are replaced
+ * by annotation type member declarations in this context.
+ * </p>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), or the
+ * first character of the "@interface" (if no
+ * modifiers). The source range extends through the last character of the "}"
+ * token following the body declarations.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnnotationTypeDeclaration extends AbstractTypeDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(AnnotationTypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(AnnotationTypeDeclaration.class);
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(AnnotationTypeDeclaration.class);
+
+ /**
+ * The "bodyDeclarations" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ internalBodyDeclarationPropertyFactory(AnnotationTypeDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(AnnotationTypeDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new AST node for an annotation type declaration owned by the given
+ * AST. By default, the type declaration is for an annotation
+ * type of an unspecified, but legal, name; no modifiers; no javadoc;
+ * and an empty list of body declarations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AnnotationTypeDeclaration(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ // this property will not be asked for (node type did not exist in JLS2)
+ return null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+ return BODY_DECLARATIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ANNOTATION_TYPE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ AnnotationTypeDeclaration result = new AnnotationTypeDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setName((SimpleName) getName().clone(target));
+ result.bodyDeclarations().addAll(ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AsbtractTypeDeclaration.
+ */
+ ITypeBinding internalResolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + this.modifiers.listSize()
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + this.bodyDeclarations.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java
new file mode 100644
index 000000000..18238725d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationTypeMemberDeclaration.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Annotation type member declaration AST node type (added in JLS3 API).
+ * <pre>
+ * AnnotationTypeMemberDeclaration:
+ * [ Javadoc ] { ExtendedModifier }
+ * Type Identifier <b>(</b> <b>)</b> [ <b>default</b> Expression ] <b>;</b>
+ * </pre>
+ * <p>
+ * Note that annotation type member declarations are only meaningful as
+ * elements of {@link AnnotationTypeDeclaration#bodyDeclarations()}.
+ * </p>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers),
+ * or the first character of the member type (no modifiers).
+ * The source range extends through the last character of the
+ * ";" token.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnnotationTypeMemberDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(AnnotationTypeMemberDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(AnnotationTypeMemberDeclaration.class);
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "default" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor DEFAULT_PROPERTY =
+ new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "default", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(6);
+ createPropertyList(AnnotationTypeMemberDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(DEFAULT_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The member name; lazily initialized; defaults to an unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName memberName = null;
+
+ /**
+ * The member type; lazily initialized; defaults to int.
+ */
+ private Type memberType = null;
+
+ /**
+ * The optional default expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalDefaultValue = null;
+
+ /**
+ * Creates a new AST node for an annotation type member declaration owned
+ * by the given AST. By default, the declaration is for a member of an
+ * unspecified, but legal, name; no modifiers; no javadoc;
+ * an unspecified value type; and no default value.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AnnotationTypeMemberDeclaration(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == DEFAULT_PROPERTY) {
+ if (get) {
+ return getDefault();
+ } else {
+ setDefault((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ // this property will not be asked for (node type did not exist in JLS2)
+ return null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ANNOTATION_TYPE_MEMBER_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ AnnotationTypeMemberDeclaration result = new AnnotationTypeMemberDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setType((Type) ASTNode.copySubtree(target, getType()));
+ result.setName((SimpleName) getName().clone(target));
+ result.setDefault((Expression) ASTNode.copySubtree(target, getDefault()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getDefault());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of the annotation type member declared in this declaration.
+ *
+ * @return the member name node
+ */
+ public SimpleName getName() {
+ if (this.memberName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.memberName == null) {
+ preLazyInit();
+ this.memberName = new SimpleName(this.ast);
+ postLazyInit(this.memberName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.memberName;
+ }
+
+ /**
+ * Sets the name of the annotation type member declared in this declaration to the
+ * given name.
+ *
+ * @param memberName the new member name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName memberName) {
+ if (memberName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.memberName;
+ preReplaceChild(oldChild, memberName, NAME_PROPERTY);
+ this.memberName = memberName;
+ postReplaceChild(oldChild, memberName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the type of the annotation type member declared in this
+ * declaration.
+ *
+ * @return the type of the member
+ */
+ public Type getType() {
+ if (this.memberType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.memberType == null) {
+ preLazyInit();
+ this.memberType = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.memberType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.memberType;
+ }
+
+ /**
+ * Sets the type of the annotation type member declared in this declaration
+ * to the given type.
+ *
+ * @param type the new member type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.memberType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.memberType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the default value of this annotation type member, or
+ * <code>null</code> if there is none.
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getDefault() {
+ return this.optionalDefaultValue;
+ }
+
+ /**
+ * Sets or clears the default value of this annotation type member.
+ *
+ * @param defaultValue the expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setDefault(Expression defaultValue) {
+ // a AnnotationTypeMemberDeclaration may occur inside an Expression - must check cycles
+ ASTNode oldChild = this.optionalDefaultValue;
+ preReplaceChild(oldChild, defaultValue, DEFAULT_PROPERTY);
+ this.optionalDefaultValue = defaultValue;
+ postReplaceChild(oldChild, defaultValue, DEFAULT_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the annotation type member declared
+ * in this declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public IMethodBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveMember(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + this.modifiers.listSize()
+ + (this.memberName == null ? 0 : getName().treeSize())
+ + (this.memberType == null ? 0 : getType().treeSize())
+ + (this.optionalDefaultValue == null ? 0 : getDefault().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java
new file mode 100644
index 000000000..97d407f22
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnonymousClassDeclaration.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Anonymous class declaration AST node type. For JLS2, this type of node appears
+ * only as a child on a class instance creation expression.
+ * For JLS3, this type of node appears may also appear as the child of
+ * an enum constant declaration.
+ *
+ * <pre>
+ * AnonymousClassDeclaration:
+ * <b>{</b> ClassBodyDeclaration <b>}</b>
+ * </pre>
+ *
+ * @see ClassInstanceCreation
+ * @see EnumConstantDeclaration
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnonymousClassDeclaration extends ASTNode {
+
+ /**
+ * The "bodyDeclarations" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ new ChildListPropertyDescriptor(AnonymousClassDeclaration.class, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(AnonymousClassDeclaration.class, properyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body declarations (element type: <code>BodyDeclaration</code>).
+ * Defaults to none.
+ */
+ private ASTNode.NodeList bodyDeclarations =
+ new ASTNode.NodeList(BODY_DECLARATIONS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an anonymous class declaration owned
+ * by the given AST. By default, the list of body declarations is empty.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AnonymousClassDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ANONYMOUS_CLASS_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ AnonymousClassDeclaration result = new AnonymousClassDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of body declarations of this
+ * anonymous class declaration.
+ *
+ * @return the live list of body declarations
+ * (element type: <code>BodyDeclaration</code>)
+ */
+ public List bodyDeclarations() {
+ return this.bodyDeclarations;
+ }
+
+ /**
+ * Resolves and returns the binding for the anonymous class declared in
+ * this declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + this.bodyDeclarations.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java
new file mode 100644
index 000000000..58e02e0e3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayAccess.java
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array access expression AST node type.
+ *
+ * <pre>
+ * ArrayAccess:
+ * Expression <b>[</b> Expression <b>]</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayAccess extends Expression {
+
+ /**
+ * The "array" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor ARRAY_PROPERTY =
+ new ChildPropertyDescriptor(ArrayAccess.class, "array", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "index" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor INDEX_PROPERTY =
+ new ChildPropertyDescriptor(ArrayAccess.class, "index", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ArrayAccess.class, properyList);
+ addProperty(ARRAY_PROPERTY, properyList);
+ addProperty(INDEX_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The array expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression arrayExpression = null;
+
+ /**
+ * The index expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression indexExpression = null;
+
+ /**
+ * Creates a new unparented array access expression node owned by the given
+ * AST. By default, the array and index expresssions are unspecified,
+ * but legal.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == ARRAY_PROPERTY) {
+ if (get) {
+ return getArray();
+ } else {
+ setArray((Expression) child);
+ return null;
+ }
+ }
+ if (property == INDEX_PROPERTY) {
+ if (get) {
+ return getIndex();
+ } else {
+ setIndex((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_ACCESS;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayAccess result = new ArrayAccess(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setArray((Expression) getArray().clone(target));
+ result.setIndex((Expression) getIndex().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getArray());
+ acceptChild(visitor, getIndex());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the array expression of this array access expression.
+ *
+ * @return the array expression node
+ */
+ public Expression getArray() {
+ if (this.arrayExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.arrayExpression == null) {
+ preLazyInit();
+ this.arrayExpression = new SimpleName(this.ast);
+ postLazyInit(this.arrayExpression, ARRAY_PROPERTY);
+ }
+ }
+ }
+ return this.arrayExpression;
+ }
+
+ /**
+ * Sets the array expression of this array access expression.
+ *
+ * @param expression the array expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setArray(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayAccess may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.arrayExpression;
+ preReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+ this.arrayExpression = expression;
+ postReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+ }
+
+ /**
+ * Returns the index expression of this array access expression.
+ *
+ * @return the index expression node
+ */
+ public Expression getIndex() {
+ if (this.indexExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.indexExpression == null) {
+ preLazyInit();
+ this.indexExpression = new SimpleName(this.ast);
+ postLazyInit(this.indexExpression, INDEX_PROPERTY);
+ }
+ }
+ }
+ return this.indexExpression;
+ }
+
+ /**
+ * Sets the index expression of this array access expression.
+ *
+ * @param expression the index expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setIndex(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayAccess may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.indexExpression;
+ preReplaceChild(oldChild, expression, INDEX_PROPERTY);
+ this.indexExpression = expression;
+ postReplaceChild(oldChild, expression, INDEX_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.arrayExpression == null ? 0 : getArray().treeSize())
+ + (this.indexExpression == null ? 0 : getIndex().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java
new file mode 100644
index 000000000..2a57be45c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayCreation.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array creation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * ArrayCreation:
+ * <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ * <b>new</b> TypeName <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ * <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * <b>new</b> TypeName <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * </pre>
+ * <p>
+ * The mapping from Java language syntax to AST nodes is as follows:
+ * <ul>
+ * <li>the type node is the array type of the creation expression,
+ * with one level of array per set of square brackets,</li>
+ * <li>the dimension expressions are collected into the <code>dimensions</code>
+ * list.</li>
+ * </ul>
+ * </p>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * ArrayCreation:
+ * <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ * <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ * <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayCreation extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ArrayCreation.class, "type", ArrayType.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "dimensions" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ArrayCreation.class, "dimensions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(ArrayCreation.class, "initializer", ArrayInitializer.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(ArrayCreation.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(DIMENSIONS_PROPERTY, properyList);
+ addProperty(INITIALIZER_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The array type; lazily initialized; defaults to a unspecified,
+ * legal array type.
+ */
+ private ArrayType arrayType = null;
+
+ /**
+ * The list of dimension expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList dimensions =
+ new ASTNode.NodeList(DIMENSIONS_PROPERTY);
+
+ /**
+ * The optional array initializer, or <code>null</code> if none;
+ * defaults to none.
+ */
+ private ArrayInitializer optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for an array creation expression owned by the
+ * given AST. By default, the array type is an unspecified 1-dimensional
+ * array, the list of dimensions is empty, and there is no array
+ * initializer.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayCreation(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((ArrayInitializer) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((ArrayType) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == DIMENSIONS_PROPERTY) {
+ return dimensions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_CREATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayCreation result = new ArrayCreation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setType((ArrayType) getType().clone(target));
+ result.dimensions().addAll(ASTNode.copySubtrees(target, dimensions()));
+ result.setInitializer(
+ (ArrayInitializer) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.dimensions);
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the array type in this array creation expression.
+ *
+ * @return the array type
+ */
+ public ArrayType getType() {
+ if (this.arrayType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.arrayType == null) {
+ preLazyInit();
+ this.arrayType = this.ast.newArrayType(
+ this.ast.newPrimitiveType(PrimitiveType.INT));
+ postLazyInit(this.arrayType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.arrayType;
+ }
+
+ /**
+ * Sets the array type in this array creation expression.
+ *
+ * @param type the new array type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(ArrayType type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayCreation cannot occur inside a ArrayType - cycles not possible
+ ASTNode oldChild = this.arrayType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.arrayType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of dimension expressions in this array
+ * initializer.
+ *
+ * @return the live list of dimension expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List dimensions() {
+ return this.dimensions;
+ }
+
+ /**
+ * Returns the array initializer of this array creation expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the array initializer node, or <code>null</code> if
+ * there is none
+ */
+ public ArrayInitializer getInitializer() {
+ return this.optionalInitializer;
+ }
+
+ /**
+ * Sets or clears the array initializer of this array creation expression.
+ *
+ * @param initializer the array initializer node, or <code>null</code>
+ * if there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setInitializer(ArrayInitializer initializer) {
+ // an ArrayCreation may occur inside an ArrayInitializer
+ // must check cycles
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ int size = memSize()
+ + (this.arrayType == null ? 0 : getType().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize())
+ + this.dimensions.listSize();
+ return size;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java
new file mode 100644
index 000000000..342faf063
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayInitializer.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array initializer AST node type.
+ *
+ * <pre>
+ * ArrayInitializer:
+ * <b>{</b> [ Expression { <b>,</b> Expression} [ <b>,</b> ]] <b>}</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayInitializer extends Expression {
+
+ /**
+ * The "expressions" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor EXPRESSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ArrayInitializer.class, "expressions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ArrayInitializer.class, properyList);
+ addProperty(EXPRESSIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList expressions =
+ new ASTNode.NodeList(EXPRESSIONS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an array initializer owned by the
+ * given AST. By default, the list of expressions is empty.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayInitializer(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == EXPRESSIONS_PROPERTY) {
+ return expressions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_INITIALIZER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayInitializer result = new ArrayInitializer(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.expressions().addAll(ASTNode.copySubtrees(target, expressions()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.expressions);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of expressions in this array initializer.
+ *
+ * @return the live list of expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List expressions() {
+ return this.expressions;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.expressions.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
new file mode 100644
index 000000000..25f8d9301
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for an array type.
+ * <p>
+ * Array types are expressed in a recursive manner, one dimension at a time.
+ * </p>
+ * <pre>
+ * ArrayType:
+ * Type <b>[</b> <b>]</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayType extends Type {
+
+ /**
+ * The "componentType" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ArrayType.class, properyList);
+ addProperty(COMPONENT_TYPE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The component type; lazily initialized; defaults to a simple type with
+ * an unspecfied, but legal, name.
+ */
+ private Type componentType = null;
+
+ /**
+ * Creates a new unparented node for an array type owned by the given AST.
+ * By default, a 1-dimensional array of an unspecified simple type.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == COMPONENT_TYPE_PROPERTY) {
+ if (get) {
+ return getComponentType();
+ } else {
+ setComponentType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayType result = new ArrayType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setComponentType((Type) getComponentType().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getComponentType());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the component type of this array type. The component type
+ * may be another array type.
+ *
+ * @return the component type node
+ */
+ public Type getComponentType() {
+ if (this.componentType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.componentType == null) {
+ preLazyInit();
+ this.componentType = new SimpleType(this.ast);
+ postLazyInit(this.componentType, COMPONENT_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.componentType;
+ }
+
+ /**
+ * Sets the component type of this array type. The component type
+ * may be another array type.
+ *
+ * @param componentType the component type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setComponentType(Type componentType) {
+ if (componentType == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.componentType;
+ preReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+ this.componentType = componentType;
+ postReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the element type of this array type. The element type is
+ * never an array type.
+ * <p>
+ * This is a convenience method that descends a chain of nested array types
+ * until it reaches a non-array type.
+ * </p>
+ *
+ * @return the component type node
+ */
+ public Type getElementType() {
+ Type t = getComponentType();
+ while (t.isArrayType()) {
+ t = ((ArrayType) t).getComponentType();
+ }
+ return t;
+ }
+
+ /**
+ * Returns the number of dimensions in this array type.
+ * <p>
+ * This is a convenience method that descends a chain of nested array types
+ * until it reaches a non-array type.
+ * </p>
+ *
+ * @return the number of dimensions (always positive)
+ */
+ public int getDimensions() {
+ Type t = getComponentType();
+ int dimensions = 1; // always include this array type
+ while (t.isArrayType()) {
+ dimensions++;
+ t = ((ArrayType) t).getComponentType();
+ }
+ return dimensions;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.componentType == null ? 0 : getComponentType().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java
new file mode 100644
index 000000000..c7720f9a4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AssertStatement.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Assert statement AST node type.
+ *
+ * <pre>
+ * AssertStatement:
+ * <b>assert</b> Expression [ <b>:</b> Expression ] <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AssertStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(AssertStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "message" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor MESSAGE_PROPERTY =
+ new ChildPropertyDescriptor(AssertStatement.class, "message", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(AssertStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(MESSAGE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The message expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalMessageExpression = null;
+
+ /**
+ * Creates a new unparented assert statement node owned by the given
+ * AST. By default, the assert statement has an unspecified, but legal,
+ * expression, and not message expression.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ AssertStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == MESSAGE_PROPERTY) {
+ if (get) {
+ return getMessage();
+ } else {
+ setMessage((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ASSERT_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ AssertStatement result = new AssertStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ result.setMessage(
+ (Expression) ASTNode.copySubtree(target, getMessage()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getMessage());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the first expression of this assert statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the first expression of this assert statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an AssertStatement may occur inside an Expression - must check cycles
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the message expression of this assert statement, or
+ * <code>null</code> if there is none.
+ *
+ * @return the message expression node, or <code>null</code> if there
+ * is none
+ */
+ public Expression getMessage() {
+ return this.optionalMessageExpression;
+ }
+
+ /**
+ * Sets or clears the message expression of this assert statement.
+ *
+ * @param expression the message expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setMessage(Expression expression) {
+ // an AsertStatement may occur inside an Expression - must check cycles
+ ASTNode oldChild = this.optionalMessageExpression;
+ preReplaceChild(oldChild, expression, MESSAGE_PROPERTY);
+ this.optionalMessageExpression = expression;
+ postReplaceChild(oldChild, expression, MESSAGE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.optionalMessageExpression == null ? 0 : getMessage().treeSize());
+
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
new file mode 100644
index 000000000..411c94641
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Assignment expression AST node type.
+ *
+ * <pre>
+ * Assignment:
+ * Expression AssignmentOperator Expression
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Assignment extends Expression {
+
+ /**
+ * Assignment operators (typesafe enumeration).
+ * <pre>
+ * AssignmentOperator:<code>
+ * <b>=</b> ASSIGN
+ * <b>+=</b> PLUS_ASSIGN
+ * <b>-=</b> MINUS_ASSIGN
+ * <b>*=</b> TIMES_ASSIGN
+ * <b>/=</b> DIVIDE_ASSIGN
+ * <b>&amp;=</b> BIT_AND_ASSIGN
+ * <b>|=</b> BIT_OR_ASSIGN
+ * <b>^=</b> BIT_XOR_ASSIGN
+ * <b>%=</b> REMAINDER_ASSIGN
+ * <b>&lt;&lt;=</b> LEFT_SHIFT_ASSIGN
+ * <b>&gt;&gt;=</b> RIGHT_SHIFT_SIGNED_ASSIGN
+ * <b>&gt;&gt;&gt;=</b> RIGHT_SHIFT_UNSIGNED_ASSIGN</code>
+ * </pre>
+ */
+ public static class Operator {
+
+ /**
+ * The name of the operator
+ */
+ private String op;
+
+ /**
+ * Creates a new assignment operator with the given name.
+ * <p>
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ * </p>
+ *
+ * @param op the character sequence for the operator
+ */
+ private Operator(String op) {
+ this.op = op;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return this.op;
+ }
+
+ /** = operator. */
+ public static final Operator ASSIGN = new Operator("=");//$NON-NLS-1$
+ /** += operator. */
+ public static final Operator PLUS_ASSIGN = new Operator("+=");//$NON-NLS-1$
+ /** -= operator. */
+ public static final Operator MINUS_ASSIGN = new Operator("-=");//$NON-NLS-1$
+ /** *= operator. */
+ public static final Operator TIMES_ASSIGN = new Operator("*=");//$NON-NLS-1$
+ /** /= operator. */
+ public static final Operator DIVIDE_ASSIGN = new Operator("/=");//$NON-NLS-1$
+ /** &amp;= operator. */
+ public static final Operator BIT_AND_ASSIGN = new Operator("&=");//$NON-NLS-1$
+ /** |= operator. */
+ public static final Operator BIT_OR_ASSIGN = new Operator("|=");//$NON-NLS-1$
+ /** ^= operator. */
+ public static final Operator BIT_XOR_ASSIGN = new Operator("^=");//$NON-NLS-1$
+ /** %= operator. */
+ public static final Operator REMAINDER_ASSIGN = new Operator("%=");//$NON-NLS-1$
+ /** &lt;&lt;== operator. */
+ public static final Operator LEFT_SHIFT_ASSIGN =
+ new Operator("<<=");//$NON-NLS-1$
+ /** &gt;&gt;= operator. */
+ public static final Operator RIGHT_SHIFT_SIGNED_ASSIGN =
+ new Operator(">>=");//$NON-NLS-1$
+ /** &gt;&gt;&gt;= operator. */
+ public static final Operator RIGHT_SHIFT_UNSIGNED_ASSIGN =
+ new Operator(">>>=");//$NON-NLS-1$
+
+ /**
+ * Returns the assignment operator corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toOperator</code> is the converse of <code>toString</code>:
+ * that is, <code>Operator.toOperator(op.toString()) == op</code> for all
+ * operators <code>op</code>.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ * @return the assignment operator, or <code>null</code> if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ ASSIGN,
+ PLUS_ASSIGN,
+ MINUS_ASSIGN,
+ TIMES_ASSIGN,
+ DIVIDE_ASSIGN,
+ BIT_AND_ASSIGN,
+ BIT_OR_ASSIGN,
+ BIT_XOR_ASSIGN,
+ REMAINDER_ASSIGN,
+ LEFT_SHIFT_ASSIGN,
+ RIGHT_SHIFT_SIGNED_ASSIGN,
+ RIGHT_SHIFT_UNSIGNED_ASSIGN
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+ }
+
+ /**
+ * The "leftHandSide" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LEFT_HAND_SIDE_PROPERTY =
+ new ChildPropertyDescriptor(Assignment.class, "leftHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "operator" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(Assignment.class, "operator", Assignment.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "rightHandSide" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor RIGHT_HAND_SIDE_PROPERTY =
+ new ChildPropertyDescriptor(Assignment.class, "rightHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(Assignment.class, properyList);
+ addProperty(LEFT_HAND_SIDE_PROPERTY, properyList);
+ addProperty(OPERATOR_PROPERTY, properyList);
+ addProperty(RIGHT_HAND_SIDE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The assignment operator; defaults to Assignment.Operator.ASSIGN
+ */
+ private Assignment.Operator assignmentOperator = Assignment.Operator.ASSIGN;
+
+ /**
+ * The left hand side; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftHandSide = null;
+
+ /**
+ * The right hand side; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression rightHandSide = null;
+
+ /**
+ * Creates a new AST node for an assignment expression owned by the given
+ * AST. By default, the node has an assignment operator, and unspecified
+ * left and right hand sides.
+ *
+ * @param ast the AST that is to own this node
+ */
+ Assignment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_HAND_SIDE_PROPERTY) {
+ if (get) {
+ return getLeftHandSide();
+ } else {
+ setLeftHandSide((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_HAND_SIDE_PROPERTY) {
+ if (get) {
+ return getRightHandSide();
+ } else {
+ setRightHandSide((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ASSIGNMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Assignment result = new Assignment(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setOperator(getOperator());
+ result.setLeftHandSide((Expression) getLeftHandSide().clone(target));
+ result.setRightHandSide((Expression) getRightHandSide().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftHandSide());
+ acceptChild(visitor, getRightHandSide());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this assignment expression.
+ *
+ * @return the assignment operator
+ */
+ public Assignment.Operator getOperator() {
+ return this.assignmentOperator;
+ }
+
+ /**
+ * Sets the operator of this assignment expression.
+ *
+ * @param assignmentOperator the assignment operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(Assignment.Operator assignmentOperator) {
+ if (assignmentOperator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.assignmentOperator = assignmentOperator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the left hand side of this assignment expression.
+ *
+ * @return the left hand side node
+ */
+ public Expression getLeftHandSide() {
+ if (this.leftHandSide == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftHandSide == null) {
+ preLazyInit();
+ this.leftHandSide= new SimpleName(this.ast);
+ postLazyInit(this.leftHandSide, LEFT_HAND_SIDE_PROPERTY);
+ }
+ }
+ }
+ return this.leftHandSide;
+ }
+
+ /**
+ * Sets the left hand side of this assignment expression.
+ *
+ * @param expression the left hand side node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setLeftHandSide(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an Assignment may occur inside a Expression - must check cycles
+ ASTNode oldChild = this.leftHandSide;
+ preReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+ this.leftHandSide = expression;
+ postReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+ }
+
+ /**
+ * Returns the right hand side of this assignment expression.
+ *
+ * @return the right hand side node
+ */
+ public Expression getRightHandSide() {
+ if (this.rightHandSide == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightHandSide == null) {
+ preLazyInit();
+ this.rightHandSide= new SimpleName(this.ast);
+ postLazyInit(this.rightHandSide, RIGHT_HAND_SIDE_PROPERTY);
+ }
+ }
+ }
+ return this.rightHandSide;
+ }
+
+ /**
+ * Sets the right hand side of this assignment expression.
+ *
+ * @param expression the right hand side node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setRightHandSide(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an Assignment may occur inside a Expression - must check cycles
+ ASTNode oldChild = this.rightHandSide;
+ preReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+ this.rightHandSide = expression;
+ postReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftHandSide == null ? 0 : getLeftHandSide().treeSize())
+ + (this.rightHandSide == null ? 0 : getRightHandSide().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java
new file mode 100644
index 000000000..94c0ee59c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java
@@ -0,0 +1,273 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: BaseCallMessageSend.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT
+ *
+ * BaseCallMessageSend represents a 'base call'
+ * inside a role method with 'callin' modifier (OTJLD §4.3),
+ * e.g.
+ * <code>base.myRoleMethod(arg1, arg2)</code>
+ *
+ * Contained AST elements:
+ * a selector name (<code>SimpleName</code>), e.g. <code>myRoleMethod<code>.
+ * a List of argument expressions (<code>Expression</code>).
+ *
+ * @author mkr
+ * @version $Id: BaseCallMessageSend.java 23416 2010-02-03 19:59:31Z stephan $
+ */
+public class BaseCallMessageSend extends Expression
+{
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(BaseCallMessageSend.class,
+ "name",//$NON-NLS-1$
+ SimpleName.class,
+ MANDATORY,
+ NO_CYCLE_RISK);
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(BaseCallMessageSend.class,
+ "arguments",//$NON-NLS-1$
+ Expression.class,
+ CYCLE_RISK);
+
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ List propertyList = new ArrayList(3);
+ createPropertyList(BaseCallMessageSend.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The method name; lazily initialized;
+ */
+ private SimpleName _methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList _arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a tsuper expression owned by the given AST.
+ * By default, there is no qualifier.
+ *
+ * @param ast the AST that is to own this node
+ */
+ BaseCallMessageSend(AST ast)
+ {
+ super(ast);
+ }
+
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property,
+ boolean get,
+ ASTNode child)
+ {
+
+ if (property == NAME_PROPERTY)
+ {
+ if (get) {
+ return getName();
+ }
+ else
+ {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == ARGUMENTS_PROPERTY)
+ {
+ return getArguments();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ final int getNodeType0()
+ {
+ return BASE_CALL_MESSAGE_SEND;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ BaseCallMessageSend result = new BaseCallMessageSend(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((SimpleName)_methodName.clone(target));
+ result.getArguments().addAll(ASTNode.copySubtrees(target, _arguments));
+ return result;
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, _methodName);
+ acceptChildren(visitor, _arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName()
+ {
+ if (_methodName == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_methodName == null)
+ {
+ preLazyInit();
+ _methodName = new SimpleName(this.ast);
+ postLazyInit(_methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return _methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name)
+ {
+ if (name == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = _methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ _methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the ordered list of argument expressions in this
+ * base call method send expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List getArguments()
+ {
+ return _arguments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize()
+ {
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize()
+ {
+ return
+ memSize()
+ + (_methodName == null ? 0 : _methodName.treeSize())
+ + (_arguments == null ? 0 : _arguments.listSize());
+ }
+
+ public IMethodBinding resolveMethodBinding()
+ {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java
new file mode 100644
index 000000000..25f4c5126
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java
@@ -0,0 +1,184 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: BaseConstructorInvocation.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT
+ *
+ * BaseConstructorMessageSend represents a 'base call' to a constructor of the
+ * role's base class (OTJLD §2.4.2),
+ * e.g. <code>base();</code> or <code>base(arg1, arg2);</code>.
+ *
+ * Contained AST elements:
+ * a list of argument expressions (<code>Expression</code>).
+ *
+ * Locations in source code:
+ * This node can only be used within role constructor bodies, i.e. it appears in
+ * ordinary <code>ExpressionStatement</code>s only.
+ *
+ * Contrary to org.eclipse.jdt.internal.compiler.ast.BaseConstructorMessageSend
+ * this is not an assignment. In the compiler ast
+ * "base(args)" is translated to "_OT$base = new BaseClass(args);".
+ * In the dom ast we just need "base(args);".
+ *
+ * @author mkr
+ * @version $Id: BaseConstructorInvocation.java 23416 2010-02-03 19:59:31Z stephan $
+ */
+public class BaseConstructorInvocation extends Statement
+{
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(BaseConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ List propertyList = new ArrayList(2);
+ createPropertyList(BaseConstructorInvocation.class, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList _arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a base expression owned by the given AST.
+ * By default, there is no qualifier.
+ *
+ * @param ast the AST that is to own this node
+ */
+ BaseConstructorInvocation(AST ast)
+ {
+ super(ast);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this
+ * base constructor invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List getArguments()
+ {
+ return _arguments;
+ }
+
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == ARGUMENTS_PROPERTY)
+ {
+ return getArguments();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ final int getNodeType0()
+ {
+ return BASE_CONSTRUCTOR_INVOCATION;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ BaseConstructorInvocation result = new BaseConstructorInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.getArguments().addAll(ASTNode.copySubtrees(target, getArguments()));
+
+ return result;
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, _arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+
+ int memSize()
+ {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ int treeSize()
+ {
+ return memSize() + (_arguments == null
+ ? 0
+ : _arguments.listSize());
+ }
+
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java
new file mode 100644
index 000000000..27aff86ea
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.HashSet;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+
+/**
+ * Internal helper class for comparing bindings.
+ *
+ * @since 3.1
+ */
+class BindingComparator {
+ /**
+ * @param bindings
+ * @param otherBindings
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(TypeVariableBinding[] bindings, TypeVariableBinding[] otherBindings) {
+ if (bindings == null) {
+ return otherBindings == null;
+ }
+ if (otherBindings == null) {
+ return false;
+ }
+ int length = bindings.length;
+ int otherLength = otherBindings.length;
+ if (length != otherLength) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ TypeVariableBinding typeVariableBinding = bindings[i];
+ TypeVariableBinding typeVariableBinding2 = otherBindings[i];
+ if (!isEqual(typeVariableBinding, typeVariableBinding2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @param declaringElement
+ * @param declaringElement2
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(Binding declaringElement, Binding declaringElement2, HashSet visitedTypes) {
+ if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding)){
+ return false;
+ }
+ return isEqual((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement,
+ (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement2,
+ visitedTypes);
+ } else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding)) {
+ return false;
+ }
+ return isEqual((org.eclipse.jdt.internal.compiler.lookup.MethodBinding) declaringElement,
+ (org.eclipse.jdt.internal.compiler.lookup.MethodBinding) declaringElement2,
+ visitedTypes);
+ } else if (declaringElement instanceof VariableBinding) {
+ if (!(declaringElement2 instanceof VariableBinding)) {
+ return false;
+ }
+ return isEqual((VariableBinding) declaringElement,
+ (VariableBinding) declaringElement2);
+ } else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding)) {
+ return false;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding = (org.eclipse.jdt.internal.compiler.lookup.PackageBinding) declaringElement;
+ org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = (org.eclipse.jdt.internal.compiler.lookup.PackageBinding) declaringElement2;
+ return CharOperation.equals(packageBinding.compoundName, packageBinding2.compoundName);
+ } else if (declaringElement instanceof ImportBinding) {
+ if (!(declaringElement2 instanceof ImportBinding)) {
+ return false;
+ }
+ ImportBinding importBinding = (ImportBinding) declaringElement;
+ ImportBinding importBinding2 = (ImportBinding) declaringElement2;
+ return importBinding.isStatic() == importBinding2.isStatic()
+ && importBinding.onDemand == importBinding2.onDemand
+ && CharOperation.equals(importBinding.compoundName, importBinding2.compoundName);
+ }
+ return false;
+ }
+
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2) {
+ return isEqual(methodBinding, methodBinding2, new HashSet());
+ }
+
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2,
+ HashSet visitedTypes) {
+ if (methodBinding == null) {
+ return methodBinding2 == null;
+ }
+ if (methodBinding2 == null) return false;
+ return CharOperation.equals(methodBinding.selector, methodBinding2.selector)
+ && isEqual(methodBinding.returnType, methodBinding2.returnType, visitedTypes)
+ && isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, visitedTypes)
+ && isEqual(methodBinding.declaringClass, methodBinding2.declaringClass, visitedTypes)
+ && isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, visitedTypes)
+ && isEqual(methodBinding.parameters, methodBinding2.parameters, visitedTypes);
+ }
+
+ static boolean isEqual(org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding mapping,
+ org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding mapping2)
+ {
+ return isEqual(mapping, mapping2, new HashSet());
+ }
+
+ static boolean isEqual(org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding mapping,
+ org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding mapping2,
+ HashSet visitedTypes)
+ {
+ if (mapping == null) {
+ return mapping2 == null;
+ }
+ if (mapping2 == null) return false;
+ if (mapping.name != null || mapping2.name != null) {
+ if (mapping.name == null || mapping2.name == null) return false;
+ if (!CharOperation.equals(mapping.name, mapping2.name)) return false;
+ }
+ if (mapping.isCallin() != mapping2.isCallin()) return false;
+ if (!isEqual(mapping._roleMethodBinding, mapping2._roleMethodBinding)) return false;
+ if (mapping.callinModifier != mapping2.callinModifier) return false;
+ if (mapping.calloutModifier != mapping2.calloutModifier) return false;
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] baseMethods = mapping._baseMethods;
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] baseMethods2 = mapping2._baseMethods;
+ if (baseMethods.length != baseMethods2.length) return false;
+ for (int i = 0; i < baseMethods.length; i++)
+ if (!isEqual(baseMethods[i], baseMethods2[i])) return false;
+ return true;
+ }
+
+ static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) {
+ return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+ && CharOperation.equals(variableBinding.name, variableBinding2.name)
+ && isEqual(variableBinding.type, variableBinding2.type)
+ && (variableBinding.id == variableBinding2.id);
+ }
+
+ static boolean isEqual(FieldBinding fieldBinding, FieldBinding fieldBinding2) {
+ HashSet visitedTypes = new HashSet();
+ return (fieldBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (fieldBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+ && CharOperation.equals(fieldBinding.name, fieldBinding2.name)
+ && isEqual(fieldBinding.type, fieldBinding2.type, visitedTypes)
+ && isEqual(fieldBinding.declaringClass, fieldBinding2.declaringClass, visitedTypes);
+ }
+
+ /**
+ * @param bindings
+ * @param otherBindings
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings) {
+ return isEqual(bindings, otherBindings, new HashSet());
+ }
+ /**
+ * @param bindings
+ * @param otherBindings
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings, HashSet visitedTypes) {
+ if (bindings == null) {
+ return otherBindings == null;
+ }
+ if (otherBindings == null) {
+ return false;
+ }
+ int length = bindings.length;
+ int otherLength = otherBindings.length;
+ if (length != otherLength) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (!isEqual(bindings[i], otherBindings[i], visitedTypes)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2, HashSet visitedTypes) {
+ if (typeBinding == typeBinding2)
+ return true;
+ if (typeBinding == null || typeBinding2 == null)
+ return false;
+
+// TODO(SH): Should this method use AccOTTypeJustFlag instead of AccJustFlag?
+
+ switch (typeBinding.kind()) {
+ case Binding.BASE_TYPE :
+ if (!typeBinding2.isBaseType()) {
+ return false;
+ }
+ return typeBinding.id == typeBinding2.id;
+
+ case Binding.ARRAY_TYPE :
+ if (!typeBinding2.isArrayType()) {
+ return false;
+ }
+ return typeBinding.dimensions() == typeBinding2.dimensions()
+ && isEqual(typeBinding.leafComponentType(), typeBinding2.leafComponentType(), visitedTypes);
+
+ case Binding.PARAMETERIZED_TYPE :
+ if (!typeBinding2.isParameterizedType()) {
+ return false;
+ }
+ ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) typeBinding;
+ ParameterizedTypeBinding parameterizedTypeBinding2 = (ParameterizedTypeBinding) typeBinding2;
+ return CharOperation.equals(parameterizedTypeBinding.compoundName, parameterizedTypeBinding2.compoundName)
+ && (parameterizedTypeBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ == (parameterizedTypeBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ && isEqual(parameterizedTypeBinding.arguments, parameterizedTypeBinding2.arguments, visitedTypes)
+ && isEqual(parameterizedTypeBinding.enclosingType(), parameterizedTypeBinding2.enclosingType(), visitedTypes);
+
+ case Binding.WILDCARD_TYPE :
+ if (typeBinding2.kind() != Binding.WILDCARD_TYPE) {
+ return false;
+ }
+ WildcardBinding wildcardBinding = (WildcardBinding) typeBinding;
+ WildcardBinding wildcardBinding2 = (WildcardBinding) typeBinding2;
+ return isEqual(wildcardBinding.bound, wildcardBinding2.bound, visitedTypes)
+ && wildcardBinding.boundKind == wildcardBinding2.boundKind;
+
+ case Binding.INTERSECTION_TYPE:
+ if (typeBinding2.kind() != Binding.INTERSECTION_TYPE) {
+ return false;
+ }
+ WildcardBinding intersectionBinding = (WildcardBinding) typeBinding;
+ WildcardBinding intersectionBinding2 = (WildcardBinding) typeBinding2;
+ return isEqual(intersectionBinding.bound, intersectionBinding2.bound, visitedTypes)
+ && isEqual(intersectionBinding.otherBounds, intersectionBinding2.otherBounds, visitedTypes);
+
+ case Binding.TYPE_PARAMETER :
+ if (!(typeBinding2.isTypeVariable())) {
+ return false;
+ }
+ if (typeBinding.isCapture()) {
+ if (!(typeBinding2.isCapture())) {
+ return false;
+ }
+ CaptureBinding captureBinding = (CaptureBinding) typeBinding;
+ CaptureBinding captureBinding2 = (CaptureBinding) typeBinding2;
+ if (captureBinding.position == captureBinding2.position) {
+ if (visitedTypes.contains(typeBinding)) return true;
+ visitedTypes.add(typeBinding);
+
+ return isEqual(captureBinding.wildcard, captureBinding2.wildcard, visitedTypes)
+ && isEqual(captureBinding.sourceType, captureBinding2.sourceType, visitedTypes);
+ }
+ return false;
+ }
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) typeBinding;
+ TypeVariableBinding typeVariableBinding2 = (TypeVariableBinding) typeBinding2;
+ if (CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)) {
+ if (visitedTypes.contains(typeBinding)) return true;
+ visitedTypes.add(typeBinding);
+
+ return isEqual(typeVariableBinding.declaringElement, typeVariableBinding2.declaringElement, visitedTypes)
+ && isEqual(typeVariableBinding.superclass(), typeVariableBinding2.superclass(), visitedTypes)
+ && isEqual(typeVariableBinding.superInterfaces(), typeVariableBinding2.superInterfaces(), visitedTypes);
+ }
+ return false;
+ case Binding.GENERIC_TYPE :
+ if (!typeBinding2.isGenericType()) {
+ return false;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+ ReferenceBinding referenceBinding2 = (ReferenceBinding) typeBinding2;
+ return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+ && (referenceBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ == (referenceBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ && isEqual(referenceBinding.typeVariables(), referenceBinding2.typeVariables(), visitedTypes)
+ && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
+
+ case Binding.RAW_TYPE :
+ default :
+ if (!(typeBinding2 instanceof ReferenceBinding)) {
+ return false;
+ }
+//{ObjectTeams: avoid confusion between class/ifc parts of a role:
+/* orig:
+ referenceBinding = (ReferenceBinding) typeBinding;
+ referenceBinding2 = (ReferenceBinding) typeBinding2;
+ :giro */
+ referenceBinding = ((ReferenceBinding) typeBinding).getRealType();
+ referenceBinding2 = ((ReferenceBinding) typeBinding2).getRealType();
+// SH}
+ char[] constantPoolName = referenceBinding.constantPoolName();
+ char[] constantPoolName2 = referenceBinding2.constantPoolName();
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=116833
+ if (constantPoolName == null) {
+ if (constantPoolName2 != null) {
+ return false;
+ }
+ if (!CharOperation.equals(referenceBinding.computeUniqueKey(), referenceBinding2.computeUniqueKey())) {
+ return false;
+ }
+ } else {
+ if (constantPoolName2 == null) {
+ return false;
+ }
+ if (!CharOperation.equals(constantPoolName, constantPoolName2)) {
+ return false;
+ }
+ }
+ return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+ && (!referenceBinding2.isGenericType())
+ && (referenceBinding.isRawType() == referenceBinding2.isRawType())
+ && ((referenceBinding.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ == ((referenceBinding2.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+ && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
+ }
+ }
+ /**
+ * @param typeBinding
+ * @param typeBinding2
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2) {
+ return isEqual(typeBinding, typeBinding2, new HashSet());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
new file mode 100644
index 000000000..0b2424805
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
@@ -0,0 +1,1049 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: BindingResolver.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+
+/**
+ * A binding resolver is an internal mechanism for figuring out the binding
+ * for a major declaration, type, or name reference. This also handles
+ * the creation and mapping between annotations and the ast nodes that define them.
+ * <p>
+ * The default implementation serves as the default binding resolver
+ * that does no resolving whatsoever. Internal subclasses do all the real work.
+ * </p>
+ *
+ * @see AST#getBindingResolver
+ */
+class BindingResolver {
+
+ /**
+ * Creates a binding resolver.
+ */
+ BindingResolver() {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Finds the corresponding AST node from which the given binding originated.
+ * Returns <code>null</code> if the binding does not correspond to any node
+ * in the compilation unit.
+ * <p>
+ * The following table indicates the expected node type for the various
+ * different kinds of bindings:
+ * <ul>
+ * <li></li>
+ * <li>package - a <code>PackageDeclaration</code></li>
+ * <li>class or interface - a <code>TypeDeclaration</code> or a
+ * <code>ClassInstanceCreation</code> (for anonymous classes) </li>
+ * <li>primitive type - none</li>
+ * <li>array type - none</li>
+ * <li>field - a <code>VariableDeclarationFragment</code> in a
+ * <code>FieldDeclaration</code> </li>
+ * <li>local variable - a <code>SingleVariableDeclaration</code>, or
+ * a <code>VariableDeclarationFragment</code> in a
+ * <code>VariableDeclarationStatement</code> or
+ * <code>VariableDeclarationExpression</code></li>
+ * <li>method - a <code>MethodDeclaration</code> </li>
+ * <li>constructor - a <code>MethodDeclaration</code> </li>
+ * <li>annotation type - an <code>AnnotationTypeDeclaration</code>
+ * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code>
+ * </ul>
+ * </p>
+ * <p>
+ * The implementation of <code>CompilationUnit.findDeclaringNode</code>
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param binding the binding
+ * @return the corresponding node where the bindings is declared,
+ * or <code>null</code> if none
+ */
+ ASTNode findDeclaringNode(IBinding binding) {
+ return null;
+ }
+
+ /**
+ * Finds the corresponding AST node from which the given binding key originated.
+ *
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param bindingKey the binding key
+ * @return the corresponding node where the bindings is declared,
+ * or <code>null</code> if none
+ */
+ ASTNode findDeclaringNode(String bindingKey) {
+ return null;
+ }
+
+ /**
+ * Finds the corresponding AST node from which the given annotation instance originated.
+ *
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param instance the dom annotation
+ * @return the corresponding node where the bindings is declared,
+ * or <code>null</code> if none
+ */
+ ASTNode findDeclaringNode(IAnnotationBinding instance) {
+ return null;
+ }
+
+ /**
+ * Allows the user to get information about the given old/new pair of
+ * AST nodes.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param currentNode the new node
+ * @return org.eclipse.jdt.internal.compiler.ast.ASTNode
+ */
+ org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+ return null;
+ }
+
+ /**
+ * Returns the new method binding corresponding to the given old method binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param methodBinding the old method binding
+ * @return the new method binding
+ */
+ IMethodBinding getMethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
+ return null;
+ }
+
+//{ObjectTeams: new retrieval:
+ IMethodMappingBinding getMethodMappingBinding(org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding callbinding) {
+ return null;
+ }
+// SH}
+ /**
+ * Returns the new member value pair binding corresponding to the given old value pair binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param valuePair the old value pair binding
+ * @return the new member value pair binding
+ */
+ IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) {
+ return null;
+ }
+
+ /**
+ * Returns the new package binding corresponding to the given old package binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param packageBinding the old package binding
+ * @return the new package binding
+ */
+ IPackageBinding getPackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given old type binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param referenceBinding the old type binding
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+ return null;
+ }
+
+
+ /**
+ * Returns the new type binding corresponding to the given variableDeclaration.
+ * This is used for recovered binding only.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param variableDeclaration the given variable declaration
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given type. This is used for recovered binding
+ * only.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the given type
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(Type type) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given recovered type binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param recoveredTypeBinding the recovered type binding
+ * @param dimensions the dimensions to add the to given type binding dimensions
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+ return null;
+ }
+
+ /**
+ * Returns the new variable binding corresponding to the given old variable binding.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param binding the old variable binding
+ * @return the new variable binding
+ */
+ IVariableBinding getVariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
+ return null;
+ }
+
+ /**
+ * Return the working copy owner for the receiver.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ * @return the working copy owner for the receiver
+ */
+ public WorkingCopyOwner getWorkingCopyOwner() {
+ return null;
+ }
+
+ /**
+ * Return the new annotation corresponding to the given old annotation
+ * <p>
+ * The default implementation of this method returns <code>null</code>
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param instance the old annotation
+ * @return the new DOM annotation
+ */
+ IAnnotationBinding getAnnotationInstance(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding instance) {
+ return null;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(MethodInvocation methodInvocation) {
+ return false;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation methodInvocation) {
+ return false;
+ }
+
+ /**
+ * Returns the compiler lookup environment used by this binding resolver.
+ * Returns <code>null</code> if none.
+ *
+ * @return the lookup environment used by this resolver, or <code>null</code> if none.
+ */
+ LookupEnvironment lookupEnvironment() {
+ return null;
+ }
+
+ /**
+ * This method is used to record the scope and its corresponding node.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ * </p>
+ * @param astNode
+ */
+ void recordScope(ASTNode astNode, BlockScope blockScope) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Returns whether this expression node is the site of a boxing
+ * conversion (JLS3 5.1.7). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return <code>true</code> if this expression is the site of a
+ * boxing conversion, or <code>false</code> if either no boxing conversion
+ * is involved or if bindings were not requested when the AST was created
+ * @since 3.1
+ */
+ boolean resolveBoxing(Expression expression) {
+ return false;
+ }
+
+ /**
+ * Returns whether this expression node is the site of an unboxing
+ * conversion (JLS3 5.1.8). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return <code>true</code> if this expression is the site of an
+ * unboxing conversion, or <code>false</code> if either no unboxing
+ * conversion is involved or if bindings were not requested when the
+ * AST was created
+ * @since 3.1
+ */
+ boolean resolveUnboxing(Expression expression) {
+ return false;
+ }
+
+ /**
+ * Resolves and returns the compile-time constant expression value as
+ * specified in JLS2 15.28, if this expression has one. Constant expression
+ * values are unavailable unless bindings are requested when the AST is
+ * being built. If the type of the value is a primitive type, the result
+ * is the boxed equivalent (i.e., int returned as an <code>Integer</code>);
+ * if the type of the value is <code>String</code>, the result is the string
+ * itself. If the expression does not have a compile-time constant expression
+ * value, the result is <code>null</code>.
+ * <p>
+ * Resolving constant expressions takes into account the value of simple
+ * and qualified names that refer to constant variables (JLS2 4.12.4).
+ * </p>
+ * <p>
+ * Note 1: enum constants are not considered constant expressions either.
+ * The result is always <code>null</code> for these.
+ * </p>
+ * <p>
+ * Note 2: Compile-time constant expressions cannot denote <code>null</code>.
+ * So technically {@link NullLiteral} nodes are not constant expressions.
+ * The result is <code>null</code> for these nonetheless.
+ * </p>
+ *
+ * @return the constant expression value, or <code>null</code> if this
+ * expression has no constant expression value or if bindings were not
+ * requested when the AST was created
+ * @since 3.1
+ */
+ Object resolveConstantExpressionValue(Expression expression) {
+ return null;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ * <p>
+ * The implementation of
+ * <code>ClassInstanceCreation.resolveConstructor</code>
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
+ return null;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ * <p>
+ * The implementation of
+ * <code>ConstructorInvocation.resolveConstructor</code>
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveConstructor(ConstructorInvocation expression) {
+ return null;
+ }
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ * <p>
+ * The implementation of
+ * <code>ConstructorInvocation.resolveConstructor</code>
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param enumConstantDeclaration the enum constant declaration of interest
+ * @return the binding for the constructor being invoked, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveConstructor(EnumConstantDeclaration enumConstantDeclaration) {
+ return null;
+ }
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ * <p>
+ * The implementation of
+ * <code>SuperConstructorInvocation.resolveConstructor</code>
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
+ return null;
+ }
+ /**
+ * Resolves the type of the given expression and returns the type binding
+ * for it.
+ * <p>
+ * The implementation of <code>Expression.resolveTypeBinding</code>
+ * forwards to this method. The result is often a function of the context
+ * in which the expression node is embedded as well as the expression
+ * subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param expression the expression whose type is of interest
+ * @return the binding for the type of the given expression, or
+ * <code>null</code> if no binding is available
+ */
+ ITypeBinding resolveExpressionType(Expression expression) {
+ return null;
+ }
+
+ /**
+ * Resolves the given field access and returns the binding for it.
+ * <p>
+ * The implementation of <code>FieldAccess.resolveFieldBinding</code>
+ * forwards to this method. How the field resolves is often a function of
+ * the context in which the field access node is embedded as well as
+ * the field access subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param fieldAccess the field access of interest
+ * @return the binding for the given field access, or
+ * <code>null</code> if no binding is available
+ */
+ IVariableBinding resolveField(FieldAccess fieldAccess) {
+ return null;
+ }
+
+ /**
+ * Resolves the given super field access and returns the binding for it.
+ * <p>
+ * The implementation of <code>SuperFieldAccess.resolveFieldBinding</code>
+ * forwards to this method. How the field resolves is often a function of
+ * the context in which the super field access node is embedded as well as
+ * the super field access subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param fieldAccess the super field access of interest
+ * @return the binding for the given field access, or
+ * <code>null</code> if no binding is available
+ */
+ IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+ return null;
+ }
+
+ /**
+ * Resolves the given import declaration and returns the binding for it.
+ * <p>
+ * The implementation of <code>ImportDeclaration.resolveBinding</code>
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param importDeclaration the import declaration of interest
+ * @return the binding for the given package declaration, or
+ * the package binding (for on-demand imports) or type binding
+ * (for single-type imports), or <code>null</code> if no binding is
+ * available
+ */
+ IBinding resolveImport(ImportDeclaration importDeclaration) {
+ return null;
+ }
+
+ /**
+ * Resolves the given annotation type declaration and returns the binding
+ * for it.
+ * <p>
+ * The implementation of <code>AnnotationTypeMemberDeclaration.resolveBinding</code>
+ * forwards to this method. How the declaration resolves is often a
+ * function of the context in which the declaration node is embedded as well
+ * as the declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param member the annotation type member declaration of interest
+ * @return the binding for the given annotation type member declaration, or <code>null</code>
+ * if no binding is available
+ * @since 3.0
+ */
+ IMethodBinding resolveMember(AnnotationTypeMemberDeclaration member) {
+ return null;
+ }
+
+ /**
+ * Resolves the given method declaration and returns the binding for it.
+ * <p>
+ * The implementation of <code>MethodDeclaration.resolveBinding</code>
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method declaration node is embedded as well as
+ * the method declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param method the method or constructor declaration of interest
+ * @return the binding for the given method declaration, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveMethod(MethodDeclaration method) {
+ return null;
+ }
+
+ /**
+ * Resolves the given method invocation and returns the binding for it.
+ * <p>
+ * The implementation of <code>MethodInvocation.resolveMethodBinding</code>
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method invocation node is embedded as well as
+ * the method invocation subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param method the method invocation of interest
+ * @return the binding for the given method invocation, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveMethod(MethodInvocation method) {
+ return null;
+ }
+
+//{ObjectTeams: resolve bindings for OT-specific nodes
+
+ IMethodBinding resolveConstructor(BaseConstructorInvocation constructor)
+ {
+ return null;
+ }
+
+ IMethodBinding resolveConstructor(TSuperConstructorInvocation constructor)
+ {
+ return null;
+ }
+
+
+ IMethodBinding resolveMethod(BaseCallMessageSend method)
+ {
+ return null;
+ }
+
+
+ IMethodBinding resolveMethod(MethodSpec method)
+ {
+ return null;
+ }
+
+ IMethodBinding resolveMethod(TSuperMessageSend method)
+ {
+ return null;
+ }
+
+ IMethodMappingBinding resolveMethodMapping(AbstractMethodMappingDeclaration mapping)
+ {
+ return null;
+ }
+
+ IVariableBinding resolveVariable(FieldAccessSpec field)
+ {
+ return null;
+ }
+//mkr}
+
+ /**
+ * Resolves the given method invocation and returns the binding for it.
+ * <p>
+ * The implementation of <code>MethodInvocation.resolveMethodBinding</code>
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method invocation node is embedded as well as
+ * the method invocation subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param method the method invocation of interest
+ * @return the binding for the given method invocation, or
+ * <code>null</code> if no binding is available
+ */
+ IMethodBinding resolveMethod(SuperMethodInvocation method) {
+ return null;
+ }
+
+ /**
+ * Resolves the given name and returns the type binding for it.
+ * <p>
+ * The implementation of <code>Name.resolveBinding</code> forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param name the name of interest
+ * @return the binding for the name, or <code>null</code> if no binding is
+ * available
+ */
+ IBinding resolveName(Name name) {
+ return null;
+ }
+
+ /**
+ * Resolves the given package declaration and returns the binding for it.
+ * <p>
+ * The implementation of <code>PackageDeclaration.resolveBinding</code>
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param pkg the package declaration of interest
+ * @return the binding for the given package declaration, or
+ * <code>null</code> if no binding is available
+ */
+ IPackageBinding resolvePackage(PackageDeclaration pkg) {
+ return null;
+ }
+
+ /**
+ * Resolves the given reference and returns the binding for it.
+ * <p>
+ * The implementation of <code>MemberRef.resolveBinding</code> forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param ref the reference of interest
+ * @return the binding for the reference, or <code>null</code> if no binding is
+ * available
+ * @since 3.0
+ */
+ IBinding resolveReference(MemberRef ref) {
+ return null;
+ }
+
+ /**
+ * Resolves the given member value pair and returns the binding for it.
+ * <p>
+ * The implementation of <code>MemberValuePair.resolveMemberValuePairBinding</code> forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param memberValuePair the member value pair of interest
+ * @return the binding for the member value pair, or <code>null</code> if no binding is
+ * available
+ * @since 3.2
+ */
+ IMemberValuePairBinding resolveMemberValuePair(MemberValuePair memberValuePair) {
+ return null;
+ }
+
+ /**
+ * Resolves the given reference and returns the binding for it.
+ * <p>
+ * The implementation of <code>MethodRef.resolveBinding</code> forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param ref the reference of interest
+ * @return the binding for the reference, or <code>null</code> if no binding is
+ * available
+ * @since 3.0
+ */
+ IBinding resolveReference(MethodRef ref) {
+ return null;
+ }
+
+ /**
+ * Resolves the given annotation type declaration and returns the binding
+ * for it.
+ * <p>
+ * The implementation of <code>AnnotationTypeDeclaration.resolveBinding</code>
+ * forwards to this method. How the declaration resolves is often a
+ * function of the context in which the declaration node is embedded as well
+ * as the declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the annotation type declaration of interest
+ * @return the binding for the given annotation type declaration, or <code>null</code>
+ * if no binding is available
+ * @since 3.0
+ */
+ ITypeBinding resolveType(AnnotationTypeDeclaration type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given anonymous class declaration and returns the binding
+ * for it.
+ * <p>
+ * The implementation of <code>AnonymousClassDeclaration.resolveBinding</code>
+ * forwards to this method. How the declaration resolves is often a
+ * function of the context in which the declaration node is embedded as well
+ * as the declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the anonymous class declaration of interest
+ * @return the binding for the given class declaration, or <code>null</code>
+ * if no binding is available
+ */
+ ITypeBinding resolveType(AnonymousClassDeclaration type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given enum declaration and returns the binding
+ * for it.
+ * <p>
+ * The implementation of <code>EnumDeclaration.resolveBinding</code>
+ * forwards to this method. How the enum declaration resolves is often
+ * a function of the context in which the declaration node is embedded
+ * as well as the enum declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the enum declaration of interest
+ * @return the binding for the given enum declaration, or <code>null</code>
+ * if no binding is available
+ * @since 3.0
+ */
+ ITypeBinding resolveType(EnumDeclaration type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given type and returns the type binding for it.
+ * <p>
+ * The implementation of <code>Type.resolveBinding</code>
+ * forwards to this method. How the type resolves is often a function
+ * of the context in which the type node is embedded as well as the type
+ * subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the type of interest
+ * @return the binding for the given type, or <code>null</code>
+ * if no binding is available
+ */
+ ITypeBinding resolveType(Type type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given class or interface declaration and returns the binding
+ * for it.
+ * <p>
+ * The implementation of <code>TypeDeclaration.resolveBinding</code>
+ * (and <code>TypeDeclarationStatement.resolveBinding</code>) forwards
+ * to this method. How the type declaration resolves is often a function of
+ * the context in which the type declaration node is embedded as well as the
+ * type declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the class or interface declaration of interest
+ * @return the binding for the given type declaration, or <code>null</code>
+ * if no binding is available
+ */
+ ITypeBinding resolveType(TypeDeclaration type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given type parameter and returns the type binding for the
+ * type parameter.
+ * <p>
+ * The implementation of <code>TypeParameter.resolveBinding</code>
+ * forwards to this method. How the declaration resolves is often a
+ * function of the context in which the declaration node is embedded as well
+ * as the declaration subtree itself.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param typeParameter the type paramter of interest
+ * @return the binding for the given type parameter, or <code>null</code>
+ * if no binding is available
+ * @since 3.1
+ */
+ ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+ return null;
+ }
+
+ /**
+ * Resolves the given enum constant declaration and returns the binding for
+ * the field.
+ * <p>
+ * The implementation of <code>EnumConstantDeclaration.resolveVariable</code>
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param enumConstant the enum constant declaration of interest
+ * @return the field binding for the given enum constant declaration, or
+ * <code>null</code> if no binding is available
+ * @since 3.0
+ */
+ IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
+ return null;
+ }
+
+ /**
+ * Resolves the given variable declaration and returns the binding for it.
+ * <p>
+ * The implementation of <code>VariableDeclaration.resolveBinding</code>
+ * forwards to this method. How the variable declaration resolves is often
+ * a function of the context in which the variable declaration node is
+ * embedded as well as the variable declaration subtree itself. VariableDeclaration
+ * declarations used as local variable, formal parameter and exception
+ * variables resolve to local variable bindings; variable declarations
+ * used to declare fields resolve to field bindings.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param variable the variable declaration of interest
+ * @return the binding for the given variable declaration, or
+ * <code>null</code> if no binding is available
+ */
+ IVariableBinding resolveVariable(VariableDeclaration variable) {
+ return null;
+ }
+
+ /**
+ * Resolves the given well known type by name and returns the type binding
+ * for it.
+ * <p>
+ * The implementation of <code>AST.resolveWellKnownType</code>
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param name the name of a well known type
+ * @return the corresponding type binding, or <code>null<code> if the
+ * named type is not considered well known or if no binding can be found
+ * for it
+ */
+ ITypeBinding resolveWellKnownType(String name) {
+ return null;
+ }
+
+ /**
+ * Resolves the given annotation instance and returns the DOM representation for it.
+ * <p>
+ * The implementation of {@link Annotation#resolveAnnotationBinding()}
+ * forwards to this method.
+ * </p>
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param annotation the annotation ast node of interest
+ * @return the DOM annotation representation for the given ast node, or
+ * <code>null</code> if none is available
+ */
+ IAnnotationBinding resolveAnnotation(Annotation annotation) {
+ return null;
+ }
+
+ /**
+ * Answer an array type binding with the given type binding and the given
+ * dimensions.
+ *
+ * <p>If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+ * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+ * dimensions.</p>
+ *
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param typeBinding the given type binding
+ * @param dimensions the given dimensions
+ * @return an array type binding with the given type binding and the given
+ * dimensions
+ * @throws IllegalArgumentException if the type binding represents the <code>void</code> type binding
+ */
+ ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+ return null;
+ }
+
+ /**
+ * Returns the compilation unit scope used by this binding resolver.
+ * Returns <code>null</code> if none.
+ *
+ * @return the compilation unit scope by this resolver, or <code>null</code> if none.
+ */
+ public CompilationUnitScope scope() {
+ return null;
+ }
+
+ /**
+ * Allows the user to store information about the given old/new pair of
+ * AST nodes.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param newNode the new AST node
+ * @param oldASTNode the old AST node
+ */
+ void store(ASTNode newNode, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Allows the user to update information about the given old/new pair of
+ * AST nodes.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the old AST node
+ * @param newNode the new AST node
+ */
+ void updateKey(ASTNode node, ASTNode newNode) {
+ // default implementation: do nothing
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java
new file mode 100644
index 000000000..23c429af4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Block.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block statement AST node type.
+ *
+ * <pre>
+ * Block:
+ * <b>{</b> { Statement } <b>}</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Block extends Statement {
+
+ /**
+ * The "statements" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(Block.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(Block.class, properyList);
+ addProperty(STATEMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of statements (element type: <code>Statement</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList statements =
+ new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented block node owned by the given AST.
+ * By default, the block is empty.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Block(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == STATEMENTS_PROPERTY) {
+ return statements();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BLOCK;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Block result = new Block(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.statements().addAll(
+ ASTNode.copySubtrees(target, statements()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.statements);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live list of statements in this block. Adding and
+ * removing nodes from this list affects this node dynamically.
+ * All nodes in this list must be <code>Statement</code>s;
+ * attempts to add any other type of node will trigger an
+ * exception.
+ *
+ * @return the live list of statements in this block
+ * (element type: <code>Statement</code>)
+ */
+ public List statements() {
+ return this.statements;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.statements.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java
new file mode 100644
index 000000000..88d89866d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BlockComment.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block comment AST node type.
+ * <p>
+ * Block comments (also called "traditional" comments in JLS 3.7)
+ * begin with "/&#42;", may contain line breaks, and must end
+ * with "&#42;/". Following the definition in the JLS (first edition
+ * but not second edition), block comment normally exclude comments
+ * that begin with "/&#42;#42;", which are instead classified as doc
+ * comments ({@link Javadoc}).
+ * </p>
+ * <p>
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ * </p>
+ *
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class BlockComment extends Comment {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(1);
+ createPropertyList(BlockComment.class, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new block comment node owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ BlockComment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BLOCK_COMMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BlockComment result = new BlockComment(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
new file mode 100644
index 000000000..6ac9d9c22
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract base class of all AST nodes that represent body declarations
+ * that may appear in the body of some kind of class or interface declaration,
+ * including anonymous class declarations, enumeration declarations, and
+ * enumeration constant declarations.
+ * <p>
+ * For JLS2:
+ * <pre>
+ * BodyDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * MethodDeclaration
+ * ConstructorDeclaration
+ * FieldDeclaration
+ * Initializer
+ * </pre>
+ * For JLS3, a number of new node types were introduced:
+ * <pre>
+ * BodyDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * EnumDeclaration
+ * MethodDeclaration
+ * ConstructorDeclaration
+ * FieldDeclaration
+ * Initializer
+ * EnumConstantDeclaration
+ * AnnotationTypeDeclaration
+ * AnnotationTypeMemberDeclaration
+ * </pre>
+ * </p>
+ * <p>
+ * All types of body declarations carry modifiers (and annotations), although they differ in
+ * which modifiers are allowed. Most types of body declarations can carry a
+ * doc comment; Initializer is the only ones that does not. The source range
+ * for body declarations always includes the doc comment if present.
+ * </p>
+ *
+ * @since 2.0
+ */
+public abstract class BodyDeclaration extends ASTNode {
+
+ /**
+ * The doc comment, or <code>null</code> if none.
+ * Defaults to none.
+ */
+ Javadoc optionalDocComment = null;
+
+ /**
+ * The modifier flags; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ * @since 3.0 - field was moved up from subclasses
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The extended modifiers (element type: <code>IExtendedModifier</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ * @since 3.0
+ */
+ ASTNode.NodeList modifiers = null;
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node as used in JLS2.
+ *
+ * @return the property descriptor
+ */
+ abstract SimplePropertyDescriptor internalModifiersProperty();
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node as used in JLS3.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildListPropertyDescriptor internalModifiers2Property();
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node as used in JLS3.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildListPropertyDescriptor getModifiersProperty() {
+ // important: return property for AST.JLS3
+ return internalModifiers2Property();
+ }
+
+ /**
+ * Returns structural property descriptor for the "javadoc" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalJavadocProperty();
+
+ /**
+ * Returns structural property descriptor for the "javadoc" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildPropertyDescriptor getJavadocProperty() {
+ return internalJavadocProperty();
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "javadoc" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalJavadocPropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "modifiers" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final SimplePropertyDescriptor internalModifiersPropertyFactory(Class nodeClass) {
+ return new SimplePropertyDescriptor(nodeClass, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "modifiers" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildListPropertyDescriptor internalModifiers2PropertyFactory(Class nodeClass) {
+ return new ChildListPropertyDescriptor(nodeClass, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new AST node for a body declaration node owned by the
+ * given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ BodyDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(internalModifiers2Property());
+ }
+ }
+
+ /**
+ * Returns the doc comment node.
+ *
+ * @return the doc comment node, or <code>null</code> if none
+ */
+ public Javadoc getJavadoc() {
+ return this.optionalDocComment;
+ }
+
+ /**
+ * Sets or clears the doc comment node.
+ *
+ * @param docComment the doc comment node, or <code>null</code> if none
+ * @exception IllegalArgumentException if the doc comment string is invalid
+ */
+ public void setJavadoc(Javadoc docComment) {
+ ChildPropertyDescriptor p = internalJavadocProperty();
+ ASTNode oldChild = this.optionalDocComment;
+ preReplaceChild(oldChild, docComment, p);
+ this.optionalDocComment = docComment;
+ postReplaceChild(oldChild, docComment, p);
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ * <p>
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from <code>modifiers()</code>.
+ * </p>
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenience method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedmodifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedmodifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedmodifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ // more efficient than just calling supportedOnlyIn2() to check
+ if (this.modifiers != null) {
+ supportedOnlyIn2();
+ }
+ SimplePropertyDescriptor p = internalModifiersProperty();
+ preValueChange(p);
+ this.modifierFlags = pmodifiers;
+ postValueChange(p);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: <code>IExtendedModifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java
new file mode 100644
index 000000000..f9da563a9
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BooleanLiteral.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Boolean literal node.
+ *
+ * <pre>
+ * BooleanLiteral:
+ * <b>true</b>
+ * <b>false</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class BooleanLiteral extends Expression {
+
+ /**
+ * The "booleanValue" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor BOOLEAN_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(BooleanLiteral.class, "booleanValue", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(BooleanLiteral.class, properyList);
+ addProperty(BOOLEAN_VALUE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The boolean; defaults to the literal for <code>false</code>.
+ */
+ private boolean value = false;
+
+ /**
+ * Creates a new unparented boolean literal node owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ BooleanLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean newValue) {
+ if (property == BOOLEAN_VALUE_PROPERTY) {
+ if (get) {
+ return booleanValue();
+ } else {
+ setBooleanValue(newValue);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, newValue);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BOOLEAN_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BooleanLiteral result = new BooleanLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setBooleanValue(booleanValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the boolean value of this boolean literal node.
+ *
+ * @return <code>true</code> for the boolean literal spelled
+ * <code>"true"</code>, and <code>false</code> for the boolean literal
+ * spelled <code>"false"</code>.
+ */
+ public boolean booleanValue() {
+ return this.value;
+ }
+
+ /**
+ * Sets the boolean value of this boolean literal node.
+ *
+ * @param value <code>true</code> for the boolean literal spelled
+ * <code>"true"</code>, and <code>false</code> for the boolean literal
+ * spelled <code>"false"</code>.
+ */
+ public void setBooleanValue(boolean value) {
+ preValueChange(BOOLEAN_VALUE_PROPERTY);
+ this.value = value;
+ postValueChange(BOOLEAN_VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
new file mode 100644
index 000000000..0086aa565
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Break statement AST node type.
+ *
+ * <pre>
+ * BreakStatement:
+ * <b>break</b> [ Identifier ] <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class BreakStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(BreakStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(BreakStatement.class, properyList);
+ addProperty(LABEL_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label, or <code>null</code> if none; none by default.
+ */
+ private SimpleName optionalLabel = null;
+
+ /**
+ * Creates a new unparented break statement node owned by the given
+ * AST. By default, the break statement has no label.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ BreakStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BREAK_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BreakStatement result = new BreakStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getLabel());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this break statement, or <code>null</code> if
+ * there is none.
+ *
+ * @return the label, or <code>null</code> if there is none
+ */
+ public SimpleName getLabel() {
+ return this.optionalLabel;
+ }
+
+ /**
+ * Sets or clears the label of this break statement.
+ *
+ * @param label the label, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setLabel(SimpleName label) {
+ ASTNode oldChild = this.optionalLabel;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.optionalLabel = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalLabel == null ? 0 : getLabel().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CallinMappingDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CallinMappingDeclaration.java
new file mode 100644
index 000000000..d291e278c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CallinMappingDeclaration.java
@@ -0,0 +1,523 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: CallinMappingDeclaration.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * NEW for OTDT
+ *
+ * Represents a callin binding of a role method with one ore more base methods (OTJLD §4).
+ * Callin bindings must have one modifier (before, replace, after)
+ * and may have parameter mappings. A replace callin may also have a result mapping.
+ * e.g.:
+ *
+ * ranges from:
+ * <code>roleMethod <- after baseMethod;</code>
+ * to:
+ * <pre>
+ * void roleMethod(MyObject obj) <-
+ * after char[] baseMethod(String name, SomeClass cls) with
+ * {
+ * obj <- cls.foo(),
+ * }
+ * </pre>
+ * or:
+ * <pre>
+ * char[] roleMethod(MyObject obj) <-
+ * replace char[] baseMethod(MyObject o, String name) with
+ * {
+ * obj <- o,
+ * result <- result
+ * }
+ * </pre>
+ *
+ * Callin bindings consist of
+ * <ol>
+ * <li> a name as mentioned in source code or a generated name "&lt;File:Line,Col&gt;".
+ * <li> role_method_designator "<-" callin_modifier base_method_designator;
+ * <ol>
+ * <li> method designators may or may not contain parameters lists and return type
+ * but no modifiers (see §3.1(c)).
+ * <li> callin_modifiers are replace, before, after.
+ * </ol>
+ * <li> Parameter mappings
+ * <ol>
+ * <li> result mapping (only replace)
+ * </ol>
+ * </ol>
+ *
+ * Callin bindinds can be used in the following AST-nodes:
+ * TypeDeclaration (compiler ast)
+ * RoleTypeDeclaration (dom/ast)
+ *
+ * @author mkr
+ */
+public class CallinMappingDeclaration extends AbstractMethodMappingDeclaration
+{
+ public static final String CALLIN = "<-"; //$NON-NLS-1$
+
+ /**
+ * Creates a new AST node for a callin mapping declaration owned
+ * by the given AST. By default, the declaration is for a callin mapping
+ * of an unspecified, but legal, name;
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CallinMappingDeclaration(AST ast)
+ {
+ super(ast);
+ }
+
+ /**
+ * The "names" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(CallinMappingDeclaration.class, "name", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(CallinMappingDeclaration.class);
+
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(CallinMappingDeclaration.class);
+
+ /**
+ * The "roleMappingElement" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ROLE_MAPPING_ELEMENT_PROPERTY =
+ new ChildPropertyDescriptor(CallinMappingDeclaration.class, "roleMappingElement", MethodMappingElement.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The binding operator structural property ("<- modifier")
+ * @since 1.3.1
+ */
+ public static final ChildPropertyDescriptor BINDING_OPERATOR_PROPERTY =
+ new ChildPropertyDescriptor(CallinMappingDeclaration.class, "bindingOperator", MethodBindingOperator.class, MANDATORY, NO_CYCLE_RISK);
+
+ /**
+ * The "baseMappingElements" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor BASE_MAPPING_ELEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(CallinMappingDeclaration.class, "baseMappingElements", MethodMappingElement.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "guardPredicate" structural property of this node type.
+ * @since 0.9.25
+ */
+ public static final ChildPropertyDescriptor GUARD_PROPERTY =
+ new ChildPropertyDescriptor(CallinMappingDeclaration.class, "guardPredicate", GuardPredicateDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "parameter mappings" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor PARAMETER_MAPPINGS_PROPERTY =
+ internalParameterMappingPropertyFactory(CallinMappingDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ private SimpleName _labelName = null;
+
+ private MethodMappingElement _roleMappingElement = null; // FIXME(SH): should be MethodSpec??
+ ASTNode.NodeList _baseMappingElements = new ASTNode.NodeList(BASE_MAPPING_ELEMENTS_PROPERTY);
+
+ GuardPredicateDeclaration _optionalGuardPredicate = null;
+
+ static
+ {
+ List propertyList = new ArrayList(7);
+ createPropertyList(CallinMappingDeclaration.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(ROLE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(BINDING_OPERATOR_PROPERTY, propertyList);
+ addProperty(BASE_MAPPING_ELEMENTS_PROPERTY, propertyList);
+ addProperty(PARAMETER_MAPPINGS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(9);
+ createPropertyList(CallinMappingDeclaration.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList); // for annotations
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(ROLE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(BINDING_OPERATOR_PROPERTY, propertyList);
+ addProperty(BASE_MAPPING_ELEMENTS_PROPERTY, propertyList);
+ addProperty(GUARD_PROPERTY, propertyList);
+ addProperty(PARAMETER_MAPPINGS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ if(apiLevel == AST.JLS3)
+ return PROPERTY_DESCRIPTORS_3_0;
+ else
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+
+ final SimplePropertyDescriptor internalModifiersProperty()
+ {
+ throw new UnsupportedOperationException("JLS2 not supported"); //$NON-NLS-1$
+ }
+
+ final ChildListPropertyDescriptor internalModifiers2Property()
+ {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalGetRoleElementProperty() {
+ return ROLE_MAPPING_ELEMENT_PROPERTY;
+ }
+
+ protected ChildPropertyDescriptor internalGetBindingOperatorProperty() {
+ return BINDING_OPERATOR_PROPERTY;
+ }
+
+ final ChildListPropertyDescriptor internalParameterMappingsProperty()
+ {
+ return PARAMETER_MAPPINGS_PROPERTY;
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == JAVADOC_PROPERTY)
+ {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName)child);
+ return null;
+ }
+ }
+ // name is not a child (SimpleName) but a direct String property
+ // callin modifier is not a child either but a direct int property
+ if (property == ROLE_MAPPING_ELEMENT_PROPERTY)
+ {
+ if (get) {
+ return getRoleMappingElement();
+ } else {
+ setRoleMappingElement((MethodSpec) child);
+ return null;
+ }
+ }
+ if (property == GUARD_PROPERTY)
+ {
+ if (get) {
+ return getGuardPredicate();
+ } else {
+ setGuardPredicate((GuardPredicateDeclaration) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error (incl. handling of elements common to all method mappings):
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if(property == MODIFIERS2_PROPERTY)
+ return modifiers();
+
+ if (property == BASE_MAPPING_ELEMENTS_PROPERTY)
+ return getBaseMappingElements();
+
+ if (property == PARAMETER_MAPPINGS_PROPERTY)
+ return getParameterMappings();
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ ChildPropertyDescriptor internalJavadocProperty()
+ {
+ return JAVADOC_PROPERTY;
+ }
+
+ List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ int getNodeType0()
+ {
+ return CALLIN_MAPPING_DECLARATION;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ CallinMappingDeclaration result = new CallinMappingDeclaration(target);
+ result.setName(this.getName());
+ if (this.ast.apiLevel >= AST.JLS3)
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); // annotations
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.setRoleMappingElement(
+ (MethodSpec) ASTNode.copySubtree(target, getRoleMappingElement()));
+ result.setBindingOperator((MethodBindingOperator)bindingOperator().clone(target));
+ result.getBaseMappingElements().addAll(
+ ASTNode.copySubtrees(target, getBaseMappingElements()));
+ result.setGuardPredicate((GuardPredicateDeclaration)ASTNode.copySubtree(target, getGuardPredicate()));
+ result.getParameterMappings().addAll(
+ ASTNode.copySubtrees(target, getParameterMappings()));
+ return result;
+ }
+
+
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ acceptChild(visitor, _labelName);
+ acceptChild(visitor, _roleMappingElement);
+ if (this.ast.apiLevel >= AST.JLS3)
+ acceptChildren(visitor, modifiers);
+ acceptChild(visitor, bindingOperator);
+ acceptChildren(visitor, _baseMappingElements);
+ acceptChild(visitor, this.getGuardPredicate());
+ acceptChildren(visitor, _parameterMappings);
+ }
+ visitor.endVisit(this);
+ }
+
+ void appendDebugString(StringBuffer buffer) {
+ if (getName() != null) {
+ buffer.append(getName().getIdentifier());
+ buffer.append(':');
+ }
+ super.appendDebugString(buffer);
+ }
+
+ int treeSize()
+ {
+ return memSize() + (super.optionalDocComment == null
+ ? 0
+ : getJavadoc().treeSize());
+ }
+
+ /**
+ * Returns the method spec left of the callin arrow.
+ * @return the left method spec, i.e. the declaring role method
+ */
+ @Override
+ public MethodMappingElement getRoleMappingElement()
+ {
+ if (_roleMappingElement == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_roleMappingElement == null)
+ {
+ preLazyInit();
+ _roleMappingElement = new MethodSpec(this.ast);
+ postLazyInit(_roleMappingElement, ROLE_MAPPING_ELEMENT_PROPERTY);
+ }
+ }
+ }
+ return _roleMappingElement;
+ }
+
+ /**
+ * Sets the left method spec (role method spec) declared in this callin
+ * mapping declaration to the given method spec.
+ *
+ * @param roleMappingElement
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setRoleMappingElement(MethodMappingElement roleMappingElement)
+ {
+ if (roleMappingElement == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = _roleMappingElement;
+ preReplaceChild(oldChild, roleMappingElement, ROLE_MAPPING_ELEMENT_PROPERTY);
+ _roleMappingElement = roleMappingElement;
+ postReplaceChild(oldChild, roleMappingElement, ROLE_MAPPING_ELEMENT_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of base method specs for this
+ * callin mapping declaration.
+ *
+ * @return the live list of base method specs
+ * (element type: <code>IExtendedModifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public List getBaseMappingElements()
+ {
+ return _baseMappingElements;
+ }
+
+ /**
+ * Returns the callin modifiers explicitly specified on this declaration.
+ *
+ * @return exactly one of before, after, replace using constants from Modifier
+ * @see Modifier
+ */
+ public int getCallinModifier()
+ {
+ return bindingOperator.getBindingModifier();
+ }
+
+ /**
+ * Sets the callin modifier explicitly specified on this declaration.
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @see Modifier
+ * @deprecated use setBindingOperator instead
+ */
+ public void setCallinModifier(int modifiers)
+ {
+ setCallinModifier(this.ast.newModifier(Modifier.ModifierKeyword.fromFlagValue(modifiers)));
+ }
+
+ /**
+ * @deprecated use setBindingOperator
+ */
+ public void setCallinModifier(Modifier modifier) {
+ if (this.bindingOperator == null) {
+ MethodBindingOperator op = new MethodBindingOperator(this.ast);
+ op.setBindingKind(MethodBindingOperator.KIND_CALLIN);
+ op.setBindingModifier(modifier);
+ this.setBindingOperator(op);
+ } else {
+ this.bindingOperator.setBindingModifier(modifier);
+ }
+ }
+
+ /**
+ * Returns the callin modifier for this callin mapping declaration.
+ *
+ * @see Modifier
+ * @return one of before, after, replace
+ */
+ public Modifier callinModifier()
+ {
+ return this.bindingOperator.bindingModifier();
+ }
+
+ public boolean hasName() {
+ return _labelName != null && _labelName.getIdentifier().charAt(0) != '<';
+ }
+ public void setName(SimpleName name)
+ {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this._labelName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this._labelName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+
+ }
+
+ public SimpleName getName() {
+ return this._labelName;
+ }
+
+ public void setGuardPredicate(GuardPredicateDeclaration predicate) {
+ ASTNode oldChild = this._optionalGuardPredicate;
+ preReplaceChild(oldChild, predicate, GUARD_PROPERTY);
+ this._optionalGuardPredicate = predicate;
+ postReplaceChild(oldChild, predicate, GUARD_PROPERTY);
+ }
+
+ public GuardPredicateDeclaration getGuardPredicate() {
+ return _optionalGuardPredicate;
+ }
+
+ /**
+ * Return whether a static base method is bound such that
+ * no instance will be passed through this binding
+ * (one static base method suffices to determine staticness).
+ */
+ public boolean isStatic() {
+ for (Object baseElem : this.getBaseMappingElements()) {
+ IMethodBinding baseMethod = ((MethodSpec)baseElem).resolveBinding();
+ if (baseMethod != null && Modifier.isStatic(baseMethod.getModifiers()))
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CalloutMappingDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CalloutMappingDeclaration.java
new file mode 100644
index 000000000..9bf8f86bf
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CalloutMappingDeclaration.java
@@ -0,0 +1,427 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: CalloutMappingDeclaration.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT
+ *
+ * Represents DOM-ASTNode for Callout Bindings (OTJLD §2.4.2),
+ * which has to handle code from e.g. :
+ * foo => bar;
+ * to e.g. :
+ * Integer absoluteValue(Integer integer) -> int abs(int i) with {
+ * integer.intValue() -> i,
+ * result <- new Integer(result)
+ * }
+ * and also the callout to field binding:
+ * - without value mapping:
+ *
+ * setValue -> set value;
+ *
+ * int getValue() -> get int value;
+ *
+ * - with value mappings:
+ *
+ * Integer getValue() -> get int val
+ * with { result <- new Integer(result) }
+ *
+ * void setValue(Integer i) -> set int val
+ * with { integer.intValue() -> val }
+ *
+ *
+ * This class consists of one MethodSpec for bound role method and one MethodSpec for base method
+ * or FieldAccessSpec for access to a field of the base class. Also it consists of
+ * a callout kind and an optionally mapping of parameters.
+ *
+ * This node is used in TypeDeclaration, particulary in RoleTypeDeclaration.
+ *
+ * @author ike
+ */
+public class CalloutMappingDeclaration extends AbstractMethodMappingDeclaration
+{
+ public static final String CALLOUT = "->"; //$NON-NLS-1$
+ public static final String CALLOUT_OVERRIDE = "=>"; //$NON-NLS-1$
+
+ /**
+ * Creates a new AST node for a callout mapping declaration owned
+ * by the given AST. By default, the declaration is for a callout mapping
+ * of an unspecified, but legal, name;
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CalloutMappingDeclaration(AST ast)
+ {
+ super(ast);
+ }
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(CalloutMappingDeclaration.class);
+
+ /**
+ * The left "methodSpec" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ROLE_MAPPING_ELEMENT_PROPERTY =
+ new ChildPropertyDescriptor(CalloutMappingDeclaration.class, "roleMappingElement", MethodMappingElement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The binding operator structural property ("<- modifier")
+ * @since 1.3.1
+ */
+ public static final ChildPropertyDescriptor BINDING_OPERATOR_PROPERTY =
+ new ChildPropertyDescriptor(CalloutMappingDeclaration.class, "bindingOperator", MethodBindingOperator.class, MANDATORY, NO_CYCLE_RISK);
+
+ /**
+ * The right "methodSpec" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BASE_MAPPING_ELEMENT_PROPERTY =
+ new ChildPropertyDescriptor(CalloutMappingDeclaration.class, "baseMappingElement", MethodMappingElement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "signature" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor SIGNATURE_PROPERTY =
+ new SimplePropertyDescriptor(CalloutMappingDeclaration.class, "signature", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "parameterMappings" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor PARAMETER_MAPPINGS_PROPERTY =
+ internalParameterMappingPropertyFactory(CalloutMappingDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(CalloutMappingDeclaration.class);
+
+ /**
+ * The "modifiers2" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(CalloutMappingDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ private MethodMappingElement _baseMappingElement = null;
+ private boolean _baseMappingInitialized= false;
+ private boolean _hasSignature = false;
+
+ static
+ {
+ List propertyList = new ArrayList(8);
+ createPropertyList(CalloutMappingDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(ROLE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(BINDING_OPERATOR_PROPERTY, propertyList);
+ addProperty(BASE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(PARAMETER_MAPPINGS_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(8);
+ createPropertyList(CalloutMappingDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(ROLE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(BINDING_OPERATOR_PROPERTY, propertyList);
+ addProperty(BASE_MAPPING_ELEMENT_PROPERTY, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(PARAMETER_MAPPINGS_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ if(apiLevel == AST.JLS3)
+ return PROPERTY_DESCRIPTORS_3_0;
+ else
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+
+ final SimplePropertyDescriptor internalModifiersProperty()
+ {
+ return MODIFIERS_PROPERTY;
+ }
+
+ final ChildListPropertyDescriptor internalModifiers2Property()
+ {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ final ChildListPropertyDescriptor internalParameterMappingsProperty()
+ {
+ return PARAMETER_MAPPINGS_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalJavadocProperty()
+ {
+ return JAVADOC_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalGetRoleElementProperty() {
+ return ROLE_MAPPING_ELEMENT_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalGetBindingOperatorProperty() {
+ return BINDING_OPERATOR_PROPERTY;
+ }
+
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean isGetRequest, int value)
+ {
+ if (property == MODIFIERS_PROPERTY)
+ {
+ if (isGetRequest)
+ {
+ return getModifiers();
+ }
+ else
+ {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, isGetRequest, value);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean isGet, ASTNode child)
+ {
+ if (property == JAVADOC_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getJavadoc();
+ }
+ else
+ {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+
+ if (property == BASE_MAPPING_ELEMENT_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getBaseMappingElement();
+ }
+ else
+ {
+ setBaseMappingElement((MethodSpec) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error (incl. handling of elements common to all method mappings):
+ return super.internalGetSetChildProperty(property, isGet, child);
+ }
+
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)
+ {
+ if (property == SIGNATURE_PROPERTY)
+ {
+ if (get)
+ {
+ return hasSignature();
+ }
+ else
+ {
+ setSignatureFlag(value);
+ return false;
+ }
+ }
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == PARAMETER_MAPPINGS_PROPERTY)
+ {
+ return getParameterMappings();
+ }
+ if (property == MODIFIERS2_PROPERTY)
+ {
+ return modifiers();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ int getNodeType0()
+ {
+ return CALLOUT_MAPPING_DECLARATION;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ CalloutMappingDeclaration result = new CalloutMappingDeclaration(target);
+ if (this.ast.apiLevel >= AST.JLS3)
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); // annotations
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.setRoleMappingElement(
+ (MethodMappingElement) ASTNode.copySubtree(target, getRoleMappingElement()));
+ result.setBindingOperator((MethodBindingOperator)bindingOperator().clone(target));
+ result.setBaseMappingElement(
+ (MethodMappingElement) ASTNode.copySubtree(target, getBaseMappingElement()));
+ result.setSignatureFlag(this.hasSignature());
+ result.getParameterMappings().addAll(
+ ASTNode.copySubtrees(target, this.getParameterMappings()));
+
+ return result;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel >= AST.JLS3)
+ acceptChildren(visitor, modifiers);
+ acceptChild(visitor, roleMappingElement);
+ acceptChild(visitor, bindingOperator);
+ acceptChild(visitor, _baseMappingElement);
+ acceptChildren(visitor,_parameterMappings);
+ }
+ visitor.endVisit(this);
+ }
+
+ int treeSize()
+ {
+ return memSize() + (super.optionalDocComment == null
+ ? 0
+ : getJavadoc().treeSize());
+ }
+
+ /**
+ * Returns the method spec right of the callout arrow.
+ * @return the right method spec, i.e. the referenced base method
+ * @see Modifier
+ */
+ public MethodMappingElement getBaseMappingElement()
+ {
+ if (_baseMappingElement == null && !this._baseMappingInitialized)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_baseMappingElement == null)
+ {
+ preLazyInit();
+ _baseMappingElement = new MethodSpec(this.ast);
+ this._baseMappingInitialized= true;
+ postLazyInit(_baseMappingElement, BASE_MAPPING_ELEMENT_PROPERTY);
+ }
+ }
+ }
+ return _baseMappingElement;
+ }
+
+ /**
+ * Sets the right method spec (base method spec) declared in this callout
+ * mapping declaration to the given method spec.
+ *
+ * @param baseMappingElement
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setBaseMappingElement(MethodMappingElement baseMappingElement)
+ {
+ this._baseMappingInitialized= true;
+ ASTNode oldChild = _baseMappingElement;
+ preReplaceChild(oldChild, baseMappingElement, BASE_MAPPING_ELEMENT_PROPERTY);
+ _baseMappingElement = baseMappingElement;
+ postReplaceChild(oldChild, baseMappingElement, BASE_MAPPING_ELEMENT_PROPERTY);
+ }
+
+ /**
+ *
+ * @return the flag, whether callout is a callout override or a simple callout
+ * true, if an override;
+ */
+ public boolean isCalloutOverride()
+ {
+ return this.bindingOperator().getBindingKind() == MethodBindingOperator.KIND_CALLOUT_OVERRIDE;
+ }
+
+ public boolean hasSignature()
+ {
+ return _hasSignature;
+ }
+
+ public void setSignatureFlag(boolean hasSignature)
+ {
+ preValueChange(SIGNATURE_PROPERTY);
+ _hasSignature = hasSignature;
+ postValueChange(SIGNATURE_PROPERTY);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java
new file mode 100644
index 000000000..6e1f5485e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CastExpression.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Cast expression AST node type.
+ *
+ * <pre>
+ * CastExpression:
+ * <b>(</b> Type <b>)</b> Expression
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CastExpression extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(CastExpression.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(CastExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(CastExpression.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new AST node for a cast expression owned by the given
+ * AST. By default, the type and expression are unspecified (but legal).
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CastExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CAST_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CastExpression result = new CastExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setType((Type) getType().clone(target));
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type in this cast expression.
+ *
+ * @return the type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type in this cast expression to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the expression of this cast expression.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this cast expression.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.type == null ? 0 : getType().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java
new file mode 100644
index 000000000..e9a312f41
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CatchClause.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Catch clause AST node type.
+ *
+ * <pre>
+ * CatchClause:
+ * <b>catch</b> <b>(</b> FormalParameter <b>)</b> Block
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CatchClause extends ASTNode {
+
+ /**
+ * The "exception" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXCEPTION_PROPERTY =
+ new ChildPropertyDescriptor(CatchClause.class, "exception", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(CatchClause.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(CatchClause.class, properyList);
+ addProperty(EXCEPTION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * The exception variable declaration; lazily initialized; defaults to a
+ * unspecified, but legal, variable declaration.
+ */
+ private SingleVariableDeclaration exceptionDecl = null;
+
+ /**
+ * Creates a new AST node for a catch clause owned by the given
+ * AST. By default, the catch clause declares an unspecified, but legal,
+ * exception declaration and has an empty block.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CatchClause(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXCEPTION_PROPERTY) {
+ if (get) {
+ return getException();
+ } else {
+ setException((SingleVariableDeclaration) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CATCH_CLAUSE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CatchClause result = new CatchClause(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setBody((Block) getBody().clone(target));
+ result.setException(
+ (SingleVariableDeclaration) ASTNode.copySubtree(target, getException()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getException());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the exception variable declaration of this catch clause.
+ *
+ * @return the exception variable declaration node
+ */
+ public SingleVariableDeclaration getException() {
+ if (this.exceptionDecl == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.exceptionDecl == null) {
+ preLazyInit();
+ this.exceptionDecl = new SingleVariableDeclaration(this.ast);
+ postLazyInit(this.exceptionDecl, EXCEPTION_PROPERTY);
+ }
+ }
+ }
+ return this.exceptionDecl;
+ }
+
+ /**
+ * Sets the variable declaration of this catch clause.
+ *
+ * @param exception the exception variable declaration node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setException(SingleVariableDeclaration exception) {
+ if (exception == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.exceptionDecl;
+ preReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+ this.exceptionDecl= exception;
+ postReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this catch clause.
+ *
+ * @return the catch clause body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this catch clause.
+ *
+ * @param body the catch clause block node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.exceptionDecl == null ? 0 : getException().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
new file mode 100644
index 000000000..ebf8c9b71
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
@@ -0,0 +1,389 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Character literal nodes.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CharacterLiteral extends Expression {
+
+ /**
+ * The "escapedValue" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(CharacterLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(CharacterLiteral.class, properyList);
+ addProperty(ESCAPED_VALUE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The literal string, including quotes and escapes; defaults to the
+ * literal for the character 'X'.
+ */
+ private String escapedValue = "\'X\'";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented character literal node owned by the given AST.
+ * By default, the character literal denotes an unspecified character.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CharacterLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == ESCAPED_VALUE_PROPERTY) {
+ if (get) {
+ return getEscapedValue();
+ } else {
+ setEscapedValue((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CHARACTER_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CharacterLiteral result = new CharacterLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setEscapedValue(getEscapedValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes.
+ *
+ * @return the escaped string value, including enclosing single quotes
+ * and embedded escapes
+ */
+ public String getEscapedValue() {
+ return this.escapedValue;
+ }
+
+ /**
+ * Sets the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes. For example,
+ * <ul>
+ * <li><code>'a'</code> <code>setEscapedValue("\'a\'")</code></li>
+ * <li><code>'\n'</code> <code>setEscapedValue("\'\\n\'")</code></li>
+ * </ul>
+ *
+ * @param value the string value, including enclosing single quotes
+ * and embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setEscapedValue(String value) {
+ // check setInternalEscapedValue(String) if this method is changed
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = value.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameCharacterLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = value;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+ */
+ void internalSetEscapedValue(String value) {
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = value;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /**
+ * Returns the value of this literal node.
+ * <p>
+ * For example,
+ * <pre>
+ * CharacterLiteral s;
+ * s.setEscapedValue("\'x\'");
+ * assert s.charValue() == 'x';
+ * </pre>
+ * </p>
+ *
+ * @return the character value without enclosing quotes and embedded
+ * escapes
+ * @exception IllegalArgumentException if the literal value cannot be converted
+ */
+ public char charValue() {
+ Scanner scanner = this.ast.scanner;
+ char[] source = this.escapedValue.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ int firstChar = scanner.getNextChar();
+ int secondChar = scanner.getNextChar();
+
+ if (firstChar == -1 || firstChar != '\'') {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ char value = (char) secondChar;
+ int nextChar = scanner.getNextChar();
+ if (secondChar == '\\') {
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ switch(nextChar) {
+ case 'b' :
+ value = '\b';
+ break;
+ case 't' :
+ value = '\t';
+ break;
+ case 'n' :
+ value = '\n';
+ break;
+ case 'f' :
+ value = '\f';
+ break;
+ case 'r' :
+ value = '\r';
+ break;
+ case '\"':
+ value = '\"';
+ break;
+ case '\'':
+ value = '\'';
+ break;
+ case '\\':
+ value = '\\';
+ break;
+ default : //octal (well-formed: ended by a ' )
+ try {
+ if (ScannerHelper.isDigit((char) nextChar)) {
+ int number = ScannerHelper.getNumericValue((char) nextChar);
+ nextChar = scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ if (nextChar != '\'') {
+ if (!ScannerHelper.isDigit((char) nextChar)) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ number = (number * 8) + ScannerHelper.getNumericValue((char) nextChar);
+ nextChar = scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ if (nextChar != '\'') {
+ if (!ScannerHelper.isDigit((char) nextChar)) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ number = (number * 8) + ScannerHelper.getNumericValue((char) nextChar);
+ }
+ }
+ return (char) number;
+ } else {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ }
+ nextChar = scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ }
+ if (nextChar == -1 || nextChar != '\'') {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ return value;
+ }
+ /**
+ * Sets the value of this character literal node to the given character.
+ * <p>
+ * For example,
+ * <pre>
+ * CharacterLiteral s;
+ * s.setCharValue('x');
+ * assert s.charValue() == 'x';
+ * assert s.getEscapedValue().equals("\'x\'");
+ * </pre>
+ * </p>
+ *
+ * @param value the character value
+ */
+ public void setCharValue(char value) {
+ StringBuffer b = new StringBuffer(3);
+
+ b.append('\''); // opening delimiter
+ switch(value) {
+ case '\b' :
+ b.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ b.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ b.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ b.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ b.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"':
+ b.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ b.append("\\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ b.append("\\\\"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ b.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ b.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ b.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ b.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ b.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ b.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ b.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ b.append("\\7"); //$NON-NLS-1$
+ break;
+ default:
+ b.append(value);
+ }
+ b.append('\''); // closing delimiter
+ setEscapedValue(b.toString());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(this.escapedValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildListPropertyDescriptor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildListPropertyDescriptor.java
new file mode 100644
index 000000000..b55cfe972
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildListPropertyDescriptor.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Descriptor for a child list property of an AST node.
+ * A child list property is one whose value is a list of
+ * {@link ASTNode}.
+ *
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class ChildListPropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Element type. For example, for a node type like
+ * CompilationUnit, the "imports" property is ImportDeclaration.class.
+ * <p>
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ * </p>
+ */
+ final Class elementType;
+
+ /**
+ * Indicates whether a cycle is possible.
+ * <p>
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ * </p>
+ */
+ final boolean cycleRisk;
+
+ /**
+ * Creates a new child list property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param elementType the element type of this property
+ * @param cycleRisk <code>true</code> if this property is at
+ * risk of cycles, and <code>false</code> if there is no worry about cycles
+ */
+ ChildListPropertyDescriptor(Class nodeClass, String propertyId, Class elementType, boolean cycleRisk) {
+ super(nodeClass, propertyId);
+ if (elementType == null) {
+ throw new IllegalArgumentException();
+ }
+ this.elementType = elementType;
+ this.cycleRisk = cycleRisk;
+ }
+
+ /**
+ * Returns the element type of this list property.
+ * <p>
+ * For example, for a node type like CompilationUnit,
+ * the "imports" property returns <code>ImportDeclaration.class</code>.
+ * </p>
+ *
+ * @return the element type of the property
+ */
+ public final Class getElementType() {
+ return this.elementType;
+ }
+
+ /**
+ * Returns whether this property is vulnerable to cycles.
+ * <p>
+ * A property is vulnerable to cycles if a node of the owning
+ * type (that is, the type that owns this property) could legally
+ * appear in the AST subtree below this property. For example,
+ * the body property of a
+ * {@link MethodDeclaration} node
+ * admits a body which might include statement that embeds
+ * another {@link MethodDeclaration} node.
+ * On the other hand, the name property of a
+ * MethodDeclaration node admits only names, and thereby excludes
+ * another MethodDeclaration node.
+ * </p>
+ *
+ * @return <code>true</code> if cycles are possible,
+ * and <code>false</code> if cycles are impossible
+ */
+ public final boolean cycleRisk() {
+ return this.cycleRisk;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildPropertyDescriptor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildPropertyDescriptor.java
new file mode 100644
index 000000000..2e6a8a288
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ChildPropertyDescriptor.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Descriptor for a child property of an AST node.
+ * A child property is one whose value is an
+ * {@link ASTNode}.
+ *
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.jdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class ChildPropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Child type. For example, for a node type like
+ * CompilationUnit, the "package" property is PackageDeclaration.class
+ */
+ private final Class childClass;
+
+ /**
+ * Indicates whether the child is mandatory. A child property is allowed
+ * to be <code>null</code> only if it is not mandatory.
+ */
+ private final boolean mandatory;
+
+ /**
+ * Indicates whether a cycle is possible.
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ */
+ final boolean cycleRisk;
+
+ /**
+ * Creates a new child property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param childType the child type of this property
+ * @param mandatory <code>true</code> if the property is mandatory,
+ * and <code>false</code> if it is may be <code>null</code>
+ * @param cycleRisk <code>true</code> if this property is at
+ * risk of cycles, and <code>false</code> if there is no worry about cycles
+ */
+ ChildPropertyDescriptor(Class nodeClass, String propertyId, Class childType, boolean mandatory, boolean cycleRisk) {
+ super(nodeClass, propertyId);
+ if (childType == null || !ASTNode.class.isAssignableFrom(childType)) {
+ throw new IllegalArgumentException();
+ }
+ this.childClass = childType;
+ this.mandatory = mandatory;
+ this.cycleRisk = cycleRisk;
+ }
+
+ /**
+ * Returns the child type of this property.
+ * <p>
+ * For example, for a node type like CompilationUnit,
+ * the "package" property returns <code>PackageDeclaration.class</code>.
+ * </p>
+ *
+ * @return the child type of the property
+ */
+ public final Class getChildType() {
+ return this.childClass;
+ }
+
+ /**
+ * Returns whether this property is mandatory. A property value
+ * is not allowed to be <code>null</code> if it is mandatory.
+ *
+ * @return <code>true</code> if the property is mandatory,
+ * and <code>false</code> if it is may be <code>null</code>
+ */
+ public final boolean isMandatory() {
+ return this.mandatory;
+ }
+
+ /**
+ * Returns whether this property is vulnerable to cycles.
+ * <p>
+ * A property is vulnerable to cycles if a node of the owning
+ * type (that is, the type that owns this property) could legally
+ * appear in the AST subtree below this property. For example,
+ * the body property of a
+ * {@link MethodDeclaration} node
+ * admits a body which might include statement that embeds
+ * another {@link MethodDeclaration} node.
+ * On the other hand, the name property of a
+ * MethodDeclaration node admits only names, and thereby excludes
+ * another MethodDeclaration node.
+ * </p>
+ *
+ * @return <code>true</code> if cycles are possible,
+ * and <code>false</code> if cycles are impossible
+ */
+ public final boolean cycleRisk() {
+ return this.cycleRisk;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java
new file mode 100644
index 000000000..9d8e42750
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ClassInstanceCreation.java
@@ -0,0 +1,585 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class instance creation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * ClassInstanceCreation:
+ * [ Expression <b>.</b> ] <b>new</b> Name
+ * <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * [ AnonymousClassDeclaration ]
+ * </pre>
+ * For JLS3, type arguments are added
+ * and the type name is generalized to a type so that parameterized
+ * types can be instantiated:
+ * <pre>
+ * ClassInstanceCreation:
+ * [ Expression <b>.</b> ]
+ * <b>new</b> [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * Type <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * [ AnonymousClassDeclaration ]
+ * </pre>
+ * <p>
+ * Not all node arragements will represent legal Java constructs. In particular,
+ * it is nonsense if the type is a primitive type or an array type (primitive
+ * types cannot be instantiated, and array creations must be represented with
+ * <code>ArrayCreation</code> nodes). The normal use is when the type is a
+ * simple, qualified, or parameterized type.
+ * </p>
+ * <p>
+ * A type like "A.B" can be represented either of two ways:
+ * <ol>
+ * <li>
+ * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+ * </li>
+ * <li>
+ * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+ * </li>
+ * </ol>
+ * The first form is preferred when "A" is known to be a type (as opposed
+ * to a package). However, a parser cannot always determine this. Clients
+ * should be prepared to handle either rather than make assumptions.
+ * (Note also that the first form became possible as of JLS3; only the second
+ * form existed in JLS2.)
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ClassInstanceCreation extends Expression {
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ClassInstanceCreation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ClassInstanceCreation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "anonymousClassDeclaration" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(ClassInstanceCreation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(6);
+ createPropertyList(ClassInstanceCreation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The type name; lazily initialized; defaults to a unspecified,
+ * legal type name. Not used in JLS3.
+ */
+ private Name typeName = null;
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified type.
+ * @since 3.0
+ */
+ private Type type = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * The optional anonymous class declaration; <code>null</code> for none;
+ * defaults to none.
+ */
+ private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+
+ /**
+ * Creates a new AST node for a class instance creation expression owned
+ * by the given AST. By default, there is no qualifying expression,
+ * an empty list of type parameters, an unspecified type, an empty
+ * list of arguments, and does not declare an anonymous class.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ClassInstanceCreation (AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+ if (get) {
+ return getAnonymousClassDeclaration();
+ } else {
+ setAnonymousClassDeclaration((AnonymousClassDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CLASS_INSTANCE_CREATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ClassInstanceCreation result = new ClassInstanceCreation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setName((Name) getName().clone(target));
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ result.setType((Type) getType().clone(target));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ result.setAnonymousClassDeclaration(
+ (AnonymousClassDeclaration)
+ ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getName());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ acceptChild(visitor, getType());
+ }
+ acceptChildren(visitor, this.arguments);
+ acceptChild(visitor, getAnonymousClassDeclaration());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this class instance creation expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets or clears the expression of this class instance creation expression.
+ *
+ * @param expression the expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ // a ClassInstanceCreation may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this class
+ * instance creation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the type instantiated in this class instance
+ * creation expression (JLS2 API only).
+ *
+ * @return the type name node
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getType()}, which returns a <code>Type</code> instead of a
+ * <code>Name</code>.
+ */
+ public Name getName() {
+ return internalGetName();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ Name internalGetName() {
+ supportedOnlyIn2();
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of the type instantiated in this class instance
+ * creation expression (JLS2 API only).
+ *
+ * @param name the new type name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>`
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setType(Type)}, which expects a <code>Type</code> instead of
+ * a <code>Name</code>.
+ */
+ public void setName(Name name) {
+ internalSetName(name);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ void internalSetName(Name name) {
+ supportedOnlyIn2();
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.typeName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the type instantiated in this class instance creation
+ * expression (added in JLS3 API).
+ *
+ * @return the type node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public Type getType() {
+ unsupportedIn2();
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = new SimpleType(this.ast);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type instantiated in this class instance creation
+ * expression (added in JLS3 API).
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>`
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public void setType(Type type) {
+ unsupportedIn2();
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this class
+ * instance creation expression.
+ *
+ * @return the live list of argument expressions (possibly empty)
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Returns the anonymous class declaration introduced by this
+ * class instance creation expression, if it has one.
+ *
+ * @return the anonymous class declaration, or <code>null</code> if none
+ */
+ public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+ return this.optionalAnonymousClassDeclaration;
+ }
+
+ /**
+ * Sets whether this class instance creation expression declares
+ * an anonymous class (that is, has class body declarations).
+ *
+ * @param decl the anonymous class declaration, or <code>null</code>
+ * if none
+ */
+ public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+ ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+ preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ this.optionalAnonymousClassDeclaration = decl;
+ postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression. For anonymous classes, the binding is that of the anonymous
+ * constructor.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the constructor binding, or <code>null</code> if the binding
+ * cannot be resolved
+ */
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 6 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ // n.b. type == null for ast.API_LEVEL == JLS2
+ // n.b. typeArguments == null for ast.API_LEVEL == JLS2
+ // n.b. typeName == null for ast.API_LEVEL >= JLS3
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize())
+ + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Comment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Comment.java
new file mode 100644
index 000000000..ca69b46e5
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Comment.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent comments.
+ * There are exactly three kinds of comment:
+ * line comments ({@link LineComment}),
+ * block comments ({@link BlockComment}), and
+ * doc comments ({@link Javadoc}).
+ * <p>
+ * <pre>
+ * Comment:
+ * LineComment
+ * BlockComment
+ * Javadoc
+ * </pre>
+ * </p>
+ *
+ * @since 3.0
+ */
+public abstract class Comment extends ASTNode {
+
+ /**
+ * Alternate root node, or <code>null</code> if none.
+ * Initially <code>null</code>.
+ */
+ private ASTNode alternateRoot = null;
+
+ /**
+ * Creates a new AST node for a comment owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Comment(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this comment is a block comment
+ * (<code>BlockComment</code>).
+ *
+ * @return <code>true</code> if this is a block comment, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isBlockComment() {
+ return (this instanceof BlockComment);
+ }
+
+ /**
+ * Returns whether this comment is a line comment
+ * (<code>LineComment</code>).
+ *
+ * @return <code>true</code> if this is a line comment, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isLineComment() {
+ return (this instanceof LineComment);
+ }
+
+ /**
+ * Returns whether this comment is a doc comment
+ * (<code>Javadoc</code>).
+ *
+ * @return <code>true</code> if this is a doc comment, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isDocComment() {
+ return (this instanceof Javadoc);
+ }
+
+ /**
+ * Returns the root AST node that this comment occurs
+ * within, or <code>null</code> if none (or not recorded).
+ * <p>
+ * Typically, the comment nodes created while parsing a compilation
+ * unit are not considered descendents of the normal AST
+ * root, namely an {@link CompilationUnit}. Instead, these
+ * comment nodes exist outside the normal AST and each is
+ * a root in its own right. This optional property provides
+ * a well-known way to navigate from the comment to the
+ * compilation unit in such cases. Note that the alternate root
+ * property is not one of the comment node's children. It is simply a
+ * reference to a node.
+ * </p>
+ *
+ * @return the alternate root node, or <code>null</code>
+ * if none
+ * @see #setAlternateRoot(ASTNode)
+ */
+ public final ASTNode getAlternateRoot() {
+ return this.alternateRoot;
+ }
+
+ /**
+ * Returns the root AST node that this comment occurs
+ * within, or <code>null</code> if none (or not recorded).
+ * <p>
+ * </p>
+ *
+ * @param root the alternate root node, or <code>null</code>
+ * if none
+ * @see #getAlternateRoot()
+ */
+ public final void setAlternateRoot(ASTNode root) {
+ // alternate root is *not* considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.alternateRoot = root;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
new file mode 100644
index 000000000..ec7a585cd
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -0,0 +1,1091 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Java compilation unit AST node type. This is the type of the root of an AST.
+ * <p>
+ * The source range for this type of node is ordinarily the entire source file,
+ * including leading and trailing whitespace and comments.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * CompilationUnit:
+ * [ PackageDeclaration ]
+ * { ImportDeclaration }
+ * { TypeDeclaration | <b>;</b> }
+ * </pre>
+ * For JLS3, the kinds of type declarations
+ * grew to include enum and annotation type declarations:
+ * <pre>
+ * CompilationUnit:
+ * [ PackageDeclaration ]
+ * { ImportDeclaration }
+ * { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | <b>;</b> }
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CompilationUnit extends ASTNode {
+
+ /**
+ * Canonical empty list of messages.
+ */
+ private static final Message[] EMPTY_MESSAGES = new Message[0];
+
+ /**
+ * Canonical empty list of problems.
+ */
+ private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
+
+ /**
+ * The "imports" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor IMPORTS_PROPERTY =
+ new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "package" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor PACKAGE_PROPERTY =
+ new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ /**
+ * The "types" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor TYPES_PROPERTY =
+ new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(CompilationUnit.class, properyList);
+ addProperty(PACKAGE_PROPERTY, properyList);
+ addProperty(IMPORTS_PROPERTY, properyList);
+ addProperty(TYPES_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The comment mapper, or <code>null</code> if none;
+ * initially <code>null</code>.
+ * @since 3.0
+ */
+ private DefaultCommentMapper commentMapper = null;
+
+ /**
+ * The Java type root (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
+ * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
+ */
+ private ITypeRoot typeRoot = null;
+
+ /**
+ * The list of import declarations in textual order order;
+ * initially none (elementType: <code>ImportDeclaration</code>).
+ */
+ private ASTNode.NodeList imports =
+ new ASTNode.NodeList(IMPORTS_PROPERTY);
+
+ /**
+ * Line end table. If <code>lineEndTable[i] == p</code> then the
+ * line number <code>i+1</code> ends at character position
+ * <code>p</code>. Except for the last line, the positions are that
+ * of the last character of the line delimiter.
+ * For example, the source string <code>A\nB\nC</code> has
+ * line end table {1, 3} (if \n is one character).
+ */
+ private int[] lineEndTable = Util.EMPTY_INT_ARRAY;
+
+ /**
+ * Messages reported by the compiler during parsing or name resolution.
+ */
+ private Message[] messages;
+
+ /**
+ * The comment list (element type: <code>Comment</code>,
+ * or <code>null</code> if none; initially <code>null</code>.
+ * @since 3.0
+ */
+ private List optionalCommentList = null;
+
+ /**
+ * The comment table, or <code>null</code> if none; initially
+ * <code>null</code>. This array is the storage underlying
+ * the <code>optionalCommentList</code> ArrayList.
+ * @since 3.0
+ */
+ Comment[] optionalCommentTable = null;
+
+ /**
+ * The package declaration, or <code>null</code> if none; initially
+ * <code>null</code>.
+ */
+ private PackageDeclaration optionalPackageDeclaration = null;
+
+ /**
+ * Problems reported by the compiler during parsing or name resolution.
+ */
+ private IProblem[] problems = EMPTY_PROBLEMS;
+
+ /**
+ * Internal data used to perform statements recovery.
+ */
+ private Object statementsRecoveryData;
+
+ /**
+ * The list of type declarations in textual order order;
+ * initially none (elementType: <code>AbstractTypeDeclaration</code>)
+ */
+ private ASTNode.NodeList types =
+ new ASTNode.NodeList(TYPES_PROPERTY);
+
+ /**
+ * Creates a new AST node for a compilation owned by the given AST.
+ * The compilation unit initially has no package declaration, no
+ * import declarations, and no type declarations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ CompilationUnit(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getPackage());
+ acceptChildren(visitor, this.imports);
+ acceptChildren(visitor, this.types);
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CompilationUnit result = new CompilationUnit(target);
+ // n.b do not copy line number table or messages
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setPackage(
+ (PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
+ result.imports().addAll(ASTNode.copySubtrees(target, imports()));
+ result.types().addAll(ASTNode.copySubtrees(target, types()));
+ return result;
+ }
+
+
+ /**
+ * Returns the column number corresponding to the given source character
+ * position in the original source string. Column number are zero-based.
+ * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
+ * if the column number information is unknown.
+ *
+ * @param position a 0-based character position, possibly
+ * negative or out of range
+ * @return the 0-based column number, or <code>-1</code> if the character
+ * position does not correspond to a source line in the original
+ * source file or <code>-2</code> if column number information is unknown for this
+ * compilation unit
+ * @see ASTParser
+ * @since 3.2
+ */
+ public int getColumnNumber(final int position) {
+ if (this.lineEndTable == null) return -2;
+ final int line = getLineNumber(position);
+ if (line == -1) {
+ return -1;
+ }
+ if (line == 1) {
+ if (position >= getStartPosition() + getLength()) return -1;
+ return position;
+ }
+ // length is different from 0
+ int length = this.lineEndTable.length;
+ // -1 to for one-based to zero-based conversion.
+ // -1, again, to get previous line.
+ final int previousLineOffset = this.lineEndTable[line - 2];
+ // previousLineOffset + 1 is the first character of the current line
+ final int offsetForLine = previousLineOffset + 1;
+ final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line - 1];
+ if (offsetForLine > currentLineEnd) {
+ return -1;
+ } else {
+ return position - offsetForLine;
+ }
+ }
+
+ /**
+ * Finds the corresponding AST node in the given compilation unit from
+ * which the given binding originated. Returns <code>null</code> if the
+ * binding does not correspond to any node in this compilation unit.
+ * This method always returns <code>null</code> if bindings were not requested
+ * when this AST was built.
+ * <p>
+ * The following table indicates the expected node type for the various
+ * different kinds of bindings:
+ * <ul>
+ * <li>package - a <code>PackageDeclaration</code></li>
+ * <li>class or interface - a <code>TypeDeclaration</code> or a
+ * <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
+ * <li>primitive type - none</li>
+ * <li>array type - none</li>
+ * <li>field - a <code>VariableDeclarationFragment</code> in a
+ * <code>FieldDeclaration</code> </li>
+ * <li>local variable - a <code>SingleVariableDeclaration</code>, or
+ * a <code>VariableDeclarationFragment</code> in a
+ * <code>VariableDeclarationStatement</code> or
+ * <code>VariableDeclarationExpression</code></li>
+ * <li>method - a <code>MethodDeclaration</code> </li>
+ * <li>constructor - a <code>MethodDeclaration</code> </li>
+ * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
+ * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
+ * <li>enum type - an <code>EnumDeclaration</code></li>
+ * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+ * <li>type variable - a <code>TypeParameter</code></li>
+ * <li>capture binding - none</li>
+ * <li>annotation binding - an <code>Annotation</code></li>
+ * <li>member value pair binding - an <code>MemberValuePair</code>,
+ * or <code>null</code> if it represents a default value or a single member value</li>
+ * </ul>
+ * For parameterized or raw type bindings, the declaring node is
+ * that of the corresponding generic type. And for parameterized or raw
+ * method bindings, the declaring node is that of the corresponding
+ * generic method.
+ * </p>
+ * <p>
+ * Each call to {@link ASTParser#createAST(org.eclipse.core.runtime.IProgressMonitor)} with a request for bindings
+ * gives rise to separate universe of binding objects. This method always returns
+ * <code>null</code> when the binding object comes from a different AST.
+ * Use <code>findDeclaringNode(binding.getKey())</code> when the binding comes
+ * from a different AST.
+ * </p>
+ *
+ * @param binding the binding
+ * @return the corresponding node where the given binding is declared,
+ * or <code>null</code> if the binding does not correspond to a node in this
+ * compilation unit or if bindings were not requested when this AST was built
+ * @see #findDeclaringNode(String)
+ */
+ public ASTNode findDeclaringNode(IBinding binding) {
+ return this.ast.getBindingResolver().findDeclaringNode(binding);
+ }
+
+ /**
+ * Finds the corresponding AST node in the given compilation unit from
+ * which the binding with the given key originated. Returns
+ * <code>null</code> if the corresponding node cannot be determined.
+ * This method always returns <code>null</code> if bindings were not requested
+ * when this AST was built.
+ * <p>
+ * The following table indicates the expected node type for the various
+ * different kinds of binding keys:
+ * <ul>
+ * <li></li>
+ * <li>package - a <code>PackageDeclaration</code></li>
+ * <li>class or interface - a <code>TypeDeclaration</code> or a
+ * <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
+ * <li>primitive type - none</li>
+ * <li>array type - none</li>
+ * <li>field - a <code>VariableDeclarationFragment</code> in a
+ * <code>FieldDeclaration</code> </li>
+ * <li>local variable - a <code>SingleVariableDeclaration</code>, or
+ * a <code>VariableDeclarationFragment</code> in a
+ * <code>VariableDeclarationStatement</code> or
+ * <code>VariableDeclarationExpression</code></li>
+ * <li>method - a <code>MethodDeclaration</code> </li>
+ * <li>constructor - a <code>MethodDeclaration</code> </li>
+ * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
+ * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
+ * <li>enum type - an <code>EnumDeclaration</code></li>
+ * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+ * <li>type variable - a <code>TypeParameter</code></li>
+ * <li>capture binding - none</li>
+ * </ul>
+ * For parameterized or raw type bindings, the declaring node is
+ * that of the corresponding generic type. And for parameterized or raw
+ * method bindings, the declaring node is that of the corresponding
+ * generic method.
+ * </p>
+ *
+ * @param key the binding key, or <code>null</code>
+ * @return the corresponding node where a binding with the given
+ * key is declared, or <code>null</code> if the key is <code>null</code>
+ * or if the key does not correspond to a node in this compilation unit
+ * or if bindings were not requested when this AST was built
+ * @see IBinding#getKey()
+ * @since 2.1
+ */
+ public ASTNode findDeclaringNode(String key) {
+ return this.ast.getBindingResolver().findDeclaringNode(key);
+ }
+
+ /**
+ * Returns a list of the comments encountered while parsing
+ * this compilation unit.
+ * <p>
+ * Since the Java language allows comments to appear most anywhere
+ * in the source text, it is problematic to locate comments in relation
+ * to the structure of an AST. The one exception is doc comments
+ * which, by convention, immediately precede type, field, and
+ * method declarations; these comments are located in the AST
+ * by {@link BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
+ * Other comments do not show up in the AST. The table of comments
+ * is provided for clients that need to find the source ranges of
+ * all comments in the original source string. It includes entries
+ * for comments of all kinds (line, block, and doc), arranged in order
+ * of increasing source position.
+ * </p>
+ * <p>
+ * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
+ * of a doc comment associated with a body declaration is the body
+ * declaration node; for these comment nodes
+ * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
+ * (assuming an unmodified AST) reflecting the fact that these nodes
+ * are property located in the AST for the compilation unit.
+ * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
+ * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
+ * will return the comment node itself, indicating that these comment nodes
+ * are not directly connected to the AST for the compilation unit. The
+ * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
+ * method provides a way to navigate from a comment to its compilation
+ * unit.
+ * </p>
+ * <p>
+ * A note on visitors: The only comment nodes that will be visited when
+ * visiting a compilation unit are the doc comments parented by body
+ * declarations. To visit all comments in normal reading order, iterate
+ * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
+ * on each element.
+ * </p>
+ * <p>
+ * Clients cannot modify the resulting list.
+ * </p>
+ *
+ * @return an unmodifiable list of comments in increasing order of source
+ * start position, or <code>null</code> if comment information
+ * for this compilation unit is not available
+ * @see ASTParser
+ * @since 3.0
+ */
+ public List getCommentList() {
+ return this.optionalCommentList;
+ }
+
+ /**
+ * Returns the internal comment mapper.
+ *
+ * @return the comment mapper, or <code>null</code> if none.
+ * @since 3.0
+ */
+ DefaultCommentMapper getCommentMapper() {
+ return this.commentMapper;
+ }
+
+ /**
+ * Returns the extended source length of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return a (possibly 0) length, or <code>0</code>
+ * if no source position information is recorded for this node
+ * @see #getExtendedStartPosition(ASTNode)
+ * @since 3.0
+ */
+ public int getExtendedLength(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ // fall back: use best info available
+ return node.getLength();
+ } else {
+ return this.commentMapper.getExtendedLength(node);
+ }
+ }
+
+ /**
+ * Returns the extended start position of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is recorded for this node
+ * @see #getExtendedLength(ASTNode)
+ * @since 3.0
+ */
+ public int getExtendedStartPosition(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ // fall back: use best info available
+ return node.getStartPosition();
+ } else {
+ return this.commentMapper.getExtendedStartPosition(node);
+ }
+ }
+
+ /**
+ * The Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
+ * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
+ *
+ * @return the Java element this compilation unit was created from, or <code>null</code> if none
+ * @since 3.1
+ * @see #getTypeRoot()
+ */
+ public IJavaElement getJavaElement() {
+ return this.typeRoot;
+ }
+
+ /**
+ * Returns the list of messages reported by the compiler during the parsing
+ * or the type checking of this compilation unit. This list might be a subset of
+ * errors detected and reported by a Java compiler.
+ * <p>
+ * This list of messages is suitable for simple clients that do little
+ * more than log the messages or display them to the user. Clients that
+ * need further details should call <code>getProblems</code> to get
+ * compiler problem objects.
+ * </p>
+ *
+ * @return the list of messages, possibly empty
+ * @see #getProblems()
+ * @see ASTParser
+ */
+ public Message[] getMessages() {
+ if (this.messages == null) {
+ int problemLength = this.problems.length;
+ if (problemLength == 0) {
+ this.messages = EMPTY_MESSAGES;
+ } else {
+ this.messages = new Message[problemLength];
+ for (int i = 0; i < problemLength; i++) {
+ IProblem problem = this.problems[i];
+ int start = problem.getSourceStart();
+ int end = problem.getSourceEnd();
+ this.messages[i] = new Message(problem.getMessage(), start, end - start + 1);
+ }
+ }
+ }
+ return this.messages;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return COMPILATION_UNIT;
+ }
+
+ /**
+ * Returns the node for the package declaration of this compilation
+ * unit, or <code>null</code> if this compilation unit is in the
+ * default package.
+ *
+ * @return the package declaration node, or <code>null</code> if none
+ */
+ public PackageDeclaration getPackage() {
+ return this.optionalPackageDeclaration;
+ }
+
+ /**
+ * Given a line number and column number, returns the corresponding
+ * position in the original source string.
+ * Returns -2 if no line number information is available for this
+ * compilation unit.
+ * Returns the total size of the source string if <code>line</code>
+ * is greater than the actual number lines in the unit.
+ * Returns -1 if <code>column</code> is less than 0,
+ * or the position of the last character of the line if <code>column</code>
+ * is beyond the legal range, or the given line number is less than one.
+ *
+ * @param line the one-based line number
+ * @param column the zero-based column number
+ * @return the 0-based character position in the source string;
+ * <code>-2</code> if line/column number information is not known
+ * for this compilation unit or <code>-1</code> the inputs are not valid
+ * @since 3.2
+ */
+ public int getPosition(int line, int column) {
+ if (this.lineEndTable == null) return -2;
+ if (line < 1 || column < 0) return -1;
+ int length;
+ if ((length = this.lineEndTable.length) == 0) {
+ if (line != 1) return -1;
+ return column >= getStartPosition() + getLength() ? -1 : column;
+ }
+ if (line == 1) {
+ final int endOfLine = this.lineEndTable[0];
+ return column > endOfLine ? -1 : column;
+ } else if( line > length + 1 ) {
+ // greater than the number of lines in the source string.
+ return -1;
+ }
+ // -1 to for one-based to zero-based conversion.
+ // -1, again, to get previous line.
+ final int previousLineOffset = this.lineEndTable[line - 2];
+ // previousLineOffset + 1 is the first character of the current line
+ final int offsetForLine = previousLineOffset + 1;
+ final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
+ if ((offsetForLine + column) > currentLineEnd) {
+ return -1;
+ } else {
+ return offsetForLine + column;
+ }
+ }
+
+ /**
+ * Returns the list of detailed problem reports noted by the compiler
+ * during the parsing or the type checking of this compilation unit. This
+ * list might be a subset of errors detected and reported by a Java
+ * compiler.
+ * <p>
+ * Simple clients that do little more than log the messages or display
+ * them to the user should probably call <code>getMessages</code> instead.
+ * </p>
+ *
+ * @return the list of detailed problem objects, possibly empty
+ * @see #getMessages()
+ * @see ASTParser
+ * @since 2.1
+ */
+ public IProblem[] getProblems() {
+ return this.problems;
+ }
+
+ /**
+ * Internal method
+ *
+ * This method return internal data used to perform statements recovery.
+ *
+ * @return internal data used to perform statements recovery.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 3.5
+ */
+ public Object getStatementsRecoveryData() {
+ return this.statementsRecoveryData;
+ }
+
+ /**
+ * The Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
+ * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
+ *
+ * @return the Java type root this compilation unit was created from, or <code>null</code> if none
+ * @since 3.3
+ */
+ public ITypeRoot getTypeRoot() {
+ return this.typeRoot;
+ }
+
+ /**
+ * Returns the live list of nodes for the import declarations of this
+ * compilation unit, in order of appearance.
+ *
+ * @return the live list of import declaration nodes
+ * (elementType: <code>ImportDeclaration</code>)
+ */
+ public List imports() {
+ return this.imports;
+ }
+
+ /**
+ * Return the index in the whole comments list {@link #getCommentList() }
+ * of the first leading comments associated with the given node.
+ *
+ * @param node the node
+ * @return 0-based index of first leading comment or -1 if node has no associated
+ * comment before its start position.
+ * @since 3.2
+ */
+ public int firstLeadingCommentIndex(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ return -1;
+ }
+ return this.commentMapper.firstLeadingCommentIndex(node);
+ }
+
+ /**
+ * Return the index in the whole comments list {@link #getCommentList() }
+ * of the last trailing comments associated with the given node.
+ *
+ * @param node the node
+ * @return 0-based index of last trailing comment or -1 if node has no
+ * associated comment after its end position.
+ * @since 3.2
+ */
+ public int lastTrailingCommentIndex(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ return -1;
+ }
+ return this.commentMapper.lastTrailingCommentIndex(node);
+ }
+
+ /**
+ * Initializes the internal comment mapper with the given
+ * scanner.
+ *
+ * @param scanner the scanner
+ * @since 3.0
+ */
+ void initCommentMapper(Scanner scanner) {
+ this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
+ this.commentMapper.initialize(this, scanner);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == IMPORTS_PROPERTY) {
+ return imports();
+ }
+ if (property == TYPES_PROPERTY) {
+ return types();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == PACKAGE_PROPERTY) {
+ if (get) {
+ return getPackage();
+ } else {
+ setPackage((PackageDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /**
+ * Returns the line number corresponding to the given source character
+ * position in the original source string. The initial line of the
+ * compilation unit is numbered 1, and each line extends through the
+ * last character of the end-of-line delimiter. The very last line extends
+ * through the end of the source string and has no line delimiter.
+ * For example, the source string <code>class A\n{\n}</code> has 3 lines
+ * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
+ * Returns 1 for a character position that does not correspond to any
+ * source line, or if no line number information is available for this
+ * compilation unit.
+ *
+ * @param position a 0-based character position, possibly
+ * negative or out of range
+ * @return the 1-based line number, or <code>1</code> if the character
+ * position does not correspond to a source line in the original
+ * source file or if line number information is not known for this
+ * compilation unit
+ * @deprecated Use getLineNumber(int) instead. Be careful to handle the negative values.
+ * @see ASTParser
+ * @see #getLineNumber(int)
+ */
+ public int lineNumber(int position) {
+ int lineNumber = getLineNumber(position);
+ return lineNumber < 1 ? 1 : lineNumber;
+ }
+
+ /**
+ * Returns the line number corresponding to the given source character
+ * position in the original source string. The initial line of the
+ * compilation unit is numbered 1, and each line extends through the
+ * last character of the end-of-line delimiter. The very last line extends
+ * through the end of the source string and has no line delimiter.
+ * For example, the source string <code>class A\n{\n}</code> has 3 lines
+ * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
+ * Returns -1 for a character position that does not correspond to any
+ * source line, or -2 if no line number information is available for this
+ * compilation unit.
+ *
+ * @param position a 0-based character position, possibly
+ * negative or out of range
+ * @return the 1-based line number, or <code>-1</code> if the character
+ * position does not correspond to a source line in the original
+ * source file or <code>-2</code> if line number information is not known for this
+ * compilation unit
+ * @see ASTParser
+ * @since 3.2
+ */
+ public int getLineNumber(int position) {
+ if (this.lineEndTable == null) return -2;
+ int length;
+ if ((length = this.lineEndTable.length) == 0) {
+ if (position >= getStartPosition() + getLength()) {
+ return -1;
+ }
+ return 1;
+ }
+ int low = 0;
+ if (position < 0) {
+ // position illegal
+ return -1;
+ }
+ if (position <= this.lineEndTable[low]) {
+ // before the first line delimiter
+ return 1;
+ }
+ // assert position > lineEndTable[low+1] && low == 0
+ int hi = length - 1;
+ if (position > this.lineEndTable[hi]) {
+ // position beyond the last line separator
+ if (position >= getStartPosition() + getLength()) {
+ // this is beyond the end of the source length
+ return -1;
+ } else {
+ return length + 1;
+ }
+ }
+ // assert lineEndTable[low] < position <= lineEndTable[hi]
+ // && low == 0 && hi == length - 1 && low < hi
+
+ // binary search line end table
+ while (true) {
+ // invariant lineEndTable[low] < position <= lineEndTable[hi]
+ // && 0 <= low < hi <= length - 1
+ // reducing measure hi - low
+ if (low + 1 == hi) {
+ // assert lineEndTable[low] < position <= lineEndTable[low+1]
+ // position is on line low+1 (line number is low+2)
+ return low + 2;
+ }
+ // assert hi - low >= 2, so average is truly in between
+ int mid = low + (hi - low) / 2;
+ // assert 0 <= low < mid < hi <= length - 1
+ if (position <= this.lineEndTable[mid]) {
+ // assert lineEndTable[low] < position <= lineEndTable[mid]
+ // && 0 <= low < mid < hi <= length - 1
+ hi = mid;
+ } else {
+ // position > lineEndTable[mid]
+ // assert lineEndTable[mid] < position <= lineEndTable[hi]
+ // && 0 <= low < mid < hi <= length - 1
+ low = mid;
+ }
+ // in both cases, invariant reachieved with reduced measure
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 8 * 4;
+ if (this.lineEndTable != null) {
+ size += HEADERS + 4 * this.lineEndTable.length;
+ }
+ if (this.optionalCommentTable != null) {
+ size += HEADERS + 4 * this.optionalCommentTable.length;
+ }
+ // ignore the space taken up by optionalCommentList
+ return size;
+ }
+
+ /**
+ * Enables the recording of changes to this compilation
+ * unit and its descendents. The compilation unit must have
+ * been created by <code>ASTParser</code> and still be in
+ * its original state. Once recording is on,
+ * arbitrary changes to the subtree rooted at this compilation
+ * unit are recorded internally. Once the modification has
+ * been completed, call <code>rewrite</code> to get an object
+ * representing the corresponding edits to the original
+ * source code string.
+ *
+ * @exception IllegalArgumentException if this compilation unit is
+ * marked as unmodifiable, or if this compilation unit has already
+ * been tampered with, or recording has already been enabled
+ * @since 3.0
+ */
+ public void recordModifications() {
+ getAST().recordModifications(this);
+ }
+
+ /**
+ * Converts all modifications recorded for this compilation
+ * unit into an object representing the corresponding text
+ * edits to the given document containing the original source
+ * code for this compilation unit.
+ * <p>
+ * The compilation unit must have been created by
+ * <code>ASTParser</code> from the source code string in the
+ * given document, and recording must have been turned
+ * on with a prior call to <code>recordModifications</code>
+ * while the AST was still in its original state.
+ * </p>
+ * <p>
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications made to the AST
+ * are added to the ones already on record. If this method
+ * is called again later, the resulting text edit object will
+ * accurately reflect the net cumulative affect of all those
+ * changes.
+ * </p>
+ *
+ * @param document original document containing source code
+ * for this compilation unit
+ * @param options the table of formatter options
+ * (key type: <code>String</code>; value type: <code>String</code>);
+ * or <code>null</code> to use the standard global options
+ * {@link org.eclipse.jdt.core.JavaCore#getOptions() JavaCore.getOptions()}.
+ * @return text edit object describing the changes to the
+ * document corresponding to the recorded AST modifications
+ * @exception IllegalArgumentException if the document passed is
+ * <code>null</code> or does not correspond to this AST
+ * @exception IllegalStateException if <code>recordModifications</code>
+ * was not called to enable recording
+ * @see #recordModifications()
+ * @since 3.0
+ */
+ public TextEdit rewrite(IDocument document, Map options) {
+ return getAST().rewrite(document, options);
+ }
+
+ /**
+ * Sets the list of the comments encountered while parsing
+ * this compilation unit.
+ *
+ * @param commentTable a list of comments in increasing order
+ * of source start position, or <code>null</code> if comment
+ * information for this compilation unit is not available
+ * @exception IllegalArgumentException if the comment table is
+ * not in increasing order of source position
+ * @see #getCommentList()
+ * @see ASTParser
+ * @since 3.0
+ */
+ void setCommentTable(Comment[] commentTable) {
+ // double check table to ensure that all comments have
+ // source positions and are in strictly increasing order
+ if (commentTable == null) {
+ this.optionalCommentList = null;
+ this.optionalCommentTable = null;
+ } else {
+ int nextAvailablePosition = 0;
+ for (int i = 0; i < commentTable.length; i++) {
+ Comment comment = commentTable[i];
+ if (comment == null) {
+ throw new IllegalArgumentException();
+ }
+ int start = comment.getStartPosition();
+ int length = comment.getLength();
+ if (start < 0 || length < 0 || start < nextAvailablePosition) {
+ throw new IllegalArgumentException();
+ }
+ nextAvailablePosition = comment.getStartPosition() + comment.getLength();
+ }
+ this.optionalCommentTable = commentTable;
+ List commentList = Arrays.asList(commentTable);
+ // protect the list from further modification
+ this.optionalCommentList = Collections.unmodifiableList(commentList);
+ }
+ }
+
+ /**
+ * Sets the Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
+ * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
+ *
+ * @param typeRoot the Java type root this compilation unit was created from
+ */
+ void setTypeRoot(ITypeRoot typeRoot) {
+ this.typeRoot = typeRoot;
+ }
+
+ /**
+ * Sets the line end table for this compilation unit.
+ * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code>
+ * ends at character position <code>p</code>. Except for the last line, the
+ * positions are that of (the last character of) the line delimiter.
+ * For example, the source string <code>A\nB\nC</code> has
+ * line end table {1, 3, 4}.
+ *
+ * @param lineEndTable the line end table
+ */
+ void setLineEndTable(int[] lineEndTable) {
+ if (lineEndTable == null) {
+ throw new NullPointerException();
+ }
+ // alternate root is *not* considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.lineEndTable = lineEndTable;
+ }
+
+ /**
+ * Sets or clears the package declaration of this compilation unit
+ * node to the given package declaration node.
+ *
+ * @param pkgDecl the new package declaration node, or
+ * <code>null</code> if this compilation unit does not have a package
+ * declaration (that is in the default package)
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setPackage(PackageDeclaration pkgDecl) {
+ ASTNode oldChild = this.optionalPackageDeclaration;
+ preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+ this.optionalPackageDeclaration = pkgDecl;
+ postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+ }
+
+
+ /**
+ * Sets the array of problems reported by the compiler during the parsing or
+ * name resolution of this compilation unit.
+ *
+ * @param problems the list of problems
+ */
+ void setProblems(IProblem[] problems) {
+ if (problems == null) {
+ throw new IllegalArgumentException();
+ }
+ this.problems = problems;
+ }
+
+ /**
+ * Internal method
+ *
+ * Sets internal data used to perform statements recovery.
+ * @param data
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 3.5
+ */
+ void setStatementsRecoveryData(Object data) {
+ this.statementsRecoveryData = data;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ int size = memSize();
+ if (this.optionalPackageDeclaration != null) {
+ size += getPackage().treeSize();
+ }
+ size += this.imports.listSize();
+ size += this.types.listSize();
+ // include disconnected comments
+ if (this.optionalCommentList != null) {
+ for (int i = 0; i < this.optionalCommentList.size(); i++) {
+ Comment comment = (Comment) this.optionalCommentList.get(i);
+ if (comment != null && comment.getParent() == null) {
+ size += comment.treeSize();
+ }
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the live list of nodes for the top-level type declarations of this
+ * compilation unit, in order of appearance.
+ * <p>
+ * Note that in JLS3, the types may include both enum declarations
+ * and annotation type declarations introduced in J2SE 5.
+ * For JLS2, the elements are always <code>TypeDeclaration</code>.
+ * </p>
+ *
+ * @return the live list of top-level type declaration
+ * nodes (elementType: <code>AbstractTypeDeclaration</code>)
+ */
+ public List types() {
+ return this.types;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
new file mode 100644
index 000000000..d269ab760
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -0,0 +1,1032 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: CompilationUnitResolver.java 23404 2010-02-03 14:10:22Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.ISourceType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.jdt.internal.compiler.util.Messages;
+import org.eclipse.jdt.internal.core.BinaryMember;
+import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
+import org.eclipse.jdt.internal.core.CancelableProblemFactory;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.SourceRefElement;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.util.BindingKeyResolver;
+import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
+import org.eclipse.jdt.internal.core.util.DOMFinder;
+import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+
+/**
+ * <h4>OTDT changes:</h4>
+ * <dl>
+ * <dt>What:<dd> setup and use Dependencies for calling into the compiler.
+ * </dl>
+ */
+class CompilationUnitResolver extends Compiler {
+
+ /* A list of int */
+ static class IntArrayList {
+ public int[] list = new int[5];
+ public int length = 0;
+ public void add(int i) {
+ if (this.list.length == this.length) {
+ System.arraycopy(this.list, 0, this.list = new int[this.length*2], 0, this.length);
+ }
+ this.list[this.length++] = i;
+ }
+ }
+
+ /*
+ * The sources that were requested.
+ * Map from file name (char[]) to ICompilationUnit.
+ */
+ HashtableOfObject requestedSources;
+
+ /*
+ * The binding keys that were requested.
+ * Map from file name (char[]) to BindingKey (or ArrayList if multiple keys in the same file).
+ */
+ HashtableOfObject requestedKeys;
+
+ DefaultBindingResolver.BindingTables bindingTables;
+
+ boolean hasCompilationAborted;
+
+ private IProgressMonitor monitor;
+
+ /**
+ * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the compiler is run, compilation results are sent to the given requestor.
+ *
+ * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+ * Environment used by the compiler in order to resolve type and package
+ * names. The name environment implements the actual connection of the compiler
+ * to the outside world (for example, in batch mode the name environment is performing
+ * pure file accesses, reuse previous build state or connection to repositories).
+ * Note: the name environment is responsible for implementing the actual classpath
+ * rules.
+ *
+ * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ * Configurable part for problem handling, allowing the compiler client to
+ * specify the rules for handling problems (stop on first error or accumulate
+ * them all) and at the same time perform some actions such as opening a dialog
+ * in UI when compiling interactively.
+ * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
+ *
+ * @param compilerOptions The compiler options to use for the resolution.
+ *
+ * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+ * Component which will receive and persist all compilation results and is intended
+ * to consume them as they are produced. Typically, in a batch compiler, it is
+ * responsible for writing out the actual .class files to the file system.
+ * @see org.eclipse.jdt.internal.compiler.CompilationResult
+ *
+ * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+ * Factory used inside the compiler to create problem descriptors. It allows the
+ * compiler client to supply its own representation of compilation problems in
+ * order to avoid object conversions. Note that the factory is not supposed
+ * to accumulate the created problems, the compiler will gather them all and hand
+ * them back as part of the compilation unit result.
+ */
+ public CompilationUnitResolver(
+ INameEnvironment environment,
+ IErrorHandlingPolicy policy,
+ CompilerOptions compilerOptions,
+ ICompilerRequestor requestor,
+ IProblemFactory problemFactory,
+ IProgressMonitor monitor) {
+
+ super(environment, policy, compilerOptions, requestor, problemFactory);
+ this.hasCompilationAborted = false;
+ this.monitor =monitor;
+ }
+
+ /*
+ * Add additional source types
+ */
+ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ // Need to reparse the entire source of the compilation unit so as to get source positions
+ // (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
+ SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
+ accept((org.eclipse.jdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getCompilationUnit(), accessRestriction);
+ }
+
+ public synchronized void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
+ super.accept(sourceUnit, accessRestriction);
+ }
+
+ /**
+ * Add the initial set of compilation units into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+ protected void beginToCompile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
+ int sourceLength = sourceUnits.length;
+ int keyLength = bindingKeys.length;
+ int maxUnits = sourceLength + keyLength;
+ this.totalUnits = 0;
+ this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+ int index = 0;
+
+ // walks the source units
+ this.requestedSources = new HashtableOfObject();
+ for (int i = 0; i < sourceLength; i++) {
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
+ CompilationUnitDeclaration parsedUnit;
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
+ try {
+ if (this.options.verbose) {
+ this.out.println(
+ Messages.bind(Messages.compilation_request,
+ new String[] {
+ String.valueOf(index++ + 1),
+ String.valueOf(maxUnits),
+ new String(sourceUnit.getFileName())
+ }));
+ }
+ // diet parsing for large collection of units
+ if (this.totalUnits < this.parseThreshold) {
+ parsedUnit = this.parser.parse(sourceUnit, unitResult);
+ } else {
+ parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
+ }
+ // initial type binding creation
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ addCompilationUnit(sourceUnit, parsedUnit);
+ this.requestedSources.put(unitResult.getFileName(), sourceUnit);
+ worked(1);
+ } finally {
+ sourceUnits[i] = null; // no longer hold onto the unit
+ }
+ }
+
+ // walk the binding keys
+ this.requestedKeys = new HashtableOfObject();
+ for (int i = 0; i < keyLength; i++) {
+ BindingKeyResolver resolver = new BindingKeyResolver(bindingKeys[i], this, this.lookupEnvironment);
+ resolver.parse(true/*pause after fully qualified name*/);
+ // If it doesn't have a type name, then it is either an array type, package or base type, which will definitely not have a compilation unit.
+ // Skipping it will speed up performance because the call will open jars. (theodora)
+ CompilationUnitDeclaration parsedUnit = resolver.hasTypeName() ? resolver.getCompilationUnitDeclaration() : null;
+ if (parsedUnit != null) {
+ char[] fileName = parsedUnit.compilationResult.getFileName();
+ Object existing = this.requestedKeys.get(fileName);
+ if (existing == null)
+ this.requestedKeys.put(fileName, resolver);
+ else if (existing instanceof ArrayList)
+ ((ArrayList) existing).add(resolver);
+ else {
+ ArrayList list = new ArrayList();
+ list.add(existing);
+ list.add(resolver);
+ this.requestedKeys.put(fileName, list);
+ }
+
+ } else {
+ char[] key = resolver.hasTypeName()
+ ? resolver.getKey().toCharArray() // binary binding
+ : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding
+ this.requestedKeys.put(key, resolver);
+ }
+ worked(1);
+ }
+
+ // binding resolution
+ this.lookupEnvironment.completeTypeBindings();
+ }
+
+ IBinding createBinding(String key) {
+ if (this.bindingTables == null)
+ throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
+ BindingKeyResolver keyResolver = new BindingKeyResolver(key, this, this.lookupEnvironment);
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ if (compilerBinding == null) return null;
+ DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables, false);
+ return resolver.getBinding(compilerBinding);
+ }
+
+ public static CompilationUnit convert(CompilationUnitDeclaration compilationUnitDeclaration, char[] source, int apiLevel, Map options, boolean needToResolveBindings, WorkingCopyOwner owner, DefaultBindingResolver.BindingTables bindingTables, int flags, IProgressMonitor monitor) {
+ BindingResolver resolver = null;
+ AST ast = AST.newAST(apiLevel);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ CompilationUnit compilationUnit = null;
+ ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
+ if (needToResolveBindings) {
+ resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+ } else {
+ resolver = new BindingResolver();
+ ast.setFlag(flags);
+ }
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+ compilationUnit = converter.convert(compilationUnitDeclaration, source);
+ compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+
+ protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
+ CompilerOptions compilerOptions = new CompilerOptions(options);
+ compilerOptions.performMethodsFullRecovery = statementsRecovery;
+ compilerOptions.performStatementsRecovery = statementsRecovery;
+ compilerOptions.parseLiteralExpressionsAsConstants = false;
+ compilerOptions.storeAnnotations = true /*store annotations in the bindings*/;
+ return compilerOptions;
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ protected static IErrorHandlingPolicy getHandlingPolicy() {
+
+ // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors() {
+ return false; // stop if there are some errors
+ }
+ };
+ }
+
+ /*
+ * Answer the component to which will be handed back compilation results from the compiler
+ */
+ protected static ICompilerRequestor getRequestor() {
+ return new ICompilerRequestor() {
+ public void acceptResult(CompilationResult compilationResult) {
+ // do nothing
+ }
+ };
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
+ */
+ public void initializeParser() {
+ this.parser = new CommentRecorderParser(this.problemReporter, false);
+ }
+ public void process(CompilationUnitDeclaration unit, int i) {
+ // don't resolve a second time the same unit (this would create the same binding twice)
+ char[] fileName = unit.compilationResult.getFileName();
+ if (this.requestedKeys.get(fileName) == null && this.requestedSources.get(fileName) == null)
+ super.process(unit, i);
+ }
+ /*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+ protected void handleInternalException(
+ Throwable internalException,
+ CompilationUnitDeclaration unit,
+ CompilationResult result) {
+ super.handleInternalException(internalException, unit, result);
+ if (unit != null) {
+ removeUnresolvedBindings(unit);
+ }
+ }
+
+ /*
+ * Compiler recovery in case of internal AbortCompilation event
+ */
+ protected void handleInternalException(
+ AbortCompilation abortException,
+ CompilationUnitDeclaration unit) {
+ super.handleInternalException(abortException, unit);
+ if (unit != null) {
+ removeUnresolvedBindings(unit);
+ }
+ this.hasCompilationAborted = true;
+ }
+
+ public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
+ try {
+ CompilerOptions compilerOptions = new CompilerOptions(options);
+ compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+ Parser parser = new CommentRecorderParser(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ compilerOptions,
+ new DefaultProblemFactory()),
+ false);
+ int unitLength = compilationUnits.length;
+ if (monitor != null) monitor.beginTask("", unitLength); //$NON-NLS-1$
+ for (int i = 0; i < unitLength; i++) {
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
+ CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+
+ if (compilationUnitDeclaration.ignoreMethodBodies) {
+ compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ continue;
+ }
+
+ //fill the methods bodies in order for the code to be generated
+ //real parse of the method....
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int j = 0, typeLength = types.length; j < typeLength; j++) {
+ types[j].parseMethods(parser, compilationUnitDeclaration);
+ }
+ }
+
+ // convert AST
+ CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, flags /* flags */, monitor);
+ node.setTypeRoot(compilationUnits[i]);
+
+ // accept AST
+ astRequestor.acceptAST(compilationUnits[i], node);
+
+ if (monitor != null) monitor.worked(1);
+ }
+ } finally {
+ if (monitor != null) monitor.done();
+ }
+ }
+
+ public static CompilationUnitDeclaration parse(
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ NodeSearcher nodeSearcher,
+ Map settings,
+ int flags) {
+ if (sourceUnit == null) {
+ throw new IllegalStateException();
+ }
+ CompilerOptions compilerOptions = new CompilerOptions(settings);
+ boolean statementsRecovery = (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+ compilerOptions.performMethodsFullRecovery = statementsRecovery;
+ compilerOptions.performStatementsRecovery = statementsRecovery;
+ compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+ Parser parser = new CommentRecorderParser(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ compilerOptions,
+ new DefaultProblemFactory()),
+ false);
+ CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+
+ if (compilationUnitDeclaration.ignoreMethodBodies) {
+ compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ return compilationUnitDeclaration;
+ }
+
+ if (nodeSearcher != null) {
+ char[] source = parser.scanner.getSource();
+ int searchPosition = nodeSearcher.position;
+ if (searchPosition < 0 || searchPosition > source.length) {
+ // the position is out of range. There is no need to search for a node.
+ return compilationUnitDeclaration;
+ }
+
+ compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);
+
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+ if (node == null) {
+ return compilationUnitDeclaration;
+ }
+
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
+ } else if (enclosingTypeDeclaration != null) {
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+ ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(parser, compilationUnitDeclaration);
+ }
+ }
+ } else {
+ //fill the methods bodies in order for the code to be generated
+ //real parse of the method....
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int j = 0, typeLength = types.length; j < typeLength; j++) {
+ types[j].parseMethods(parser, compilationUnitDeclaration);
+ }
+ }
+ }
+ return compilationUnitDeclaration;
+ }
+
+ public static void resolve(
+ ICompilationUnit[] compilationUnits,
+ String[] bindingKeys,
+ ASTRequestor requestor,
+ int apiLevel,
+ Map options,
+ IJavaProject javaProject,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) {
+
+ CancelableNameEnvironment environment = null;
+ CancelableProblemFactory problemFactory = null;
+ try {
+ if (monitor != null) {
+ int amountOfWork = (compilationUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
+ monitor.beginTask("", amountOfWork); //$NON-NLS-1$
+ }
+ environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
+ problemFactory = new CancelableProblemFactory(monitor);
+ CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+ compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+ CompilationUnitResolver resolver =
+ new CompilationUnitResolver(
+ environment,
+ getHandlingPolicy(),
+ compilerOptions,
+ getRequestor(),
+ problemFactory,
+ monitor);
+ resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
+ if (NameLookup.VERBOSE) {
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ } catch (JavaModelException e) {
+ // project doesn't exist -> simple parse without resolving
+ parse(compilationUnits, requestor, apiLevel, options, flags, monitor);
+ } finally {
+ if (monitor != null) monitor.done();
+ if (environment != null) {
+ environment.monitor = null; // don't hold a reference to this external object
+ }
+ if (problemFactory != null) {
+ problemFactory.monitor = null; // don't hold a reference to this external object
+ }
+ }
+ }
+ public static CompilationUnitDeclaration resolve(
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ IJavaProject javaProject,
+ NodeSearcher nodeSearcher,
+ Map options,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) throws JavaModelException {
+
+ CompilationUnitDeclaration unit = null;
+ CancelableNameEnvironment environment = null;
+ CancelableProblemFactory problemFactory = null;
+ CompilationUnitResolver resolver = null;
+ try {
+ environment = new CancelableNameEnvironment(((JavaProject)javaProject), owner, monitor);
+ problemFactory = new CancelableProblemFactory(monitor);
+ CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+ boolean ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+ compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
+ resolver =
+ new CompilationUnitResolver(
+ environment,
+ getHandlingPolicy(),
+ compilerOptions,
+ getRequestor(),
+ problemFactory,
+ monitor);
+ boolean analyzeAndGenerateCode = !ignoreMethodBodies;
+ unit =
+ resolver.resolve(
+ null, // no existing compilation unit declaration
+ sourceUnit,
+ nodeSearcher,
+ true, // method verification
+ analyzeAndGenerateCode, // analyze code
+ analyzeAndGenerateCode); // generate code
+ if (resolver.hasCompilationAborted) {
+ // the bindings could not be resolved due to missing types in name environment
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
+ CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
+ final int problemCount = unit.compilationResult.problemCount;
+ if (problemCount != 0) {
+ unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
+ System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
+ unitDeclaration.compilationResult.problemCount = problemCount;
+ }
+ return unitDeclaration;
+ }
+ if (NameLookup.VERBOSE) {
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return unit;
+ } finally {
+ if (environment != null) {
+ environment.monitor = null; // don't hold a reference to this external object
+ }
+ if (problemFactory != null) {
+ problemFactory.monitor = null; // don't hold a reference to this external object
+ }
+ // first unit cleanup is done by caller, but cleanup all enqueued requested units (not processed)
+// if (resolver != null) {
+// for (int i = 1; i < resolver.totalUnits; i++) { // could be more requested units
+// CompilationUnitDeclaration parsedUnit = resolver.unitsToProcess[i];
+// if (parsedUnit.scope != null)
+// parsedUnit.scope.faultInTypes(); // force resolution of signatures, so clients can query DOM AST
+// parsedUnit.cleanUp();
+// }
+// }
+ }
+ }
+ public static IBinding[] resolve(
+ final IJavaElement[] elements,
+ int apiLevel,
+ Map compilerOptions,
+ IJavaProject javaProject,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) {
+
+ final int length = elements.length;
+ final HashMap sourceElementPositions = new HashMap(); // a map from ICompilationUnit to int[] (positions in elements)
+ int cuNumber = 0;
+ final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
+ for (int i = 0; i < length; i++) {
+ IJavaElement element = elements[i];
+ if (!(element instanceof SourceRefElement))
+ throw new IllegalStateException(element + " is not part of a compilation unit or class file"); //$NON-NLS-1$
+ Object cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
+ if (cu != null) {
+ // source member
+ IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
+ if (intList == null) {
+ sourceElementPositions.put(cu, intList = new IntArrayList());
+ cuNumber++;
+ }
+ intList.add(i);
+ } else {
+ // binary member
+ try {
+ String key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
+ binaryElementPositions.put(key, i);
+ } catch (JavaModelException e) {
+ throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+ }
+ }
+ }
+ ICompilationUnit[] cus = new ICompilationUnit[cuNumber];
+ sourceElementPositions.keySet().toArray(cus);
+
+ int bindingKeyNumber = binaryElementPositions.size();
+ String[] bindingKeys = new String[bindingKeyNumber];
+ binaryElementPositions.keysToArray(bindingKeys);
+
+ class Requestor extends ASTRequestor {
+ IBinding[] bindings = new IBinding[length];
+ public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
+ // TODO (jerome) optimize to visit the AST only once
+ IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
+ for (int i = 0; i < intList.length; i++) {
+ final int index = intList.list[i];
+ SourceRefElement element = (SourceRefElement) elements[index];
+ DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
+ try {
+ finder.search();
+ } catch (JavaModelException e) {
+ throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+ }
+ this.bindings[index] = finder.foundBinding;
+ }
+ }
+ public void acceptBinding(String bindingKey, IBinding binding) {
+ int index = binaryElementPositions.get(bindingKey);
+ this.bindings[index] = binding;
+ }
+ }
+ Requestor requestor = new Requestor();
+ resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
+ return requestor.bindings;
+ }
+ /*
+ * When unit result is about to be accepted, removed back pointers
+ * to unresolved bindings
+ */
+ public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
+ final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int i = 0, max = types.length; i < max; i++) {
+ removeUnresolvedBindings(types[i]);
+ }
+ }
+ }
+ private void removeUnresolvedBindings(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type) {
+ final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
+ if (memberTypes != null) {
+ for (int i = 0, max = memberTypes.length; i < max; i++){
+ removeUnresolvedBindings(memberTypes[i]);
+ }
+ }
+ if (type.binding != null && (type.binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ type.binding = null;
+ }
+
+ final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
+ if (fields != null) {
+ for (int i = 0, max = fields.length; i < max; i++){
+ if (fields[i].binding != null && (fields[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ fields[i].binding = null;
+ }
+ }
+ }
+
+ final AbstractMethodDeclaration[] methods = type.methods;
+ if (methods != null) {
+ for (int i = 0, max = methods.length; i < max; i++){
+ if (methods[i].binding != null && (methods[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ methods[i].binding = null;
+ }
+ }
+ }
+ }
+
+ private void resolve(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor astRequestor, int apiLevel, Map compilerOptions, WorkingCopyOwner owner, int flags) {
+
+ // temporarily connect ourselves to the ASTResolver - must disconnect when done
+ astRequestor.compilationUnitResolver = this;
+ this.bindingTables = new DefaultBindingResolver.BindingTables();
+ CompilationUnitDeclaration unit = null;
+ try {
+ int length = compilationUnits.length;
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
+ System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
+//{ObjectTeams:
+ Dependencies.setup(this, this.parser, this.lookupEnvironment,
+ true/*verify*/, !this.options.ignoreMethodBodies/*analyze*/, !this.options.ignoreMethodBodies/*generate*/,
+ true, true, false);
+// SH+KM}
+
+ beginToCompile(sourceUnits, bindingKeys);
+ // process all units (some more could be injected in the loop by the lookup environment)
+ for (int i = 0; i < this.totalUnits; i++) {
+ if (resolvedRequestedSourcesAndKeys(i)) {
+ // no need to keep resolving if no more ASTs and no more binding keys are needed
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
+ // cleanup remaining units
+ for (; i < this.totalUnits; i++) {
+ this.unitsToProcess[i].cleanUp();
+ this.unitsToProcess[i] = null;
+ }
+ break;
+ }
+ unit = this.unitsToProcess[i];
+ try {
+ super.process(unit, i); // this.process(...) is optimized to not process already known units
+
+ // requested AST
+ char[] fileName = unit.compilationResult.getFileName();
+ ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
+ if (source != null) {
+ // convert AST
+ CompilationResult compilationResult = unit.compilationResult;
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
+ char[] contents = sourceUnit.getContents();
+ AST ast = AST.newAST(apiLevel);
+ ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
+ BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+ CompilationUnit compilationUnit = converter.convert(unit, contents);
+ compilationUnit.setTypeRoot(source);
+ compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+
+ // pass it to requestor
+ astRequestor.acceptAST(source, compilationUnit);
+
+ worked(1);
+
+ // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
+ this.requestedSources.put(fileName, null); // mark it as removed
+ }
+
+ // requested binding
+ Object key = this.requestedKeys.get(fileName);
+ if (key != null) {
+ if (key instanceof BindingKeyResolver) {
+ reportBinding(key, astRequestor, owner, unit);
+ worked(1);
+ } else if (key instanceof ArrayList) {
+ Iterator iterator = ((ArrayList) key).iterator();
+ while (iterator.hasNext()) {
+ reportBinding(iterator.next(), astRequestor, owner, unit);
+ worked(1);
+ }
+ }
+
+ // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
+ this.requestedKeys.put(fileName, null); // mark it as removed
+ }
+ } finally {
+ // cleanup compilation unit result
+ unit.cleanUp();
+ }
+ this.unitsToProcess[i] = null; // release reference to processed unit declaration
+ this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ }
+
+ // remaining binding keys
+ DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ Object[] keys = this.requestedKeys.valueTable;
+ for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
+ BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
+ if (keyResolver == null) continue;
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
+ // pass it to requestor
+ astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
+ worked(1);
+ }
+ } catch (OperationCanceledException e) {
+ throw e;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ // disconnect ourselves from ast requestor
+ astRequestor.compilationUnitResolver = null;
+//{ObjectTeams: restore:
+ Dependencies.release(this);
+// SH+KM}
+ }
+ }
+
+ private void reportBinding(Object key, ASTRequestor astRequestor, WorkingCopyOwner owner, CompilationUnitDeclaration unit) {
+ BindingKeyResolver keyResolver = (BindingKeyResolver) key;
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ if (compilerBinding != null) {
+ DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, false);
+ AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
+ IBinding binding;
+ if (annotationBinding != null) {
+ binding = resolver.getAnnotationInstance(annotationBinding);
+ } else {
+ binding = resolver.getBinding(compilerBinding);
+ }
+ if (binding != null)
+ astRequestor.acceptBinding(keyResolver.getKey(), binding);
+ }
+ }
+
+ private CompilationUnitDeclaration resolve(
+ CompilationUnitDeclaration unit,
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ NodeSearcher nodeSearcher,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ try {
+
+//{ObjectTeams:
+ Dependencies.setup(this, this.parser, this.lookupEnvironment,
+ verifyMethods, analyzeCode, generateCode, true, true, false);
+// SH}
+ if (unit == null) {
+ // build and record parsed units
+ this.parseThreshold = 0; // will request a full parse
+ beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
+ // process all units (some more could be injected in the loop by the lookup environment)
+//{ObjectTeams: due to role files the unit corresponding to sourceUnit need not be in position 0:
+/* orig:
+ unit = this.unitsToProcess[0];
+ :giro */
+ unit = findCorrespondingUnit(this.unitsToProcess, sourceUnit);
+// SH}
+ } else {
+ // initial type binding creation
+ this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
+
+ // binding resolution
+ this.lookupEnvironment.completeTypeBindings();
+ }
+
+ if (nodeSearcher == null) {
+ this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
+ } else {
+ int searchPosition = nodeSearcher.position;
+ char[] source = sourceUnit.getContents();
+ int length = source.length;
+ if (searchPosition >= 0 && searchPosition <= length) {
+ unit.traverse(nodeSearcher, unit.scope);
+
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+
+ if (node != null) {
+ // save existing values to restore them at the end of the parsing process
+ // see bug 47079 for more details
+ int[] oldLineEnds = this.parser.scanner.lineEnds;
+ int oldLinePtr = this.parser.scanner.linePtr;
+
+ this.parser.scanner.setSource(source, unit.compilationResult);
+
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
+ } else if (enclosingTypeDeclaration != null) {
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+ ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(this.parser, unit);
+ }
+ }
+ // this is done to prevent any side effects on the compilation unit result
+ // line separator positions array.
+ this.parser.scanner.lineEnds = oldLineEnds;
+ this.parser.scanner.linePtr = oldLinePtr;
+ }
+//{ObjectTeams: no more method bodies, have explicitly parsed those we need:
+ unit.parseMethodBodies = false;
+// SH}
+ }
+ }
+
+ if (unit.scope != null) {
+//{ObjectTeams: replace single step by Dependencies:
+/* orig:
+ // fault in fields & methods
+ unit.scope.faultInTypes();
+ if (unit.scope != null && verifyMethods) {
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+ // verify inherited methods
+ unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
+ }
+ // type checking
+ unit.resolve();
+
+ // flow analysis
+ if (analyzeCode) unit.analyseCode();
+
+ // code generation
+ if (generateCode) unit.generateCode();
+*/
+ if (generateCode)
+ Dependencies.ensureState(unit, ITranslationStates.STATE_BYTE_CODE_GENERATED);
+ else if (analyzeCode)
+ Dependencies.ensureState(unit, ITranslationStates.STATE_CODE_ANALYZED);
+ else
+ Dependencies.ensureState(unit, ITranslationStates.STATE_RESOLVED);
+// SH}
+
+ // finalize problems (suppressWarnings)
+ unit.finalizeProblems();
+ }
+ // TODO(SH): release also role file units!
+ if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
+ this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ return unit;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ return unit == null ? this.unitsToProcess[0] : unit;
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+//{ObjectTeams:
+ Dependencies.release(this);
+// SH}
+ // No reset is performed there anymore since,
+ // within the CodeAssist (or related tools),
+ // the compiler may be called *after* a call
+ // to this resolve(...) method. And such a call
+ // needs to have a compiler with a non-empty
+ // environment.
+ // this.reset();
+ }
+ }
+//{ObjectTeams: helper for above: a parsed unit need not be the first in declarations,
+// because a role file might have fetched its team.
+// So search through the array!
+ private CompilationUnitDeclaration findCorrespondingUnit(
+ CompilationUnitDeclaration[] declarations,
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit)
+ {
+ for(CompilationUnitDeclaration cud : declarations) {
+ if (CharOperation.equals(sourceUnit.getFileName(), cud.getFileName()))
+ return cud;
+ }
+ throw new InternalCompilerError("parsed unit not found in units: "+new String(sourceUnit.getFileName())); //$NON-NLS-1$
+ }
+// SH}
+
+ /*
+ * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ return resolve(
+ null, /* no existing compilation unit declaration*/
+ sourceUnit,
+ null/*no node searcher*/,
+ verifyMethods,
+ analyzeCode,
+ generateCode);
+ }
+
+ boolean resolvedRequestedSourcesAndKeys(int unitIndexToProcess) {
+ if (unitIndexToProcess < this.requestedSources.size() && unitIndexToProcess < this.requestedKeys.size())
+ return false; // must process at least this many units before checking to see if all are done
+
+ Object[] sources = this.requestedSources.valueTable;
+ for (int i = 0, l = sources.length; i < l; i++)
+ if (sources[i] != null) return false;
+ Object[] keys = this.requestedKeys.valueTable;
+ for (int i = 0, l = keys.length; i < l; i++)
+ if (keys[i] != null) return false;
+ return true;
+ }
+
+ /*
+ * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ CompilationUnitDeclaration unit,
+ org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ return resolve(
+ unit,
+ sourceUnit,
+ null/*no node searcher*/,
+ verifyMethods,
+ analyzeCode,
+ generateCode);
+ }
+
+ private void worked(int work) {
+ if (this.monitor != null) {
+ if (this.monitor.isCanceled())
+ throw new OperationCanceledException();
+ this.monitor.worked(work);
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java
new file mode 100644
index 000000000..633a985ac
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConditionalExpression.java
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Conditional expression AST node type.
+ *
+ * <pre>
+ * ConditionalExpression:
+ * Expression <b>?</b> Expression <b>:</b> Expression
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ConditionalExpression extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thenExpression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor THEN_EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "thenExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "elseExpression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor ELSE_EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "elseExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(ConditionalExpression.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(THEN_EXPRESSION_PROPERTY, properyList);
+ addProperty(ELSE_EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The condition expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression conditionExpression = null;
+
+ /**
+ * The "then" expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression thenExpression = null;
+
+ /**
+ * The "else" expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression elseExpression = null;
+
+ /**
+ * Creates a new unparented conditional expression node owned by the given
+ * AST. By default, the condition, "then", and "else" expresssions are
+ * unspecified, but legal.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ConditionalExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == THEN_EXPRESSION_PROPERTY) {
+ if (get) {
+ return getThenExpression();
+ } else {
+ setThenExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == ELSE_EXPRESSION_PROPERTY) {
+ if (get) {
+ return getElseExpression();
+ } else {
+ setElseExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONDITIONAL_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ConditionalExpression result = new ConditionalExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setThenExpression(
+ (Expression) getThenExpression().clone(target));
+ result.setElseExpression(
+ (Expression) getElseExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getThenExpression());
+ acceptChild(visitor, getElseExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the condition of this conditional expression.
+ *
+ * @return the condition node
+ */
+ public Expression getExpression() {
+ if (this.conditionExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.conditionExpression == null) {
+ preLazyInit();
+ this.conditionExpression = new SimpleName(this.ast);
+ postLazyInit(this.conditionExpression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.conditionExpression;
+ }
+
+ /**
+ * Sets the condition of this conditional expression.
+ *
+ * @param expression the condition node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.conditionExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.conditionExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "then" part of this conditional expression.
+ *
+ * @return the "then" expression node
+ */
+ public Expression getThenExpression() {
+ if (this.thenExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.thenExpression == null) {
+ preLazyInit();
+ this.thenExpression = new SimpleName(this.ast);
+ postLazyInit(this.thenExpression, THEN_EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.thenExpression;
+ }
+
+ /**
+ * Sets the "then" part of this conditional expression.
+ *
+ * @param expression the "then" expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setThenExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.thenExpression;
+ preReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+ this.thenExpression = expression;
+ postReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "else" part of this conditional expression.
+ *
+ * @return the "else" expression node
+ */
+ public Expression getElseExpression() {
+ if (this.elseExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.elseExpression == null) {
+ preLazyInit();
+ this.elseExpression = new SimpleName(this.ast);
+ postLazyInit(this.elseExpression, ELSE_EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.elseExpression;
+ }
+
+ /**
+ * Sets the "else" part of this conditional expression.
+ *
+ * @param expression the "else" expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setElseExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.elseExpression;
+ preReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+ this.elseExpression = expression;
+ postReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.conditionExpression == null ? 0 : getExpression().treeSize())
+ + (this.thenExpression == null ? 0 : getThenExpression().treeSize())
+ + (this.elseExpression == null ? 0 : getElseExpression().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java
new file mode 100644
index 000000000..69f5657ec
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ConstructorInvocation.java
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Alternate constructor invocation statement AST node type.
+ * For JLS2:
+ * <pre>
+ * ConstructorInvocation:
+ * <b>this</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * ConstructorInvocation:
+ * [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * <b>this</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ConstructorInvocation extends Statement {
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ConstructorInvocation.class, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(3);
+ createPropertyList(ConstructorInvocation.class, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an alternate constructor invocation statement
+ * owned by the given AST. By default, an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ConstructorInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONSTRUCTOR_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ConstructorInvocation result = new ConstructorInvocation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this constructor
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this alternate
+ * constructor invocation statement.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the constructor binding, or <code>null</code> if the binding
+ * cannot be resolved
+ */
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java
new file mode 100644
index 000000000..48fde2419
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ContinueStatement.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Continue statement AST node type.
+ *
+ * <pre>
+ * ContinueStatement:
+ * <b>continue</b> [ Identifier ] <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ContinueStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(ContinueStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ContinueStatement.class, properyList);
+ addProperty(LABEL_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label, or <code>null</code> if none; none by default.
+ */
+ private SimpleName optionalLabel = null;
+
+ /**
+ * Creates a new unparented continue statement node owned by the given
+ * AST. By default, the continue statement has no label.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ContinueStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONTINUE_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ContinueStatement result = new ContinueStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getLabel());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this continue statement, or <code>null</code> if
+ * there is none.
+ *
+ * @return the label, or <code>null</code> if there is none
+ */
+ public SimpleName getLabel() {
+ return this.optionalLabel;
+ }
+
+ /**
+ * Sets or clears the label of this continue statement.
+ *
+ * @param label the label, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setLabel(SimpleName label) {
+ ASTNode oldChild = this.optionalLabel;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.optionalLabel = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalLabel == null ? 0 : getLabel().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
new file mode 100644
index 000000000..d08c20151
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+/**
+ */
+class DefaultASTVisitor extends ASTVisitor {
+ /**
+ *
+ */
+ public DefaultASTVisitor() {
+ super();
+ }
+
+ /**
+ *
+ */
+ public DefaultASTVisitor(boolean visitDocTags) {
+ super(visitDocTags);
+ }
+
+ public void endVisit(AnnotationTypeDeclaration node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(AnnotationTypeMemberDeclaration node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(AnonymousClassDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ArrayAccess node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ArrayCreation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ArrayInitializer node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ArrayType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(AssertStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(Assignment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(Block node) {
+ endVisitNode(node);
+ }
+ /* since 3.0 */
+ public void endVisit(BlockComment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(BooleanLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(BreakStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CastExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CatchClause node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CharacterLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ClassInstanceCreation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CompilationUnit node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ConditionalExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ConstructorInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ContinueStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(DoStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EmptyStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EnhancedForStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EnumConstantDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EnumDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ExpressionStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FieldAccess node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FieldDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ForStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(IfStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ImportDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(InfixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(Initializer node) {
+ endVisitNode(node);
+ }
+ public void endVisit(InstanceofExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(Javadoc node) {
+ endVisitNode(node);
+ }
+ public void endVisit(LabeledStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(LineComment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MarkerAnnotation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MemberRef node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MemberValuePair node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MethodDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MethodInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MethodRef node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MethodRefParameter node) {
+ endVisitNode(node);
+ }
+ public void endVisit(NormalAnnotation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(NullLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(NumberLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PackageDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ParameterizedType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ParenthesizedExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PostfixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PrefixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PrimitiveType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(QualifiedName node) {
+ endVisitNode(node);
+ }
+ public void endVisit(QualifiedType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ReturnStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SimpleName node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SimpleType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SingleMemberAnnotation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SingleVariableDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(StringLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperConstructorInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperFieldAccess node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperMethodInvocation node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(SwitchCase node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SwitchStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SynchronizedStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TagElement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TextElement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ThisExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ThrowStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TryStatement node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(TypeDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeDeclarationStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeParameter node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationFragment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(WhileStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(WildcardType node) {
+ endVisitNode(node);
+ }
+ protected void endVisitNode(ASTNode node) {
+ // do nothing
+ }
+ public boolean visit(AnnotationTypeDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayAccess node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayCreation node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayInitializer node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayType node) {
+ visitNode(node);
+ return false;
+ }
+ public boolean visit(AssertStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(Assignment node) {
+ return visitNode(node);
+ }
+ public boolean visit(Block node) {
+ return visitNode(node);
+ }
+ /* since 3.0 */
+ public boolean visit(BlockComment node) {
+ return visitNode(node);
+ }
+ public boolean visit(BooleanLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(BreakStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(CastExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(CatchClause node) {
+ return visitNode(node);
+ }
+ public boolean visit(CharacterLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(ClassInstanceCreation node) {
+ return visitNode(node);
+ }
+ public boolean visit(CompilationUnit node) {
+ return visitNode(node);
+ }
+ public boolean visit(ConditionalExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(ConstructorInvocation node) {
+ return visitNode(node);
+ }
+ public boolean visit(ContinueStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(DoStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(EmptyStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(EnhancedForStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(EnumConstantDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(EnumDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ExpressionStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(FieldAccess node) {
+ return visitNode(node);
+ }
+ public boolean visit(FieldDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ForStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(IfStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(ImportDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(InfixExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(Initializer node) {
+ return visitNode(node);
+ }
+ public boolean visit(InstanceofExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(Javadoc node) {
+ // do not visit Javadoc tags by default. Use constructor with boolean to enable.
+ if (super.visit(node)) {
+ return visitNode(node);
+ }
+ return false;
+ }
+ public boolean visit(LabeledStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(LineComment node) {
+ return visitNode(node);
+ }
+ public boolean visit(MarkerAnnotation node) {
+ return visitNode(node);
+ }
+ public boolean visit(MemberRef node) {
+ return visitNode(node);
+ }
+ public boolean visit(MemberValuePair node) {
+ return visitNode(node);
+ }
+ public boolean visit(MethodDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(MethodInvocation node) {
+ return visitNode(node);
+ }
+ public boolean visit(MethodRef node) {
+ return visitNode(node);
+ }
+ public boolean visit(MethodRefParameter node) {
+ return visitNode(node);
+ }
+ public boolean visit(NormalAnnotation node) {
+ return visitNode(node);
+ }
+ public boolean visit(NullLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(NumberLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(PackageDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ParameterizedType node) {
+ return visitNode(node);
+ }
+ public boolean visit(ParenthesizedExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(PostfixExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(PrefixExpression node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(PrimitiveType node) {
+ return visitNode(node);
+ }
+ public boolean visit(QualifiedName node) {
+ return visitNode(node);
+ }
+ public boolean visit(QualifiedType node) {
+ return visitNode(node);
+ }
+ public boolean visit(ReturnStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(SimpleName node) {
+ return visitNode(node);
+ }
+ public boolean visit(SimpleType node) {
+ return visitNode(node);
+ }
+ public boolean visit(SingleMemberAnnotation node) {
+ return visitNode(node);
+ }
+ public boolean visit(SingleVariableDeclaration node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(StringLiteral node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SuperConstructorInvocation node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SuperFieldAccess node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SuperMethodInvocation node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SwitchCase node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SwitchStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(SynchronizedStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TagElement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TextElement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ThisExpression node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ThrowStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TryStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeDeclaration node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeDeclarationStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeLiteral node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeParameter node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(VariableDeclarationExpression node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(VariableDeclarationFragment node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(VariableDeclarationStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(WhileStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(WildcardType node) {
+ return visitNode(node);
+ }
+
+ protected boolean visitNode(ASTNode node) {
+ return true;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
new file mode 100644
index 000000000..1974eb14f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -0,0 +1,2030 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: DefaultBindingResolver.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.jdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Literal;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutScope;
+
+/**
+ * Internal class for resolving bindings using old ASTs.
+ * <p>
+ * IMPORTANT: The methods on this class are synchronized. This is required
+ * because there may be multiple clients in separate threads concurrently
+ * reading an AST and asking for bindings for its nodes. These requests all
+ * end up invoking instance methods on this class. There are various internal
+ * tables and caches which are built and maintained in the course of looking
+ * up bindings. To ensure that they remain coherent in the presence of multiple
+ * threads, the methods are synchronized on the DefaultBindingResolver instance.
+ * </p>
+ */
+class DefaultBindingResolver extends BindingResolver {
+
+ /*
+ * Holds on binding tables that can be shared by several ASTs.
+ */
+ static class BindingTables {
+
+ /**
+ * This map is used to get a binding from its binding key.
+ */
+ Map bindingKeysToBindings;
+ /**
+ * This map is used to keep the correspondance between new bindings and the
+ * compiler bindings as well as new annotation instances to their internal counterpart.
+ * This is an identity map. We should only create one object for one binding or annotation.
+ */
+ Map compilerBindingsToASTBindings;
+
+ BindingTables() {
+ this.compilerBindingsToASTBindings = new HashMap();
+ this.bindingKeysToBindings = new HashMap();
+ }
+
+ }
+ /**
+ * This map is used to retrieve the corresponding block scope for a ast node
+ */
+ Map astNodesToBlockScope;
+
+ /**
+ * This map is used to get an ast node from its binding (new binding) or DOM
+ */
+ Map bindingsToAstNodes;
+
+ /*
+ * The shared binding tables accros ASTs.
+ */
+ BindingTables bindingTables;
+
+ /**
+ * This map is used to retrieve an old ast node using the new ast node. This is not an
+ * identity map.
+ */
+ Map newAstToOldAst;
+
+ /**
+ * Compilation unit scope
+ */
+ private CompilationUnitScope scope;
+
+ /**
+ * The working copy owner that defines the context in which this resolver is creating the bindings.
+ */
+ WorkingCopyOwner workingCopyOwner;
+
+ /**
+ * Toggle controlling whether DOM bindings should be created when missing internal compiler bindings..
+ */
+ boolean isRecoveringBindings;
+
+ /**
+ * Constructor for DefaultBindingResolver.
+ */
+ DefaultBindingResolver(CompilationUnitScope scope, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
+ this.newAstToOldAst = new HashMap();
+ this.astNodesToBlockScope = new HashMap();
+ this.bindingsToAstNodes = new HashMap();
+ this.bindingTables = bindingTables;
+ this.scope = scope;
+ this.workingCopyOwner = workingCopyOwner;
+ this.isRecoveringBindings = isRecoveringBindings;
+ }
+
+ DefaultBindingResolver(LookupEnvironment lookupEnvironment, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
+ this.newAstToOldAst = new HashMap();
+ this.astNodesToBlockScope = new HashMap();
+ this.bindingsToAstNodes = new HashMap();
+ this.bindingTables = bindingTables;
+ this.scope = new CompilationUnitScope(new CompilationUnitDeclaration(null, null, -1), lookupEnvironment);
+ this.workingCopyOwner = workingCopyOwner;
+ this.isRecoveringBindings = isRecoveringBindings;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ASTNode findDeclaringNode(IBinding binding) {
+ if (binding == null) {
+ return null;
+ }
+ if (binding instanceof IMethodBinding) {
+ IMethodBinding methodBinding = (IMethodBinding) binding;
+//{ObjectTeams: searching a role method could be answered by a callout defining this method:
+/* orig:
+ return (ASTNode) this.bindingsToAstNodes.get(methodBinding.getMethodDeclaration());
+ :giro */
+ ASTNode result = (ASTNode) this.bindingsToAstNodes.get(methodBinding.getMethodDeclaration());
+ if (result == null) {
+ // search the declaring role for callout bindings
+ ASTNode typeNode = findDeclaringNode(methodBinding.getDeclaringClass());
+ if (typeNode instanceof RoleTypeDeclaration) {
+ RoleTypeDeclaration roleType = (RoleTypeDeclaration) typeNode;
+ for (Object bodyObj : roleType.bodyDeclarations()) {
+ if (bodyObj instanceof CalloutMappingDeclaration) {
+ // callout and method are considered "equal"
+ if (((CalloutMappingDeclaration) bodyObj).resolveBinding().isEqualTo(binding))
+ return (ASTNode)bodyObj;
+ }
+ }
+ }
+ }
+ return result;
+// SH}
+ } else if (binding instanceof ITypeBinding) {
+ ITypeBinding typeBinding = (ITypeBinding) binding;
+ return (ASTNode) this.bindingsToAstNodes.get(typeBinding.getTypeDeclaration());
+ } else if (binding instanceof IVariableBinding) {
+ IVariableBinding variableBinding = (IVariableBinding) binding;
+ return (ASTNode) this.bindingsToAstNodes.get(variableBinding.getVariableDeclaration());
+ }
+ return (ASTNode) this.bindingsToAstNodes.get(binding);
+ }
+
+ synchronized ASTNode findDeclaringNode(String bindingKey) {
+ if (bindingKey == null) {
+ return null;
+ }
+ Object binding = this.bindingTables.bindingKeysToBindings.get(bindingKey);
+ if (binding == null)
+ return null;
+ return (ASTNode) this.bindingsToAstNodes.get(binding);
+ }
+
+ IBinding getBinding(org.eclipse.jdt.internal.compiler.lookup.Binding binding) {
+ switch (binding.kind()) {
+ case Binding.PACKAGE:
+ return getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
+ case Binding.TYPE:
+ case Binding.BASE_TYPE:
+ case Binding.GENERIC_TYPE:
+ case Binding.PARAMETERIZED_TYPE:
+ case Binding.RAW_TYPE:
+ return getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ case Binding.ARRAY_TYPE:
+ case Binding.TYPE_PARAMETER:
+ return new TypeBinding(this, (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ case Binding.METHOD:
+ return getMethodBinding((org.eclipse.jdt.internal.compiler.lookup.MethodBinding) binding);
+ case Binding.FIELD:
+ case Binding.LOCAL:
+ return getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);
+ }
+ return null;
+ }
+
+ Util.BindingsToNodesMap getBindingsToNodesMap() {
+ return new Util.BindingsToNodesMap() {
+ public org.eclipse.jdt.internal.compiler.ast.ASTNode get(Binding binding) {
+ return (org.eclipse.jdt.internal.compiler.ast.ASTNode)
+ DefaultBindingResolver.this.newAstToOldAst.get(DefaultBindingResolver.this.bindingsToAstNodes.get(binding));
+ }
+ };
+ }
+
+ synchronized org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+ return (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IMethodBinding getMethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding) {
+ if (methodBinding != null && !methodBinding.isValidBinding()) {
+ org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding problemMethodBinding =
+ (org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) methodBinding;
+ methodBinding = problemMethodBinding.closestMatch;
+ }
+
+ if (methodBinding != null) {
+ if (!this.isRecoveringBindings && ((methodBinding.tagBits & TagBits.HasMissingType) != 0)) {
+ return null;
+ }
+ IMethodBinding binding = (IMethodBinding) this.bindingTables.compilerBindingsToASTBindings.get(methodBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new MethodBinding(this, methodBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(methodBinding, binding);
+ return binding;
+ }
+ return null;
+ }
+
+ synchronized IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) {
+ if (valuePair == null || valuePair.binding == null) return null;
+ IMemberValuePairBinding binding =
+ (IMemberValuePairBinding) this.bindingTables.compilerBindingsToASTBindings.get(valuePair);
+ if (binding != null)
+ return binding;
+ binding = new MemberValuePairBinding(valuePair, this);
+ this.bindingTables.compilerBindingsToASTBindings.put(valuePair, binding);
+ return binding;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IPackageBinding getPackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding) {
+ if (packageBinding == null) {
+ return null;
+ }
+ IPackageBinding binding = (IPackageBinding) this.bindingTables.compilerBindingsToASTBindings.get(packageBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new PackageBinding(packageBinding, this);
+ this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
+ return binding;
+ }
+ private int getTypeArguments(ParameterizedQualifiedTypeReference typeReference) {
+ TypeReference[][] typeArguments = typeReference.typeArguments;
+ int value = 0;
+ for (int i = 0, max = typeArguments.length; i < max; i++) {
+ if ((typeArguments[i] != null) || (value != 0)) {
+ value++;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given variable declaration.
+ * This is used for recovered binding only.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param variableDeclaration the given variable declaration
+ * @return the new type binding
+ */
+ synchronized ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableDeclaration);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new RecoveredTypeBinding(this, variableDeclaration);
+ this.bindingTables.compilerBindingsToASTBindings.put(variableDeclaration, binding);
+ return binding;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given type.
+ * This is used for recovered binding only.
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param type the given type
+ * @return the new type binding
+ */
+ synchronized ITypeBinding getTypeBinding(Type type) {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(type);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new RecoveredTypeBinding(this, type);
+ this.bindingTables.compilerBindingsToASTBindings.put(type, binding);
+ return binding;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+ if (referenceBinding == null) {
+ return null;
+ } else if (!referenceBinding.isValidBinding()) {
+ switch(referenceBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ if (referenceBinding instanceof ProblemReferenceBinding) {
+ ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding2 = problemReferenceBinding.closestMatch();
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(binding2);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new TypeBinding(this, binding2);
+ this.bindingTables.compilerBindingsToASTBindings.put(binding2, binding);
+ return binding;
+ }
+ break;
+ case ProblemReasons.NotFound :
+ if (!this.isRecoveringBindings) {
+ return null;
+ }
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+ if (binding != null) {
+ return binding;
+ }
+ if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0) {
+ binding = new TypeBinding(this, referenceBinding);
+ } else {
+ binding = new RecoveredTypeBinding(this, referenceBinding);
+ }
+ this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+ return binding;
+ }
+ return null;
+ } else {
+ if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0 && !this.isRecoveringBindings) {
+ return null;
+ }
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new TypeBinding(this, referenceBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+ return binding;
+ }
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+ if (recoveredTypeBinding== null) {
+ return null;
+ }
+ return new RecoveredTypeBinding(this, recoveredTypeBinding, dimensions);
+ }
+
+ synchronized IVariableBinding getVariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding variableBinding, VariableDeclaration variableDeclaration) {
+ if (this.isRecoveringBindings) {
+ if (variableBinding != null) {
+ if (variableBinding.isValidBinding()) {
+ IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+ if (binding != null) {
+ return binding;
+ }
+ if (variableBinding.type != null) {
+ binding = new VariableBinding(this, variableBinding);
+ } else {
+ binding = new RecoveredVariableBinding(this, variableDeclaration);
+ }
+ this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+ return binding;
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (variableBinding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ return this.getVariableBinding(variableBinding);
+ }
+
+ public WorkingCopyOwner getWorkingCopyOwner() {
+ return this.workingCopyOwner;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IVariableBinding getVariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding variableBinding) {
+ if (variableBinding != null) {
+ if (variableBinding.isValidBinding()) {
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding variableType = variableBinding.type;
+ if (variableType != null) {
+ if (!this.isRecoveringBindings && ((variableType.tagBits & TagBits.HasMissingType) != 0)) {
+ return null;
+ }
+ IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new VariableBinding(this, variableBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+ return binding;
+ }
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (variableBinding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ synchronized IAnnotationBinding getAnnotationInstance(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalInstance) {
+ if (internalInstance == null) return null;
+ ReferenceBinding annotationType = internalInstance.getAnnotationType();
+ if (!this.isRecoveringBindings) {
+ if (annotationType == null || ((annotationType.tagBits & TagBits.HasMissingType) != 0)) {
+ return null;
+ }
+ }
+ IAnnotationBinding domInstance =
+ (IAnnotationBinding) this.bindingTables.compilerBindingsToASTBindings.get(internalInstance);
+ if (domInstance != null)
+ return domInstance;
+ domInstance = new AnnotationBinding(internalInstance, this);
+ this.bindingTables.compilerBindingsToASTBindings.put(internalInstance, domInstance);
+ return domInstance;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(MethodInvocation methodInvocation) {
+ Object oldNode = this.newAstToOldAst.get(methodInvocation);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+ if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+ ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+ return genericMethodBinding.inferredReturnType;
+ }
+ }
+ return false;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation superMethodInvocation) {
+ Object oldNode = this.newAstToOldAst.get(superMethodInvocation);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+ if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+ ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+ return genericMethodBinding.inferredReturnType;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ LookupEnvironment lookupEnvironment() {
+ return this.scope.environment();
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
+ */
+ synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
+ this.astNodesToBlockScope.put(astNode, blockScope);
+ }
+
+ /*
+ * @see BindingResolver#resolveBoxing(Expression)
+ */
+ boolean resolveBoxing(Expression expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+ org.eclipse.jdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.jdt.internal.compiler.ast.Expression) node;
+ return (compilerExpression.implicitConversion & TypeIds.BOXING) != 0;
+ }
+ return false;
+ }
+
+ /*
+ * @see BindingResolver#resolveUnboxing(Expression)
+ */
+ boolean resolveUnboxing(Expression expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+ org.eclipse.jdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.jdt.internal.compiler.ast.Expression) node;
+ return (compilerExpression.implicitConversion & TypeIds.UNBOXING) != 0;
+ }
+ return false;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstantExpressionValue(Expression)
+ */
+ Object resolveConstantExpressionValue(Expression expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.Expression) {
+ org.eclipse.jdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.jdt.internal.compiler.ast.Expression) node;
+ Constant constant = compilerExpression.constant;
+ if (constant != null && constant != Constant.NotAConstant) {
+ switch (constant.typeID()) {
+ case TypeIds.T_int : return new Integer(constant.intValue());
+ case TypeIds.T_byte : return new Byte(constant.byteValue());
+ case TypeIds.T_short : return new Short(constant.shortValue());
+ case TypeIds.T_char : return new Character(constant.charValue());
+ case TypeIds.T_float : return new Float(constant.floatValue());
+ case TypeIds.T_double : return new Double(constant.doubleValue());
+ case TypeIds.T_boolean : return constant.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+ case TypeIds.T_long : return new Long(constant.longValue());
+ case TypeIds.T_JavaLangString : return constant.stringValue();
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
+ */
+ synchronized IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ return getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
+ } else if (node instanceof AllocationExpression) {
+ return getMethodBinding(((AllocationExpression)node).binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(ConstructorInvocation)
+ */
+ synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof ExplicitConstructorCall) {
+ ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+ return getMethodBinding(explicitConstructorCall.binding);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.BindingResolver#resolveConstructor(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+ */
+ IMethodBinding resolveConstructor(EnumConstantDeclaration enumConstantDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(enumConstantDeclaration);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+ if (fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT && fieldDeclaration.initialization != null) {
+ AllocationExpression allocationExpression = (AllocationExpression) fieldDeclaration.initialization;
+ return getMethodBinding(allocationExpression.binding);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
+ */
+ synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof ExplicitConstructorCall) {
+ ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+ return getMethodBinding(explicitConstructorCall.binding);
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveExpressionType(Expression expression) {
+ try {
+ switch(expression.getNodeType()) {
+ case ASTNode.CLASS_INSTANCE_CREATION :
+ org.eclipse.jdt.internal.compiler.ast.ASTNode astNode = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (astNode instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ // anonymous type case
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) astNode;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } else if (astNode instanceof AllocationExpression) {
+ // should be an AllocationExpression
+ AllocationExpression allocationExpression = (AllocationExpression) astNode;
+ return this.getTypeBinding(allocationExpression.resolvedType);
+ }
+ break;
+ case ASTNode.SIMPLE_NAME :
+ case ASTNode.QUALIFIED_NAME :
+ return resolveTypeBindingForName((Name) expression);
+ case ASTNode.ARRAY_INITIALIZER :
+ case ASTNode.ARRAY_CREATION :
+ case ASTNode.ASSIGNMENT :
+ case ASTNode.POSTFIX_EXPRESSION :
+ case ASTNode.PREFIX_EXPRESSION :
+ case ASTNode.CAST_EXPRESSION :
+ case ASTNode.TYPE_LITERAL :
+ case ASTNode.INFIX_EXPRESSION :
+ case ASTNode.INSTANCEOF_EXPRESSION :
+ case ASTNode.FIELD_ACCESS :
+ case ASTNode.SUPER_FIELD_ACCESS :
+ case ASTNode.ARRAY_ACCESS :
+ case ASTNode.METHOD_INVOCATION :
+ case ASTNode.SUPER_METHOD_INVOCATION :
+ case ASTNode.CONDITIONAL_EXPRESSION :
+ case ASTNode.MARKER_ANNOTATION :
+ case ASTNode.NORMAL_ANNOTATION :
+ case ASTNode.SINGLE_MEMBER_ANNOTATION :
+ org.eclipse.jdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(expression);
+ if (compilerExpression != null) {
+ return this.getTypeBinding(compilerExpression.resolvedType);
+ }
+ break;
+ case ASTNode.STRING_LITERAL :
+ if (this.scope != null) {
+ return this.getTypeBinding(this.scope.getJavaLangString());
+ }
+ break;
+ case ASTNode.BOOLEAN_LITERAL :
+ case ASTNode.NULL_LITERAL :
+ case ASTNode.CHARACTER_LITERAL :
+ case ASTNode.NUMBER_LITERAL :
+ Literal literal = (Literal) this.newAstToOldAst.get(expression);
+ if (literal != null) {
+ return this.getTypeBinding(literal.literalType(null));
+ }
+ break;
+ case ASTNode.THIS_EXPRESSION :
+ ThisReference thisReference = (ThisReference) this.newAstToOldAst.get(expression);
+ BlockScope blockScope = (BlockScope) this.astNodesToBlockScope.get(expression);
+ if (blockScope != null) {
+//{ObjectTeams: calling into the compiler needs dependencies configured:
+ Dependencies.setup(this, null, lookupEnvironment(), false, false, false, true, true, false);
+ try {
+// orig:
+ return this.getTypeBinding(thisReference.resolveType(blockScope));
+// :giro
+ } finally {
+ Dependencies.release(this);
+ }
+// SH}
+ }
+ break;
+ case ASTNode.PARENTHESIZED_EXPRESSION :
+ ParenthesizedExpression parenthesizedExpression = (ParenthesizedExpression) expression;
+ return resolveExpressionType(parenthesizedExpression.getExpression());
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
+ Type type = variableDeclarationExpression.getType();
+ if (type != null) {
+ return type.resolveBinding();
+ }
+ break;
+ }
+ } catch (AbortCompilation e) {
+ // handle missing types
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveField(FieldAccess)
+ */
+ synchronized IVariableBinding resolveField(FieldAccess fieldAccess) {
+ Object oldNode = this.newAstToOldAst.get(fieldAccess);
+ if (oldNode instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) oldNode;
+ return this.getVariableBinding(fieldReference.binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveField(SuperFieldAccess)
+ */
+ synchronized IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+ Object oldNode = this.newAstToOldAst.get(fieldAccess);
+ if (oldNode instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) oldNode;
+ return this.getVariableBinding(fieldReference.binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveImport(ImportDeclaration)
+ */
+ synchronized IBinding resolveImport(ImportDeclaration importDeclaration) {
+ if (this.scope == null) return null;
+ try {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(importDeclaration);
+ if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ final boolean isStatic = importReference.isStatic();
+ if ((importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0) {
+ Binding binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length), true, isStatic);
+ if (binding != null) {
+ if (isStatic) {
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ return typeBinding == null ? null : typeBinding;
+ }
+ } else {
+ if ((binding.kind() & Binding.PACKAGE) != 0) {
+ IPackageBinding packageBinding = getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
+ if (packageBinding == null) {
+ return null;
+ }
+ return packageBinding;
+ } else {
+ // if it is not a package, it has to be a type
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ return typeBinding;
+ }
+ }
+ }
+ } else {
+ Binding binding = this.scope.getImport(importReference.tokens, false, isStatic);
+ if (binding != null) {
+ if (isStatic) {
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ return typeBinding == null ? null : typeBinding;
+ } else if (binding instanceof FieldBinding) {
+ IVariableBinding variableBinding = this.getVariableBinding((FieldBinding) binding);
+ return variableBinding == null ? null : variableBinding;
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding) {
+ // it is a type
+ return getMethodBinding((org.eclipse.jdt.internal.compiler.lookup.MethodBinding)binding);
+ }
+ } else {
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding);
+ return typeBinding == null ? null : typeBinding;
+ }
+ }
+ }
+ }
+ }
+ } catch(AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.BindingResolver#resolveMember(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
+ */
+ IMethodBinding resolveMember(AnnotationTypeMemberDeclaration declaration) {
+ Object oldNode = this.newAstToOldAst.get(declaration);
+ if (oldNode instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+ IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding);
+ if (methodBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(methodBinding, declaration);
+ String key = methodBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
+ }
+ return methodBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IMethodBinding resolveMethod(MethodDeclaration method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+ IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding);
+ if (methodBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(methodBinding, method);
+ String key = methodBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
+ }
+ return methodBinding;
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IMethodBinding resolveMethod(MethodInvocation method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ return getMethodBinding(messageSend.binding);
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ return getMethodBinding(messageSend.binding);
+ }
+ return null;
+ }
+
+//{ObjectTeams: resolve bindings for OT-specific nodes
+
+ synchronized IMethodBinding resolveConstructor(BaseConstructorInvocation constructor)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(constructor);
+ if (node instanceof BaseAllocationExpression)
+ {
+ BaseAllocationExpression baseAllocExpr =
+ (BaseAllocationExpression)node;
+ AllocationExpression allocExpr =
+ (AllocationExpression)baseAllocExpr.expression;
+ return this.getMethodBinding(allocExpr.binding);
+ }
+ return null;
+ }
+
+ synchronized IMethodBinding resolveConstructor(TSuperConstructorInvocation constructor)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode)this.newAstToOldAst.get(constructor);
+ if (node instanceof ExplicitConstructorCall)
+ {
+ ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall)node;
+ return this.getMethodBinding(explicitConstructorCall.binding.copyInheritanceSrc);
+ }
+ return null;
+ }
+
+ synchronized IMethodBinding resolveMethod(org.eclipse.jdt.core.dom.BaseCallMessageSend method)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode)this.newAstToOldAst.get(method);
+ if (node instanceof BaseCallMessageSend)
+ {
+ BaseCallMessageSend baseCall = (BaseCallMessageSend)node;
+ return this.getMethodBinding(baseCall.getMessageSend().binding);
+ }
+ return null;
+ }
+
+ synchronized IMethodBinding resolveMethod(org.eclipse.jdt.core.dom.MethodSpec method)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode)this.newAstToOldAst.get(method);
+
+ if (node instanceof MethodSpec)
+ {
+ MethodSpec methodSpec = (MethodSpec)node;
+ return this.getMethodBinding(methodSpec.resolvedMethod);
+ }
+ return null;
+ }
+
+ synchronized IMethodBinding resolveMethod(org.eclipse.jdt.core.dom.TSuperMessageSend method)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode)this.newAstToOldAst.get(method);
+ if (node instanceof TSuperMessageSend)
+ {
+ TSuperMessageSend msgSend = (TSuperMessageSend)node;
+ return this.getMethodBinding(msgSend.binding.copyInheritanceSrc);
+ }
+ return null;
+ }
+
+ synchronized IMethodMappingBinding resolveMethodMapping(org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration mapping)
+ {
+ Object oldNode = this.newAstToOldAst.get(mapping);
+ if (oldNode instanceof AbstractMethodMappingDeclaration) {
+ AbstractMethodMappingDeclaration mappingDeclaration = (AbstractMethodMappingDeclaration) oldNode;
+ IMethodMappingBinding mappingBinding = this.getMethodMappingBinding(mappingDeclaration.binding);
+ if (mappingBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(mappingBinding, mapping);
+ String key = mappingBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, mappingBinding);
+ }
+ if (mappingDeclaration.isCallout() && mappingBinding.getRoleMethod() != null) {
+ // if role method is not present, register the callout for its stake:
+ key = mappingBinding.getRoleMethod().getKey();
+ if (!this.bindingTables.bindingKeysToBindings.containsKey(key))
+ this.bindingTables.bindingKeysToBindings.put(key, mappingBinding);
+ }
+ return mappingBinding;
+ }
+ return null;
+ }
+
+
+
+ synchronized IVariableBinding resolveVariable(org.eclipse.jdt.core.dom.FieldAccessSpec field)
+ {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node =
+ (org.eclipse.jdt.internal.compiler.ast.ASTNode)this.newAstToOldAst.get(field);
+ if (node instanceof FieldAccessSpec)
+ {
+ FieldAccessSpec fieldAccessSpec = (FieldAccessSpec)node;
+ return this.getVariableBinding(fieldAccessSpec.resolvedField);
+ }
+ return null;
+ }
+//mkr}
+
+ synchronized ITypeBinding resolveTypeBindingForName(Name name) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+ int index = name.index;
+ if (node instanceof QualifiedNameReference) {
+ QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+ final char[][] tokens = qualifiedNameReference.tokens;
+ if (tokens.length == index) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ }
+ int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+ if (index < indexOfFirstFieldBinding) {
+ // an extra lookup is required
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ return null;
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ } else if (index == indexOfFirstFieldBinding) {
+ if (qualifiedNameReference.isTypeReference()) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ } else {
+ // in this case we want to get the next field declaring's class
+ if (qualifiedNameReference.otherBindings == null) {
+ return null;
+ }
+ FieldBinding fieldBinding = qualifiedNameReference.otherBindings[0];
+ if (fieldBinding == null) return null;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+ if (type == null) { // array length scenario
+ // use type from first binding (no capture needed for array type)
+ switch (qualifiedNameReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.RestrictiveFlagMASK) {
+ case Binding.FIELD:
+ type = ((FieldBinding) qualifiedNameReference.binding).type;
+ break;
+ case Binding.LOCAL:
+ type = ((LocalVariableBinding) qualifiedNameReference.binding).type;
+ break;
+ }
+ }
+ return this.getTypeBinding(type);
+ }
+ } else {
+ /* This is the case for a name which is part of a qualified name that
+ * cannot be resolved. See PR 13063.
+ */
+ if (qualifiedNameReference.otherBindings == null) return null;
+ final int otherBindingsLength = qualifiedNameReference.otherBindings.length;
+ if (otherBindingsLength == (index - indexOfFirstFieldBinding)) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ }
+ FieldBinding fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding];
+ if (fieldBinding == null) return null;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+ if (type == null) { // array length scenario
+ // use type from previous binding (no capture needed for array type)
+ fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1];
+ if (fieldBinding == null) return null;
+ type = fieldBinding.type;
+ }
+ return this.getTypeBinding(type);
+ }
+ } else if (node instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+ if (qualifiedTypeReference.resolvedType == null) {
+ return null;
+ }
+ if (index == qualifiedTypeReference.tokens.length) {
+ if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return null;
+ }
+ }
+ return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+ } else {
+ if (index >= 0) {
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ return null;
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ int importReferenceLength = importReference.tokens.length;
+ if (index >= 0) {
+ Binding binding = null;
+ if (this.scope == null) return null;
+ if (importReferenceLength == index) {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ } else {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ }
+ if (binding != null) {
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ return null;
+ }
+ }
+ } else if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ IMethodBinding method = getMethodBinding(methodDeclaration.binding);
+ if (method == null) return null;
+ return method.getReturnType();
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } if (node instanceof JavadocSingleNameReference) {
+ JavadocSingleNameReference singleNameReference = (JavadocSingleNameReference) node;
+ LocalVariableBinding localVariable = (LocalVariableBinding)singleNameReference.binding;
+ if (localVariable != null) {
+ return this.getTypeBinding(localVariable.type);
+ }
+ } if (node instanceof SingleNameReference) {
+ SingleNameReference singleNameReference = (SingleNameReference) node;
+ return this.getTypeBinding(singleNameReference.resolvedType);
+ } else if (node instanceof QualifiedSuperReference) {
+ QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
+ return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
+ } else if (node instanceof LocalDeclaration) {
+ IVariableBinding variable = this.getVariableBinding(((LocalDeclaration)node).binding);
+ if (variable == null) return null;
+ return variable.getType();
+ } else if (node instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding).getReturnType();
+ }
+ return getTypeBinding(fieldRef.resolvedType);
+ } else if (node instanceof FieldReference) {
+ return getTypeBinding(((FieldReference) node).resolvedType);
+ } else if (node instanceof SingleTypeReference) {
+ SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+ if (binding != null) {
+ return this.getTypeBinding(binding.leafComponentType());
+ }
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+ IVariableBinding field = this.getVariableBinding(fieldDeclaration.binding);
+ if (field == null) return null;
+ return field.getType();
+ } else if (node instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) node;
+ IMethodBinding method = getMethodBinding(messageSend.binding);
+ if (method == null) return null;
+ return method.getReturnType();
+ } else if (node instanceof AllocationExpression) {
+ AllocationExpression allocation = (AllocationExpression) node;
+ return getTypeBinding(allocation.resolvedType);
+ } else if (node instanceof JavadocImplicitTypeReference) {
+ JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+ return getTypeBinding(implicitRef.resolvedType);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeParameter) {
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter = (org.eclipse.jdt.internal.compiler.ast.TypeParameter) node;
+ return this.getTypeBinding(typeParameter.binding);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.MemberValuePair) {
+ org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair = (org.eclipse.jdt.internal.compiler.ast.MemberValuePair) node;
+ IMethodBinding method = getMethodBinding(memberValuePair.binding);
+ if (method == null) return null;
+ return method.getReturnType();
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IBinding resolveName(Name name) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+ int index = name.index;
+ if (node instanceof QualifiedNameReference) {
+ QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+ final char[][] tokens = qualifiedNameReference.tokens;
+ int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+ if (index < indexOfFirstFieldBinding) {
+ // an extra lookup is required
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ return getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ } else if (index == indexOfFirstFieldBinding) {
+ if (qualifiedNameReference.isTypeReference()) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ } else {
+ Binding binding = qualifiedNameReference.binding;
+ if (binding != null) {
+ if (binding.isValidBinding()) {
+ return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);
+ } else if (binding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ if (declaringClass != null) {
+ FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
+ if (exactBinding != null) {
+ if (exactBinding.type != null) {
+ IVariableBinding variableBinding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding != null) {
+ return variableBinding;
+ }
+ variableBinding = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
+ return variableBinding;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ /* This is the case for a name which is part of a qualified name that
+ * cannot be resolved. See PR 13063.
+ */
+ if (qualifiedNameReference.otherBindings == null || (index - indexOfFirstFieldBinding - 1) < 0) {
+ return null;
+ } else {
+ return this.getVariableBinding(qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1]);
+ }
+ }
+ } else if (node instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+ if (qualifiedTypeReference.resolvedType == null) {
+ return null;
+ }
+ if (index == qualifiedTypeReference.tokens.length) {
+ if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return getPackageBinding(typeRef.packageBinding);
+ }
+ }
+ return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+ } else {
+ if (index >= 0) {
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ return getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ int importReferenceLength = importReference.tokens.length;
+ if (index >= 0) {
+ Binding binding = null;
+ if (this.scope == null) return null;
+ if (importReferenceLength == index) {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ } else {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ }
+ if (binding != null) {
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ return getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)binding);
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.FieldBinding) {
+ // it is a type
+ return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.FieldBinding)binding);
+ } else if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding) {
+ // it is a type
+ return getMethodBinding((org.eclipse.jdt.internal.compiler.lookup.MethodBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof CompilationUnitDeclaration) {
+ CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types == null || types.length == 0) {
+ return null;
+ }
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type = types[0];
+ if (type != null) {
+ ITypeBinding typeBinding = this.getTypeBinding(type.binding);
+ if (typeBinding != null) {
+ return typeBinding.getPackage();
+ }
+ }
+ } else if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding);
+ if (methodBinding != null) {
+ return methodBinding;
+ }
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } if (node instanceof SingleNameReference) {
+ SingleNameReference singleNameReference = (SingleNameReference) node;
+ if (singleNameReference.isTypeReference()) {
+ return this.getTypeBinding(singleNameReference.resolvedType);
+ } else {
+ // this is a variable or a field
+ Binding binding = singleNameReference.binding;
+//{ObjectTeams: if binding is an internal local variable of a callin/callout wrapper try to find the actual surface element:
+ binding = CallinCalloutScope.maybeReResolveReference(singleNameReference, binding);
+// SH}
+ if (binding != null) {
+ if (binding.isValidBinding()) {
+ return this.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (binding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ if (exactBinding.type != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else if (node instanceof QualifiedSuperReference) {
+ QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
+ return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
+ } else if (node instanceof LocalDeclaration) {
+ return this.getVariableBinding(((LocalDeclaration)node).binding);
+ } else if (node instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding);
+ }
+ return getVariableBinding(fieldRef.binding);
+ } else if (node instanceof FieldReference) {
+ return getVariableBinding(((FieldReference) node).binding);
+ } else if (node instanceof SingleTypeReference) {
+ if (node instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return getPackageBinding(typeRef.packageBinding);
+ }
+ }
+ SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+ if (binding == null) {
+ return null;
+ }
+ return this.getTypeBinding(binding.leafComponentType());
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+ return this.getVariableBinding(fieldDeclaration.binding);
+ } else if (node instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) node;
+ return getMethodBinding(messageSend.binding);
+ } else if (node instanceof AllocationExpression) {
+ AllocationExpression allocation = (AllocationExpression) node;
+ return getMethodBinding(allocation.binding);
+ } else if (node instanceof JavadocImplicitTypeReference) {
+ JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+ return getTypeBinding(implicitRef.resolvedType);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeParameter) {
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter = (org.eclipse.jdt.internal.compiler.ast.TypeParameter) node;
+ return this.getTypeBinding(typeParameter.binding);
+ } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.MemberValuePair) {
+ org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair = (org.eclipse.jdt.internal.compiler.ast.MemberValuePair) node;
+ return getMethodBinding(memberValuePair.binding);
+ }
+//{ObjectTeams: Resolve bindings for OT-specific elements
+ else if (node instanceof MethodSpec)
+ {
+ if (!(node instanceof FieldAccessSpec))
+ {
+ MethodSpec methodSpec = (MethodSpec)node;
+ return getMethodBinding(methodSpec.resolvedMethod);
+ }
+ else
+ {
+ FieldAccessSpec fieldAccessSpec = (FieldAccessSpec) node;
+ return getVariableBinding(fieldAccessSpec.resolvedField);
+ }
+ }
+ else if (node instanceof LiftingTypeReference)
+ {
+ LiftingTypeReference liftingTypeRef = (LiftingTypeReference)node;
+ return getTypeBinding(liftingTypeRef.resolvedType);
+ }
+//jsv}
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolvePackage(PackageDeclaration)
+ */
+ synchronized IPackageBinding resolvePackage(PackageDeclaration pkg) {
+ if (this.scope == null) return null;
+ try {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
+ if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
+ if ((binding != null) && (binding.isValidBinding())) {
+ if (binding instanceof ReferenceBinding) {
+ // this only happens if a type name has the same name as its package
+ ReferenceBinding referenceBinding = (ReferenceBinding) binding;
+//{ObjectTeams: team packages replace the team type with the package
+ binding= referenceBinding.teamPackage;
+ if (binding == null) // only if team package didn't work go back to JDT strategy:
+// SH}
+ binding = referenceBinding.fPackage;
+ }
+ if (binding instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
+ IPackageBinding packageBinding = getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
+ if (packageBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(packageBinding, pkg);
+ String key = packageBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, packageBinding);
+ }
+ return packageBinding;
+ }
+ }
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see BindingResolver#resolveReference(MemberRef)
+ * @since 3.0
+ */
+ synchronized IBinding resolveReference(MemberRef ref) {
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+ if (expression instanceof TypeReference) {
+ return getTypeBinding(expression.resolvedType);
+ } else if (expression instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) expression;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding);
+ }
+ return getVariableBinding(fieldRef.binding);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see BindingResolver#resolveMemberValuePair(MemberValuePair)
+ * @since 3.2
+ */
+ synchronized IMemberValuePairBinding resolveMemberValuePair(org.eclipse.jdt.core.dom.MemberValuePair memberValuePair) {
+ MemberValuePair valuePair = (MemberValuePair) this.newAstToOldAst.get(memberValuePair);
+ if (valuePair != null) {
+ return getMemberValuePairBinding(valuePair.compilerElementPair);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see BindingResolver#resolveReference(MethodRef)
+ * @since 3.0
+ */
+ synchronized IBinding resolveReference(MethodRef ref) {
+ org.eclipse.jdt.internal.compiler.ast.Expression expression = (org.eclipse.jdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+ if (expression instanceof JavadocMessageSend) {
+ return getMethodBinding(((JavadocMessageSend)expression).binding);
+ }
+ else if (expression instanceof JavadocAllocationExpression) {
+ return getMethodBinding(((JavadocAllocationExpression)expression).binding);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
+ */
+ ITypeBinding resolveType(AnnotationTypeDeclaration type) {
+ final Object node = this.newAstToOldAst.get(type);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+ /*
+ * @see BindingResolver#resolveType(AnonymousClassDeclaration)
+ */
+ synchronized ITypeBinding resolveType(AnonymousClassDeclaration type) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+ if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(anonymousLocalTypeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.EnumDeclaration)
+ */
+ ITypeBinding resolveType(EnumDeclaration type) {
+ final Object node = this.newAstToOldAst.get(type);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveType(Type type) {
+ // retrieve the old ast node
+ org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = null;
+ if (node != null) {
+ if (node instanceof ParameterizedQualifiedTypeReference) {
+ ParameterizedQualifiedTypeReference typeReference = (ParameterizedQualifiedTypeReference) node;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding = typeReference.resolvedType;
+ int index;
+ if (type.isQualifiedType()) {
+ index = ((QualifiedType) type).index;
+ } else if (type.isParameterizedType()) {
+ index = ((ParameterizedType) type).index;
+ } else {
+ index = 1;
+ }
+ final int numberOfTypeArgumentsNotNull = getTypeArguments(typeReference);
+ if (index != numberOfTypeArgumentsNotNull) {
+ int i = numberOfTypeArgumentsNotNull;
+ while (i != index) {
+ typeBinding = typeBinding.enclosingType();
+ i --;
+ }
+ binding = typeBinding;
+ } else {
+ binding = typeBinding;
+ }
+ } else if (node instanceof TypeReference) {
+ TypeReference typeReference = (TypeReference) node;
+ binding = typeReference.resolvedType;
+ } else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
+ binding = (((SingleNameReference)node).resolvedType);
+ } else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
+ binding = (((QualifiedNameReference)node).resolvedType);
+ } else if (node instanceof ArrayAllocationExpression) {
+ binding = ((ArrayAllocationExpression) node).resolvedType;
+ }
+ if (binding != null) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ if (this.scope == null) return null;
+ if (binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+ } else {
+ return getTypeBinding(this.scope.createArrayType(binding, arrayType.getDimensions()));
+ }
+ } else {
+ if (binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return getTypeBinding(arrayBinding.leafComponentType);
+ } else {
+ return getTypeBinding(binding);
+ }
+ }
+ }
+ } else if (type.isPrimitiveType()) {
+ /* Handle the void primitive type returned by getReturnType for a method declaration
+ * that is a constructor declaration. It prevents null from being returned
+ */
+ if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
+ return this.getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding.VOID);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveType(TypeDeclaration type) {
+ final Object node = this.newAstToOldAst.get(type);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ synchronized ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+ final Object node = this.newAstToOldAst.get(typeParameter);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeParameter) {
+ org.eclipse.jdt.internal.compiler.ast.TypeParameter typeParameter2 = (org.eclipse.jdt.internal.compiler.ast.TypeParameter) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeParameter2.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, typeParameter);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.BindingResolver#resolveVariable(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+ */
+ synchronized IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
+ final Object node = this.newAstToOldAst.get(enumConstant);
+ if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) node;
+ IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, enumConstant);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
+ final Object node = this.newAstToOldAst.get(variable);
+ if (node instanceof AbstractVariableDeclaration) {
+ AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
+ IVariableBinding variableBinding = null;
+ if (abstractVariableDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
+ variableBinding = this.getVariableBinding(fieldDeclaration.binding, variable);
+ } else {
+ variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding, variable);
+ }
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, variable);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveWellKnownType(String name) {
+ if (this.scope == null) return null;
+ ITypeBinding typeBinding = null;
+ try {
+ if (("boolean".equals(name))//$NON-NLS-1$
+ || ("char".equals(name))//$NON-NLS-1$
+ || ("byte".equals(name))//$NON-NLS-1$
+ || ("short".equals(name))//$NON-NLS-1$
+ || ("int".equals(name))//$NON-NLS-1$
+ || ("long".equals(name))//$NON-NLS-1$
+ || ("float".equals(name))//$NON-NLS-1$
+ || ("double".equals(name))//$NON-NLS-1$
+ || ("void".equals(name))) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(Scope.getBaseType(name.toCharArray()));
+ } else if ("java.lang.Object".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaLangObject());
+ } else if ("java.lang.String".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaLangString());
+ } else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_STRINGBUFFER, 3));
+ } else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaLangThrowable());
+ } else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_EXCEPTION, 3));
+ } else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3));
+ } else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_ERROR, 3));
+ } else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaLangClass());
+ } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaLangCloneable());
+ } else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getJavaIoSerializable());
+ } else if ("java.lang.Boolean".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BOOLEAN, 3));
+ } else if ("java.lang.Byte".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BYTE, 3));
+ } else if ("java.lang.Character".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_CHARACTER, 3));
+ } else if ("java.lang.Double".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_DOUBLE, 3));
+ } else if ("java.lang.Float".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_FLOAT, 3));
+ } else if ("java.lang.Integer".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_INTEGER, 3));
+ } else if ("java.lang.Long".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_LONG, 3));
+ } else if ("java.lang.Short".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_SHORT, 3));
+ } else if ("java.lang.Void".equals(name)) {//$NON-NLS-1$
+ typeBinding = this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_VOID, 3));
+ }
+ } catch (AbortCompilation e) {
+ // ignore missing types
+ }
+ if (typeBinding != null && !typeBinding.isRecovered()) {
+ return typeBinding;
+ }
+ return null;
+ }
+
+ synchronized IAnnotationBinding resolveAnnotation(final Annotation domASTNode) {
+ Object oldNode = this.newAstToOldAst.get(domASTNode);
+ if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.Annotation) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation internalAstNode =
+ (org.eclipse.jdt.internal.compiler.ast.Annotation) oldNode;
+
+ IAnnotationBinding domAnnotation = getAnnotationInstance(internalAstNode.getCompilerAnnotation());
+ if (domAnnotation == null)
+ return null;
+ this.bindingsToAstNodes.put(domAnnotation, domASTNode);
+ return domAnnotation;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ public CompilationUnitScope scope() {
+ return this.scope;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized void store(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+ this.newAstToOldAst.put(node, oldASTNode);
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized void updateKey(ASTNode node, ASTNode newNode) {
+ Object astNode = this.newAstToOldAst.remove(node);
+ if (astNode != null) {
+ this.newAstToOldAst.put(newNode, astNode);
+ }
+ }
+
+ /**
+ * Answer an array type binding with the given type binding and the given
+ * dimensions.
+ *
+ * <p>If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+ * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+ * dimensions.</p>
+ *
+ * <p>
+ * The default implementation of this method returns <code>null</code>.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param typeBinding the given type binding
+ * @param dimensions the given dimensions
+ * @return an array type binding with the given type binding and the given
+ * dimensions
+ * @throws IllegalArgumentException if the type binding represents the <code>void</code> type binding
+ */
+ ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+ if (typeBinding instanceof RecoveredTypeBinding) throw new IllegalArgumentException("Cannot be called on a recovered type binding"); //$NON-NLS-1$
+ ITypeBinding leafComponentType = typeBinding;
+ int actualDimensions = dimensions;
+ if (typeBinding.isArray()) {
+ leafComponentType = typeBinding.getElementType();
+ actualDimensions += typeBinding.getDimensions();
+ }
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding leafTypeBinding = null;
+ if (leafComponentType.isPrimitive()) {
+ String name = leafComponentType.getBinaryName();
+ switch(name.charAt(0)) {
+ case 'I' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.INT;
+ break;
+ case 'B' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.BYTE;
+ break;
+ case 'Z' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.BOOLEAN;
+ break;
+ case 'C' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.CHAR;
+ break;
+ case 'J' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.LONG;
+ break;
+ case 'S' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.SHORT;
+ break;
+ case 'D' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.DOUBLE;
+ break;
+ case 'F' :
+ leafTypeBinding = org.eclipse.jdt.internal.compiler.lookup.TypeBinding.FLOAT;
+ break;
+ case 'V' :
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if (!(leafComponentType instanceof TypeBinding)) return null;
+ leafTypeBinding = ((TypeBinding) leafComponentType).binding;
+ }
+ return this.getTypeBinding(lookupEnvironment().createArrayType(leafTypeBinding, actualDimensions));
+ }
+ //{ObjectTeams: Binding for callin/callout mappings
+ @Override
+ synchronized IMethodMappingBinding getMethodMappingBinding(org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding callbinding)
+ {
+ if (callbinding == null)
+ {
+ return null;
+ }
+
+ if (callbinding.isValidBinding())
+ {
+ MethodMappingBinding binding =
+ (MethodMappingBinding)bindingTables.compilerBindingsToASTBindings.get(callbinding);
+ if (binding != null)
+ {
+ return binding;
+ }
+ else
+ {
+ binding = new MethodMappingBinding(this, callbinding);
+ bindingTables.compilerBindingsToASTBindings.put(callbinding, binding);
+ return binding;
+ }
+ }
+
+ return null;
+ }
+//mkr}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
new file mode 100644
index 000000000..0be0ff23b
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
@@ -0,0 +1,644 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Internal class for associating comments with AST nodes.
+ *
+ * @since 3.0
+ */
+class DefaultCommentMapper {
+ Comment[] comments;
+ Scanner scanner;
+
+ // extended nodes storage
+ int leadingPtr;
+ ASTNode[] leadingNodes;
+ long[] leadingIndexes;
+ int trailingPtr, lastTrailingPtr;
+ ASTNode[] trailingNodes;
+ long[] trailingIndexes;
+ static final int STORAGE_INCREMENT = 16;
+
+ /**
+ * @param table the given table of comments
+ */
+ DefaultCommentMapper(Comment[] table) {
+ this.comments = table;
+ }
+
+ boolean hasSameTable(Comment[] table) {
+ return this.comments == table;
+ }
+
+ /**
+ * Get comment of the list which includes a given position
+ *
+ * @param position The position belonging to the looked up comment
+ * @return comment which includes the given position or null if none was found
+ */
+ Comment getComment(int position) {
+
+ if (this.comments == null) {
+ return null;
+ }
+ int size = this.comments.length;
+ if (size == 0) {
+ return null;
+ }
+ int index = getCommentIndex(0, position, 0);
+ if (index<0) {
+ return null;
+ }
+ return this.comments[index];
+ }
+
+ /*
+ * Get the index of comment which contains given position.
+ * If there's no matching comment, then return depends on exact parameter:
+ * = 0: return -1
+ * < 0: return index of the comment before the given position
+ * > 0: return index of the comment after the given position
+ */
+ private int getCommentIndex(int start, int position, int exact) {
+ if (position == 0) {
+ if (this.comments.length > 0 && this.comments[0].getStartPosition() == 0) {
+ return 0;
+ }
+ return -1;
+ }
+ int bottom = start, top = this.comments.length - 1;
+ int i = 0, index = -1;
+ Comment comment = null;
+ while (bottom <= top) {
+ i = bottom + (top - bottom) /2;
+ comment = this.comments[i];
+ int commentStart = comment.getStartPosition();
+ if (position < commentStart) {
+ top = i-1;
+ } else if (position >=(commentStart+comment.getLength())) {
+ bottom = i+1;
+ } else {
+ index = i;
+ break;
+ }
+ }
+ if (index<0 && exact!=0) {
+ comment = this.comments[i];
+ if (position < comment.getStartPosition()) {
+ return exact<0 ? i-1 : i;
+ } else {
+ return exact<0 ? i : i+1;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Returns the extended start position of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is recorded for this node
+ * @see #getExtendedLength(ASTNode)
+ * @since 3.0
+ */
+ public int getExtendedStartPosition(ASTNode node) {
+ if (this.leadingPtr >= 0) {
+ long range = -1;
+ for (int i=0; range<0 && i<=this.leadingPtr; i++) {
+ if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
+ }
+ if (range >= 0) {
+ return this.comments[(int)(range>>32)].getStartPosition() ;
+ }
+ }
+ return node.getStartPosition();
+ }
+
+ /*
+ * Search the line number corresponding to a specific position
+ * between the given line range (inclusive)
+ * @param position int
+ * @parem lineRange size-2 int[]
+ * @return int
+ */
+ public final int getLineNumber(int position, int[] lineRange) {
+ int[] lineEnds = this.scanner.lineEnds;
+ int length = lineEnds.length;
+ return Util.getLineNumber(position, lineEnds, (lineRange[0] > length ? length : lineRange[0]) -1, (lineRange[1] > length ? length : lineRange[1]) - 1);
+ }
+
+ /*
+ * Returns the extended end position of the given node.
+ */
+ public int getExtendedEnd(ASTNode node) {
+ int end = node.getStartPosition() + node.getLength();
+ if (this.trailingPtr >= 0) {
+ long range = -1;
+ for (int i=0; range<0 && i<=this.trailingPtr; i++) {
+ if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
+ }
+ if (range >= 0) {
+ Comment lastComment = this.comments[(int) range];
+ end = lastComment.getStartPosition() + lastComment.getLength();
+ }
+ }
+ return end-1;
+ }
+
+ /**
+ * Returns the extended source length of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return a (possibly 0) length, or <code>0</code>
+ * if no source position information is recorded for this node
+ * @see #getExtendedStartPosition(ASTNode)
+ * @see #getExtendedEnd(ASTNode)
+ * @since 3.0
+ */
+ public int getExtendedLength(ASTNode node) {
+ return getExtendedEnd(node) - getExtendedStartPosition(node) + 1;
+ }
+
+ /**
+ * Return index of first leading comment of a given node.
+ *
+ * @param node
+ * @return index of first leading comment or -1 if node has no leading comment
+ */
+ int firstLeadingCommentIndex(ASTNode node) {
+ if (this.leadingPtr >= 0) {
+ for (int i=0; i<=this.leadingPtr; i++) {
+ if (this.leadingNodes[i] == node) {
+ return (int) (this.leadingIndexes[i]>>32);
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Return index of last trailing comment of a given node.
+ *
+ * @param node
+ * @return index of last trailing comment or -1 if node has no trailing comment
+ */
+ int lastTrailingCommentIndex(ASTNode node) {
+ if (this.trailingPtr >= 0) {
+ for (int i=0; i<=this.trailingPtr; i++) {
+ if (this.trailingNodes[i] == node) {
+ return (int) this.trailingIndexes[i];
+ }
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
+ * unit.
+ * Scanner is necessary to scan between nodes and comments and verify if there's
+ * nothing else than white spaces.
+ */
+ void initialize(CompilationUnit unit, Scanner sc) {
+
+ // Init array pointers
+ this.leadingPtr = -1;
+ this.trailingPtr = -1;
+
+ // Init comments
+ this.comments = unit.optionalCommentTable;
+ if (this.comments == null) {
+ return;
+ }
+ int size = this.comments.length;
+ if (size == 0) {
+ return;
+ }
+
+ // Init scanner and start ranges computing
+ this.scanner = sc;
+ this.scanner.tokenizeWhiteSpace = true;
+
+ // Start unit visit
+ DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
+ unit.accept(commentVisitor);
+
+ // Reduce leading arrays if necessary
+ int leadingCount = this.leadingPtr + 1;
+ if (leadingCount > 0 && leadingCount < this.leadingIndexes.length) {
+ System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[leadingCount], 0, leadingCount);
+ System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new long[leadingCount], 0, leadingCount);
+ }
+
+ // Reduce trailing arrays if necessary
+ if (this.trailingPtr >= 0) {
+ // remove last remaining unresolved nodes
+ while (this.trailingIndexes[this.trailingPtr] == -1) {
+ this.trailingPtr--;
+ if (this.trailingPtr < 0) {
+ this.trailingIndexes = null;
+ this.trailingNodes = null;
+ break;
+ }
+ }
+
+ // reduce array size
+ int trailingCount = this.trailingPtr + 1;
+ if (trailingCount > 0 && trailingCount < this.trailingIndexes.length) {
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[trailingCount], 0, trailingCount);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new long[trailingCount], 0, trailingCount);
+ }
+ }
+
+ // Release scanner as it's only used during unit visit
+ this.scanner = null;
+ }
+
+ /**
+ * Search and store node leading comments. Comments are searched in position range
+ * from previous extended position to node start position. If one or several comment are found,
+ * returns first comment start position, otherwise returns node start position.
+ * <p>
+ * Starts to search for first comment before node start position and return if none was found...
+ *</p><p>
+ * When first comment is found before node, goes up in comment list until one of
+ * following conditions becomes true:
+ * <ol>
+ * <li>comment end is before previous end</li>
+ * <li>comment start and previous end is on the same line but not on same line of node start</li>
+ * <li>there's other than white characters between current node and comment</li>
+ * <li>there's more than 1 line between current node and comment</li>
+ * </ol>
+ * If some comment have been found, then no token should be on
+ * on the same line before, so remove all comments which do not verify this assumption.
+ * </p><p>
+ * If finally there's leading still comments, then stores indexes of the first and last one
+ * in leading comments table.
+ */
+ int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) {
+ // Init extended position
+ int nodeStart = node.getStartPosition();
+ int extended = nodeStart;
+
+ // Get line of node start position
+ int previousEndLine = getLineNumber(previousEnd, parentLineRange);
+ int nodeStartLine = getLineNumber(nodeStart, parentLineRange);
+
+ // Find first comment index
+ int idx = getCommentIndex(0, nodeStart, -1);
+ if (idx == -1) {
+ return nodeStart;
+ }
+
+ // Look after potential comments
+ int startIdx = -1;
+ int endIdx = idx;
+ int previousStart = nodeStart;
+ while (idx >= 0 && previousStart >= previousEnd) {
+ // Verify for each comment that there's only white spaces between end and start of {following comment|node}
+ Comment comment = this.comments[idx];
+ int commentStart = comment.getStartPosition();
+ int end = commentStart+comment.getLength()-1;
+ int commentLine = getLineNumber(commentStart, parentLineRange);
+ if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
+ // stop search on condition 1) and 2)
+ break;
+ } else if ((end+1) < previousStart) { // may be equals => then no scan is necessary
+ this.scanner.resetTo(end+1, previousStart);
+ try {
+ int token = this.scanner.getNextToken();
+ if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != previousStart) {
+ // stop search on condition 3)
+ // if first comment fails, then there's no extended position in fact
+ if (idx == endIdx) {
+ return nodeStart;
+ }
+ break;
+ }
+ } catch (InvalidInputException e) {
+ // Should not happen, but return no extended position...
+ return nodeStart;
+ }
+ // verify that there's no more than one line between node/comments
+ char[] gap = this.scanner.getCurrentIdentifierSource();
+ int nbrLine = 0;
+ int pos = -1;
+ while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+ nbrLine++;
+ }
+ if (nbrLine > 1) {
+ // stop search on condition 4)
+ break;
+ }
+ }
+ // Store previous infos
+ previousStart = commentStart;
+ startIdx = idx--;
+ }
+ if (startIdx != -1) {
+ // Verify that there's no token on the same line before first leading comment
+ int commentStart = this.comments[startIdx].getStartPosition();
+ if (previousEnd < commentStart && previousEndLine != nodeStartLine) {
+ int lastTokenEnd = previousEnd;
+ this.scanner.resetTo(previousEnd, commentStart);
+ try {
+ while (this.scanner.currentPosition < commentStart) {
+ if (this.scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
+ lastTokenEnd = this.scanner.getCurrentTokenEndPosition();
+ }
+ }
+ } catch (InvalidInputException e) {
+ // do nothing
+ }
+ int lastTokenLine = getLineNumber(lastTokenEnd, parentLineRange);
+ int length = this.comments.length;
+ while (startIdx<length && lastTokenLine == getLineNumber(this.comments[startIdx].getStartPosition(), parentLineRange) && nodeStartLine != lastTokenLine) {
+ startIdx++;
+ }
+ }
+ // Store leading comments indexes
+ if (startIdx <= endIdx) {
+ if (++this.leadingPtr == 0) {
+ this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
+ this.leadingIndexes = new long[STORAGE_INCREMENT];
+ } else if (this.leadingPtr == this.leadingNodes.length) {
+ int newLength = (this.leadingPtr*3/2)+STORAGE_INCREMENT;
+ System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr);
+ System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes = new long[newLength], 0, this.leadingPtr);
+ }
+ this.leadingNodes[this.leadingPtr] = node;
+ this.leadingIndexes[this.leadingPtr] = (((long)startIdx)<<32) + endIdx;
+ extended = this.comments[endIdx].getStartPosition();
+ }
+ }
+ return extended;
+ }
+
+ /**
+ * Search and store node trailing comments. Comments are searched in position range
+ * from node end position to specified next start. If one or several comment are found,
+ * returns last comment end position, otherwise returns node end position.
+ * <p>
+ * Starts to search for first comment after node end position and return if none was found...
+ *</p><p>
+ * When first comment is found after node, goes down in comment list until one of
+ * following conditions becomes true:
+ * <ol>
+ * <li>comment start is after next start</li>
+ * <li>there's other than white characters between current node and comment</li>
+ * <li>there's more than 1 line between current node and comment</li>
+ *</ol>
+ * If at least potential comments have been found, then all of them has to be separated
+ * from following node. So, remove all comments which do not verify this assumption.
+ * Note that this verification is not applicable on last node.
+ * </p><p>
+ * If finally there's still trailing comments, then stores indexes of the first and last one
+ * in trailing comments table.
+ */
+ int storeTrailingComments(ASTNode node, int nextStart, boolean lastChild, int[] parentLineRange) {
+
+ // Init extended position
+ int nodeEnd = node.getStartPosition()+node.getLength()-1;
+ if (nodeEnd == nextStart) {
+ // special case for last child of its parent
+ if (++this.trailingPtr == 0) {
+ this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+ this.trailingIndexes = new long[STORAGE_INCREMENT];
+ this.lastTrailingPtr = -1;
+ } else if (this.trailingPtr == this.trailingNodes.length) {
+ int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+ }
+ this.trailingNodes[this.trailingPtr] = node;
+ this.trailingIndexes[this.trailingPtr] = -1;
+ return nodeEnd;
+ }
+ int extended = nodeEnd;
+
+ // Get line number
+ int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);
+
+ // Find comments range index
+ int idx = getCommentIndex(0, nodeEnd, 1);
+ if (idx == -1) {
+ return nodeEnd;
+ }
+
+ // Look after potential comments
+ int startIdx = idx;
+ int endIdx = -1;
+ int length = this.comments.length;
+ int commentStart = extended+1;
+ int previousEnd = nodeEnd+1;
+ int sameLineIdx = -1;
+ while (idx<length && commentStart < nextStart) {
+ // get comment and leave if next starting position has been reached
+ Comment comment = this.comments[idx];
+ commentStart = comment.getStartPosition();
+ // verify that there's nothing else than white spaces between node/comments
+ if (commentStart >= nextStart) {
+ // stop search on condition 1)
+ break;
+ } else if (previousEnd < commentStart) {
+ this.scanner.resetTo(previousEnd, commentStart);
+ try {
+ int token = this.scanner.getNextToken();
+ if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != commentStart) {
+ // stop search on condition 2)
+ // if first index fails, then there's no extended position in fact...
+ if (idx == startIdx) {
+ return nodeEnd;
+ }
+ // otherwise we get the last index of trailing comment => break
+ break;
+ }
+ } catch (InvalidInputException e) {
+ // Should not happen, but return no extended position...
+ return nodeEnd;
+ }
+ // verify that there's no more than one line between node/comments
+ char[] gap = this.scanner.getCurrentIdentifierSource();
+ int nbrLine = 0;
+ int pos = -1;
+ while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+ nbrLine++;
+ }
+ if (nbrLine > 1) {
+ // stop search on condition 3)
+ break;
+ }
+ }
+ // Store index if we're on the same line than node end
+ int commentLine = getLineNumber(commentStart, parentLineRange);
+ if (commentLine == nodeEndLine) {
+ sameLineIdx = idx;
+ }
+ // Store previous infos
+ previousEnd = commentStart+comment.getLength();
+ endIdx = idx++;
+ }
+ if (endIdx != -1) {
+ // Verify that following node start is separated
+ if (!lastChild) {
+ int nextLine = getLineNumber(nextStart, parentLineRange);
+ int previousLine = getLineNumber(previousEnd, parentLineRange);
+ if((nextLine - previousLine) <= 1) {
+ if (sameLineIdx == -1) return nodeEnd;
+ endIdx = sameLineIdx;
+ }
+ }
+ // Store trailing comments indexes
+ if (++this.trailingPtr == 0) {
+ this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+ this.trailingIndexes = new long[STORAGE_INCREMENT];
+ this.lastTrailingPtr = -1;
+ } else if (this.trailingPtr == this.trailingNodes.length) {
+ int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+ }
+ this.trailingNodes[this.trailingPtr] = node;
+ long nodeRange = (((long)startIdx)<<32) + endIdx;
+ this.trailingIndexes[this.trailingPtr] = nodeRange;
+ // Compute new extended end
+ extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
+ // Look for children unresolved extended end
+ ASTNode previousNode = node;
+ int ptr = this.trailingPtr - 1; // children extended end were stored before
+ while (ptr >= 0) {
+ long range = this.trailingIndexes[ptr];
+ if (range != -1) break; // there's no more unresolved nodes
+ ASTNode unresolved = this.trailingNodes[ptr];
+ if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy
+ this.trailingIndexes[ptr] = nodeRange;
+ previousNode = unresolved;
+ ptr--; // get previous node
+ }
+ // Remove remaining unresolved nodes
+ if (ptr > this.lastTrailingPtr) {
+ int offset = ptr - this.lastTrailingPtr;
+ for (int i=ptr+1; i<=this.trailingPtr; i++) {
+ this.trailingNodes[i-offset] = this.trailingNodes[i];
+ this.trailingIndexes[i-offset] = this.trailingIndexes[i];
+ }
+ this.trailingPtr -= offset;
+ }
+ this.lastTrailingPtr = this.trailingPtr;
+ }
+ return extended;
+ }
+
+ class CommentMapperVisitor extends DefaultASTVisitor {
+
+ ASTNode topSiblingParent = null;
+ ASTNode[] siblings = new ASTNode[10];
+ int[][] parentLineRange = new int[10][];
+ int siblingPtr = -1;
+
+ protected boolean visitNode(ASTNode node) {
+
+ // Get default previous end
+ ASTNode parent = node.getParent();
+ int previousEnd = parent.getStartPosition();
+
+ // Look for sibling node
+ ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null;
+ if (sibling != null) {
+ // Found one previous sibling, so compute its trailing comments using current node start position
+ try {
+ previousEnd = storeTrailingComments(sibling, node.getStartPosition(), false, this.parentLineRange[this.siblingPtr]);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+ }
+
+ // Stop visit for malformed node (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049)
+ if ((node.typeAndFlags & ASTNode.MALFORMED) != 0) {
+ return false;
+ }
+
+ // Compute leading comments for current node
+ int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.scanner.linePtr+1};
+ try {
+ storeLeadingComments(node, previousEnd, previousLineRange);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+
+ // Store current node as waiting sibling for its parent
+ if (this.topSiblingParent != parent) {
+ if (this.siblings.length == ++this.siblingPtr) {
+ System.arraycopy(this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr*2], 0, this.siblingPtr);
+ System.arraycopy(this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr*2][], 0, this.siblingPtr);
+ }
+ if (this.topSiblingParent == null) {
+ // node is a CompilationUnit
+ this.parentLineRange[this.siblingPtr] = previousLineRange;
+ } else {
+ int parentStart = parent.getStartPosition();
+ int firstLine = getLineNumber(parentStart, previousLineRange);
+ int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange);
+ if (this.parentLineRange[this.siblingPtr] == null) {
+ this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine};
+ } else {
+ int[] lineRange = this.parentLineRange[this.siblingPtr];
+ lineRange[0] = firstLine;
+ lineRange[1] = lastLine;
+ }
+ }
+ this.topSiblingParent = parent;
+ }
+ this.siblings[this.siblingPtr] = node;
+
+ // We're always ok to visit sub-levels
+ return true;
+ }
+
+ protected void endVisitNode(ASTNode node) {
+
+ // Look if a child node is waiting for trailing comments computing
+ ASTNode sibling = this.topSiblingParent == node ? (ASTNode) this.siblings[this.siblingPtr] : null;
+ if (sibling != null) {
+ try {
+ storeTrailingComments(sibling, node.getStartPosition()+node.getLength()-1, true, this.parentLineRange[this.siblingPtr]);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+ }
+ // Remove sibling if needed
+ if (this.topSiblingParent != null /*not a CompilationUnit*/
+ && this.topSiblingParent == node) {
+ this.siblingPtr--;
+ this.topSiblingParent = node.getParent();
+ }
+ }
+
+ public boolean visit ( CompilationUnit node) {
+ // do nothing special, just go down in sub-levels
+ return true;
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultValuePairBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultValuePairBinding.java
new file mode 100644
index 000000000..d51772cba
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultValuePairBinding.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ * IBM Corporation - implemented methods from IBinding
+ * IBM Corporation - renamed from ResolvedDefaultValuePair to DefaultValuePairBinding
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.dom.BindingResolver;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+
+/**
+ * Member value pair which compose of default values.
+ */
+class DefaultValuePairBinding extends MemberValuePairBinding {
+
+ private org.eclipse.jdt.internal.compiler.lookup.MethodBinding method;
+
+ DefaultValuePairBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding, BindingResolver resolver) {
+ super(null, resolver);
+ this.method = binding;
+ this.value = MemberValuePairBinding.buildDOMValue(binding.getDefaultValue(), resolver);
+ }
+
+ public IMethodBinding getMethodBinding() {
+ return this.bindingResolver.getMethodBinding(this.method);
+ }
+
+ public String getName() {
+ return new String(this.method.selector);
+ }
+
+ public Object getValue() {
+ return this.value;
+ }
+
+ public boolean isDefault() {
+ return true;
+ }
+
+ public boolean isDeprecated() {
+ return this.method.isDeprecated();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
new file mode 100644
index 000000000..41204909c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Do statement AST node type.
+ *
+ * <pre>
+ * DoStatement:
+ * <b>do</b> Statement <b>while</b> <b>(</b> Expression <b>)</b> <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class DoStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(DoStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(DoStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(DoStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new unparented do statement node owned by the given
+ * AST. By default, the expresssion is unspecified, but legal,
+ * and the body statement is an empty block.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ DoStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return DO_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ DoStatement result = new DoStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getBody());
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this do statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this do statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this do statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this do statement.
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the body of a do statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the body of a <code>DoStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
new file mode 100644
index 000000000..037b4728c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
@@ -0,0 +1,740 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Internal parser used for decoding doc comments.
+ *
+ * @since 3.0
+ */
+class DocCommentParser extends AbstractCommentParser {
+
+ private Javadoc docComment;
+ private AST ast;
+
+ DocCommentParser(AST ast, Scanner scanner, boolean check) {
+ super(null);
+ this.ast = ast;
+ this.scanner = scanner;
+ this.sourceLevel = this.ast.apiLevel() >= AST.JLS3 ? ClassFileConstants.JDK1_5 : ClassFileConstants.JDK1_3;
+ this.checkDocComment = check;
+ this.kind = DOM_PARSER | TEXT_PARSE;
+ }
+
+ /* (non-Javadoc)
+ * Returns true if tag @deprecated is present in annotation.
+ *
+ * If annotation checking is enabled, will also construct an Annotation node, which will be stored into Parser.annotation
+ * slot for being consumed later on.
+ */
+ public Javadoc parse(int[] positions) {
+ return parse(positions[0], positions[1]-positions[0]);
+ }
+ public Javadoc parse(int start, int length) {
+
+ // Init
+ this.source = this.scanner.source;
+ this.lineEnds = this.scanner.lineEnds;
+ this.docComment = new Javadoc(this.ast);
+
+ // Parse
+ if (this.checkDocComment) {
+ this.javadocStart = start;
+ this.javadocEnd = start+length-1;
+ this.firstTagPosition = this.javadocStart;
+ commentParse();
+ }
+ this.docComment.setSourceRange(start, length);
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ setComment(start, length); // backward compatibility
+ }
+ return this.docComment;
+ }
+
+ /**
+ * Sets the comment starting at the given position and with the given length.
+ * <p>
+ * Note the only purpose of this method is to hide deprecated warnings.
+ * @deprecated mark deprecated to hide deprecated usage
+ */
+ private void setComment(int start, int length) {
+ this.docComment.setComment(new String(this.source, start, length));
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("javadoc: ").append(this.docComment).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(super.toString());
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createArgumentReference(char[], java.lang.Object, int)
+ */
+ protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException {
+ try {
+ MethodRefParameter argument = this.ast.newMethodRefParameter();
+ ASTNode node = (ASTNode) typeRef;
+ int argStart = node.getStartPosition();
+ int argEnd = node.getStartPosition()+node.getLength()-1;
+ if (dim > 0) argEnd = (int) dimPositions[dim-1];
+ if (argNamePos >= 0) argEnd = (int) argNamePos;
+ if (name.length != 0) {
+ final SimpleName argName = new SimpleName(this.ast);
+ argName.internalSetIdentifier(new String(name));
+ argument.setName(argName);
+ int argNameStart = (int) (argNamePos >>> 32);
+ argName.setSourceRange(argNameStart, argEnd-argNameStart+1);
+ }
+ Type argType = null;
+ if (node.getNodeType() == ASTNode.PRIMITIVE_TYPE) {
+ argType = (PrimitiveType) node;
+// if (dim > 0) {
+// argType = this.ast.newArrayType(argType, dim);
+// argType.setSourceRange(argStart, ((int) dimPositions[dim-1])-argStart+1);
+// }
+ } else {
+ Name argTypeName = (Name) node;
+ argType = this.ast.newSimpleType(argTypeName);
+ argType.setSourceRange(argStart, node.getLength());
+ }
+ if (dim > 0 && !isVarargs) {
+ for (int i=0; i<dim; i++) {
+ argType = this.ast.newArrayType(argType);
+ argType.setSourceRange(argStart, ((int) dimPositions[i])-argStart+1);
+ }
+ }
+ argument.setType(argType);
+ argument.setSourceRange(argStart, argEnd - argStart + 1);
+ return argument;
+ }
+ catch (ClassCastException ex) {
+ throw new InvalidInputException();
+ }
+ }
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createFieldReference()
+ */
+ protected Object createFieldReference(Object receiver) throws InvalidInputException {
+ try {
+ MemberRef fieldRef = this.ast.newMemberRef();
+ SimpleName fieldName = new SimpleName(this.ast);
+ fieldName.internalSetIdentifier(new String(this.identifierStack[0]));
+ fieldRef.setName(fieldName);
+ int start = (int) (this.identifierPositionStack[0] >>> 32);
+ int end = (int) this.identifierPositionStack[0];
+ fieldName.setSourceRange(start, end - start + 1);
+ if (receiver == null) {
+ start = this.memberStart;
+ fieldRef.setSourceRange(start, end - start + 1);
+ } else {
+ Name typeRef = (Name) receiver;
+ fieldRef.setQualifier(typeRef);
+ start = typeRef.getStartPosition();
+ end = fieldName.getStartPosition()+fieldName.getLength()-1;
+ fieldRef.setSourceRange(start, end-start+1);
+ }
+ return fieldRef;
+ }
+ catch (ClassCastException ex) {
+ throw new InvalidInputException();
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createMethodReference(java.lang.Object[])
+ */
+ protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException {
+ try {
+ // Create method ref
+ MethodRef methodRef = this.ast.newMethodRef();
+ SimpleName methodName = new SimpleName(this.ast);
+ int length = this.identifierLengthStack[0] - 1; // may be > 0 for member class constructor reference
+ methodName.internalSetIdentifier(new String(this.identifierStack[length]));
+ methodRef.setName(methodName);
+ int start = (int) (this.identifierPositionStack[length] >>> 32);
+ int end = (int) this.identifierPositionStack[length];
+ methodName.setSourceRange(start, end - start + 1);
+ // Set qualifier
+ if (receiver == null) {
+ start = this.memberStart;
+ methodRef.setSourceRange(start, end - start + 1);
+ } else {
+ Name typeRef = (Name) receiver;
+ methodRef.setQualifier(typeRef);
+ start = typeRef.getStartPosition();
+ }
+ // Add arguments
+ if (arguments != null) {
+ Iterator parameters = arguments.listIterator();
+ while (parameters.hasNext()) {
+ MethodRefParameter param = (MethodRefParameter) parameters.next();
+ methodRef.parameters().add(param);
+ }
+ }
+ methodRef.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1);
+ return methodRef;
+ }
+ catch (ClassCastException ex) {
+ throw new InvalidInputException();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTag()
+ */
+ protected void createTag() {
+ TagElement tagElement = this.ast.newTagElement();
+ int position = this.scanner.currentPosition;
+ this.scanner.resetTo(this.tagSourceStart, this.tagSourceEnd);
+ StringBuffer tagName = new StringBuffer();
+ int start = this.tagSourceStart;
+ this.scanner.getNextChar();
+ while (this.scanner.currentPosition <= (this.tagSourceEnd+1)) {
+ tagName.append(this.scanner.currentCharacter);
+ this.scanner.getNextChar();
+ }
+ tagElement.setTagName(tagName.toString());
+ if (this.inlineTagStarted) {
+ start = this.inlineTagStart;
+ TagElement previousTag = null;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ }
+ int previousStart = previousTag.getStartPosition();
+ previousTag.fragments().add(tagElement);
+ previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
+ } else {
+ pushOnAstStack(tagElement, true);
+ }
+ tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
+ this.scanner.resetTo(position, this.javadocEnd);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTypeReference()
+ */
+ protected Object createTypeReference(int primitiveToken) {
+ int size = this.identifierLengthStack[this.identifierLengthPtr];
+ String[] identifiers = new String[size];
+ int pos = this.identifierPtr - size + 1;
+ for (int i = 0; i < size; i++) {
+ identifiers[i] = new String(this.identifierStack[pos+i]);
+ }
+ ASTNode typeRef = null;
+ if (primitiveToken == -1) {
+ typeRef = this.ast.internalNewName(identifiers);
+ } else {
+ switch (primitiveToken) {
+ case TerminalTokens.TokenNamevoid :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ break;
+ case TerminalTokens.TokenNameboolean :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.BOOLEAN);
+ break;
+ case TerminalTokens.TokenNamebyte :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.BYTE);
+ break;
+ case TerminalTokens.TokenNamechar :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.CHAR);
+ break;
+ case TerminalTokens.TokenNamedouble :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.DOUBLE);
+ break;
+ case TerminalTokens.TokenNamefloat :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.FLOAT);
+ break;
+ case TerminalTokens.TokenNameint :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.INT);
+ break;
+ case TerminalTokens.TokenNamelong :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.LONG);
+ break;
+ case TerminalTokens.TokenNameshort :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.SHORT);
+ break;
+ default:
+ // should not happen
+ return null;
+ }
+ }
+ // Update ref for whole name
+ int start = (int) (this.identifierPositionStack[pos] >>> 32);
+// int end = (int) this.identifierPositionStack[this.identifierPtr];
+// typeRef.setSourceRange(start, end-start+1);
+ // Update references of each simple name
+ if (size > 1) {
+ Name name = (Name)typeRef;
+ int nameIndex = size;
+ for (int i=this.identifierPtr; i>pos; i--, nameIndex--) {
+ int s = (int) (this.identifierPositionStack[i] >>> 32);
+ int e = (int) this.identifierPositionStack[i];
+ name.index = nameIndex;
+ SimpleName simpleName = ((QualifiedName)name).getName();
+ simpleName.index = nameIndex;
+ simpleName.setSourceRange(s, e-s+1);
+ name.setSourceRange(start, e-start+1);
+ name = ((QualifiedName)name).getQualifier();
+ }
+ int end = (int) this.identifierPositionStack[pos];
+ name.setSourceRange(start, end-start+1);
+ name.index = nameIndex;
+ } else {
+ int end = (int) this.identifierPositionStack[pos];
+ typeRef.setSourceRange(start, end-start+1);
+ }
+ return typeRef;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag(boolean)
+ */
+ protected boolean parseIdentifierTag(boolean report) {
+ if (super.parseIdentifierTag(report)) {
+ createTag();
+ this.index = this.tagSourceEnd+1;
+ this.scanner.resetTo(this.index, this.javadocEnd);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Parse @return tag declaration
+ */
+ protected boolean parseReturn() {
+ createTag();
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
+ */
+ protected boolean parseTag(int previousPosition) throws InvalidInputException {
+
+ // Read tag name
+ int currentPosition = this.index;
+ int token = readTokenAndConsume();
+ char[] tagName = CharOperation.NO_CHAR;
+ if (currentPosition == this.scanner.startPosition) {
+ this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+ this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+ tagName = this.scanner.getCurrentIdentifierSource();
+ } else {
+ this.tagSourceEnd = currentPosition-1;
+ }
+
+ // Try to get tag name other than java identifier
+ // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
+ if (this.scanner.currentCharacter != ' ' && !ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+ tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
+ int length = tagName.length;
+ // !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
+ switch (this.scanner.currentCharacter) {
+ case '}':
+ case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
+ case '!':
+ case '#':
+ case '%':
+ case '&':
+ case '\'':
+ case '"':
+ case ':':
+ case '<':
+ case '>':
+ break tagNameToken;
+ case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
+ System.arraycopy(tagName, 0, tagName = new char[length+1], 0, length);
+ tagName[length] = this.scanner.currentCharacter;
+ break;
+ default:
+ if (this.scanner.currentCharacter == ' ' || ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+ break tagNameToken;
+ }
+ token = readTokenAndConsume();
+ char[] ident = this.scanner.getCurrentIdentifierSource();
+ System.arraycopy(tagName, 0, tagName = new char[length+ident.length], 0, length);
+ System.arraycopy(ident, 0, tagName, length, ident.length);
+ break;
+ }
+ this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+ this.scanner.getNextChar();
+ this.index = this.scanner.currentPosition;
+ }
+ }
+ int length = tagName.length;
+ this.index = this.tagSourceEnd+1;
+ this.scanner.currentPosition = this.tagSourceEnd+1;
+ this.tagSourceStart = previousPosition;
+
+ // tage name may be empty (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=125903)
+ if (tagName.length == 0) {
+ return false;
+ }
+
+ // Decide which parse to perform depending on tag name
+ this.tagValue = NO_TAG_VALUE;
+ boolean valid = true;
+ switch (token) {
+ case TerminalTokens.TokenNameIdentifier :
+ switch (tagName[0]) {
+ case 'c':
+ if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, tagName)) {
+ this.tagValue = TAG_CATEGORY_VALUE;
+ valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'd':
+ if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName)) {
+ this.deprecated = true;
+ this.tagValue = TAG_DEPRECATED_VALUE;
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ }
+ createTag();
+ break;
+ case 'i':
+ if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, tagName)) {
+ if (this.reportProblems) {
+ recordInheritedPosition((((long) this.tagSourceStart) << 32) + this.tagSourceEnd);
+ }
+ this.tagValue = TAG_INHERITDOC_VALUE;
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ }
+ createTag();
+ break;
+ case 'p':
+ if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) {
+ this.tagValue = TAG_PARAM_VALUE;
+ valid = parseParam();
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'e':
+ if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) {
+ this.tagValue = TAG_EXCEPTION_VALUE;
+ valid = parseThrows();
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 's':
+ if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName)) {
+ this.tagValue = TAG_SEE_VALUE;
+ if (this.inlineTagStarted) {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @see inside inline comment
+ valid = false;
+ } else {
+ valid = parseReference();
+ }
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'l':
+ if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName)) {
+ this.tagValue = TAG_LINK_VALUE;
+ } else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) {
+ this.tagValue = TAG_LINKPLAIN_VALUE;
+ }
+ if (this.tagValue != NO_TAG_VALUE) {
+ if (this.inlineTagStarted) {
+ valid = parseReference();
+ } else {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @link outside inline comment
+ valid = false;
+ }
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'v':
+ if (this.sourceLevel >= ClassFileConstants.JDK1_5 && length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, tagName)) {
+ this.tagValue = TAG_VALUE_VALUE;
+ if (this.inlineTagStarted) {
+ valid = parseReference();
+ } else {
+ valid = false;
+ }
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ default:
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case TerminalTokens.TokenNamereturn :
+ this.tagValue = TAG_RETURN_VALUE;
+ valid = parseReturn();
+ break;
+ case TerminalTokens.TokenNamethrows :
+ this.tagValue = TAG_THROWS_VALUE;
+ valid = parseThrows();
+ break;
+ case TerminalTokens.TokenNameabstract:
+ case TerminalTokens.TokenNameassert:
+ case TerminalTokens.TokenNameboolean:
+ case TerminalTokens.TokenNamebreak:
+ case TerminalTokens.TokenNamebyte:
+ case TerminalTokens.TokenNamecase:
+ case TerminalTokens.TokenNamecatch:
+ case TerminalTokens.TokenNamechar:
+ case TerminalTokens.TokenNameclass:
+ case TerminalTokens.TokenNamecontinue:
+ case TerminalTokens.TokenNamedefault:
+ case TerminalTokens.TokenNamedo:
+ case TerminalTokens.TokenNamedouble:
+ case TerminalTokens.TokenNameelse:
+ case TerminalTokens.TokenNameextends:
+ case TerminalTokens.TokenNamefalse:
+ case TerminalTokens.TokenNamefinal:
+ case TerminalTokens.TokenNamefinally:
+ case TerminalTokens.TokenNamefloat:
+ case TerminalTokens.TokenNamefor:
+ case TerminalTokens.TokenNameif:
+ case TerminalTokens.TokenNameimplements:
+ case TerminalTokens.TokenNameimport:
+ case TerminalTokens.TokenNameinstanceof:
+ case TerminalTokens.TokenNameint:
+ case TerminalTokens.TokenNameinterface:
+ case TerminalTokens.TokenNamelong:
+ case TerminalTokens.TokenNamenative:
+ case TerminalTokens.TokenNamenew:
+ case TerminalTokens.TokenNamenull:
+ case TerminalTokens.TokenNamepackage:
+ case TerminalTokens.TokenNameprivate:
+ case TerminalTokens.TokenNameprotected:
+ case TerminalTokens.TokenNamepublic:
+ case TerminalTokens.TokenNameshort:
+ case TerminalTokens.TokenNamestatic:
+ case TerminalTokens.TokenNamestrictfp:
+ case TerminalTokens.TokenNamesuper:
+ case TerminalTokens.TokenNameswitch:
+ case TerminalTokens.TokenNamesynchronized:
+ case TerminalTokens.TokenNamethis:
+ case TerminalTokens.TokenNamethrow:
+ case TerminalTokens.TokenNametransient:
+ case TerminalTokens.TokenNametrue:
+ case TerminalTokens.TokenNametry:
+ case TerminalTokens.TokenNamevoid:
+ case TerminalTokens.TokenNamevolatile:
+ case TerminalTokens.TokenNamewhile:
+ case TerminalTokens.TokenNameenum :
+ case TerminalTokens.TokenNameconst :
+ case TerminalTokens.TokenNamegoto :
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ break;
+ }
+ this.textStart = this.index;
+ return valid;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushParamName(java.lang.Object)
+ */
+ protected boolean pushParamName(boolean isTypeParam) {
+ int idIndex = isTypeParam ? 1 : 0;
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(this.identifierStack[idIndex]));
+ int nameStart = (int) (this.identifierPositionStack[idIndex] >>> 32);
+ int nameEnd = (int) (this.identifierPositionStack[idIndex] & 0x00000000FFFFFFFFL);
+ name.setSourceRange(nameStart, nameEnd-nameStart+1);
+ TagElement paramTag = this.ast.newTagElement();
+ paramTag.setTagName(TagElement.TAG_PARAM);
+ if (isTypeParam) { // specific storage for @param <E> (see bug 79809)
+ // '<' was stored in identifiers stack
+ TextElement text = this.ast.newTextElement();
+ text.setText(new String(this.identifierStack[0]));
+ int txtStart = (int) (this.identifierPositionStack[0] >>> 32);
+ int txtEnd = (int) (this.identifierPositionStack[0] & 0x00000000FFFFFFFFL);
+ text.setSourceRange(txtStart, txtEnd-txtStart+1);
+ paramTag.fragments().add(text);
+ // add simple name
+ paramTag.fragments().add(name);
+ // '>' was stored in identifiers stack
+ text = this.ast.newTextElement();
+ text.setText(new String(this.identifierStack[2]));
+ txtStart = (int) (this.identifierPositionStack[2] >>> 32);
+ txtEnd = (int) (this.identifierPositionStack[2] & 0x00000000FFFFFFFFL);
+ text.setSourceRange(txtStart, txtEnd-txtStart+1);
+ paramTag.fragments().add(text);
+ // set param tag source range
+ paramTag.setSourceRange(this.tagSourceStart, txtEnd-this.tagSourceStart+1);
+ } else {
+ paramTag.setSourceRange(this.tagSourceStart, nameEnd-this.tagSourceStart+1);
+ paramTag.fragments().add(name);
+ }
+ pushOnAstStack(paramTag, true);
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushSeeRef(java.lang.Object)
+ */
+ protected boolean pushSeeRef(Object statement) {
+ TagElement seeTag = this.ast.newTagElement();
+ ASTNode node = (ASTNode) statement;
+ seeTag.fragments().add(node);
+ int end = node.getStartPosition()+node.getLength()-1;
+ if (this.inlineTagStarted) {
+ seeTag.setSourceRange(this.inlineTagStart, end-this.inlineTagStart+1);
+ switch (this.tagValue) {
+ case TAG_LINK_VALUE:
+ seeTag.setTagName(TagElement.TAG_LINK);
+ break;
+ case TAG_LINKPLAIN_VALUE:
+ seeTag.setTagName(TagElement.TAG_LINKPLAIN);
+ break;
+ case TAG_VALUE_VALUE:
+ seeTag.setTagName(TagElement.TAG_VALUE);
+ break;
+ }
+ TagElement previousTag = null;
+ int previousStart = this.inlineTagStart;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ previousStart = previousTag.getStartPosition();
+ }
+ previousTag.fragments().add(seeTag);
+ previousTag.setSourceRange(previousStart, end-previousStart+1);
+ } else {
+ seeTag.setTagName(TagElement.TAG_SEE);
+ seeTag.setSourceRange(this.tagSourceStart, end-this.tagSourceStart+1);
+ pushOnAstStack(seeTag, true);
+ }
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
+ */
+ protected void pushText(int start, int end) {
+
+ // Create text element
+ TextElement text = this.ast.newTextElement();
+ text.setText(new String( this.source, start, end-start));
+ text.setSourceRange(start, end-start);
+
+ // Search previous tag on which to add the text element
+ TagElement previousTag = null;
+ int previousStart = start;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ previousTag.setSourceRange(start, end-start);
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ previousStart = previousTag.getStartPosition();
+ }
+
+ // If we're in a inline tag, then retrieve previous tag in its fragments
+ List fragments = previousTag.fragments();
+ if (this.inlineTagStarted) {
+ int size = fragments.size();
+ if (size == 0) {
+ // no existing fragment => just add the element
+ TagElement inlineTag = this.ast.newTagElement();
+ fragments.add(inlineTag);
+ previousTag = inlineTag;
+ } else {
+ // If last fragment is a tag, then use it as previous tag
+ ASTNode lastFragment = (ASTNode) fragments.get(size-1);
+ if (lastFragment.getNodeType() == ASTNode.TAG_ELEMENT) {
+ previousTag = (TagElement) lastFragment;
+ previousStart = previousTag.getStartPosition();
+ }
+ }
+ }
+
+ // Add the text
+ previousTag.fragments().add(text);
+ previousTag.setSourceRange(previousStart, end-previousStart);
+ this.textStart = -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushThrowName(java.lang.Object)
+ */
+ protected boolean pushThrowName(Object typeRef) {
+ TagElement throwsTag = this.ast.newTagElement();
+ switch (this.tagValue) {
+ case TAG_THROWS_VALUE:
+ throwsTag.setTagName(TagElement.TAG_THROWS);
+ break;
+ case TAG_EXCEPTION_VALUE:
+ throwsTag.setTagName(TagElement.TAG_EXCEPTION);
+ break;
+ }
+ throwsTag.setSourceRange(this.tagSourceStart, this.scanner.getCurrentTokenEndPosition()-this.tagSourceStart+1);
+ throwsTag.fragments().add(typeRef);
+ pushOnAstStack(throwsTag, true);
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#refreshInlineTagPosition(int)
+ */
+ protected void refreshInlineTagPosition(int previousPosition) {
+ if (this.astPtr != -1) {
+ TagElement previousTag = (TagElement) this.astStack[this.astPtr];
+ if (this.inlineTagStarted) {
+ int previousStart = previousTag.getStartPosition();
+ previousTag.setSourceRange(previousStart, previousPosition-previousStart+1);
+ if (previousTag.fragments().size() > 0) {
+ ASTNode inlineTag = (ASTNode) previousTag.fragments().get(previousTag.fragments().size()-1);
+ if (inlineTag.getNodeType() == ASTNode.TAG_ELEMENT) {
+ int inlineStart = inlineTag.getStartPosition();
+ inlineTag.setSourceRange(inlineStart, previousPosition-inlineStart+1);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Add stored tag elements to associated comment.
+ */
+ protected void updateDocComment() {
+ for (int idx = 0; idx <= this.astPtr; idx++) {
+ this.docComment.tags().add(this.astStack[idx]);
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java
new file mode 100644
index 000000000..da132085f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EmptyStatement.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null statement AST node type.
+ *
+ * <pre>
+ * EmptyStatement:
+ * <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EmptyStatement extends Statement {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(1);
+ createPropertyList(EmptyStatement.class, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented null statement node owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ EmptyStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return EMPTY_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EmptyStatement result = new EmptyStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java
new file mode 100644
index 000000000..c01598219
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnhancedForStatement.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enhanced For statement AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnhancedForStatement:
+ * <b>for</b> <b>(</b> FormalParameter <b>:</b> Expression <b>)</b>
+ * Statement
+ * </pre>
+ * The FormalParameter is represented by a <code>SingleVariableDeclaration</code>
+ * (without an initializer).
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnhancedForStatement extends Statement {
+
+ /**
+ * The "parameter" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor PARAMETER_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "parameter", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(EnhancedForStatement.class, properyList);
+ addProperty(PARAMETER_PROPERTY, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The parameter; lazily initialized; defaults to a unspecified,
+ * legal node.
+ */
+ private SingleVariableDeclaration parameter = null;
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for an enchanced for statement owned by the
+ * given AST. By default, the parameter and expression are unspecified
+ * but legal subtrees, and the body is an empty block.
+ *
+ * @param ast the AST that is to own this node
+ */
+ EnhancedForStatement(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == PARAMETER_PROPERTY) {
+ if (get) {
+ return getParameter();
+ } else {
+ setParameter((SingleVariableDeclaration) child);
+ return null;
+ }
+ }
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ENHANCED_FOR_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EnhancedForStatement result = new EnhancedForStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setParameter((SingleVariableDeclaration) getParameter().clone(target));
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getParameter());
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the formal parameter in this enhanced for statement.
+ *
+ * @return the parameter
+ */
+ public SingleVariableDeclaration getParameter() {
+ if (this.parameter == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.parameter == null) {
+ preLazyInit();
+ this.parameter = this.ast.newSingleVariableDeclaration();
+ postLazyInit(this.parameter, PARAMETER_PROPERTY);
+ }
+ }
+ }
+ return this.parameter;
+ }
+
+ /**
+ * Sets the formal parameter in this enhanced for statement.
+ *
+ * @param parameter the new parameter
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setParameter(SingleVariableDeclaration parameter) {
+ if (parameter == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.parameter;
+ preReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+ this.parameter = parameter;
+ postReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+ }
+
+ /**
+ * Returns the expression of this enhanced for statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this enhanced for statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this enchanced for statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this enhanced for statement.
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.parameter == null ? 0 : getParameter().treeSize())
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java
new file mode 100644
index 000000000..cd194bbc9
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumConstantDeclaration.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enumeration constant declaration AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnumConstantDeclaration:
+ * [ Javadoc ] { ExtendedModifier } Identifier
+ * [ <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> ]
+ * [ AnonymousClassDeclaration ]
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the identifier. If there are class body declarations, the
+ * source range extends through the last character of the last character of
+ * the "}" token following the body declarations. If there are arguments but
+ * no class body declarations, the source range extends through the last
+ * character of the ")" token following the arguments. If there are no
+ * arguments and no class body declarations, the source range extends through
+ * the last character of the identifier.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnumConstantDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(EnumConstantDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type).
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(EnumConstantDeclaration.class);
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(EnumConstantDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(EnumConstantDeclaration.class, "arguments", Expression.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "anonymousClassDeclaration" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(EnumConstantDeclaration.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(6);
+ createPropertyList(EnumConstantDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The constant name; lazily initialized; defaults to a unspecified,
+ * legal Java class identifier.
+ */
+ private SimpleName constantName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * The optional anonymous class declaration; <code>null</code> for none;
+ * defaults to none.
+ */
+ private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+
+ /**
+ * Creates a new AST node for an enumeration constants declaration owned by
+ * the given AST. By default, the enumeration constant has an unspecified,
+ * but legal, name; no javadoc; an empty list of modifiers and annotations;
+ * an empty list of arguments; and does not declare an anonymous class.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ EnumConstantDeclaration(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+ if (get) {
+ return getAnonymousClassDeclaration();
+ } else {
+ setAnonymousClassDeclaration((AnonymousClassDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ // this property will not be asked for (node type did not exist in JLS2)
+ return null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ENUM_CONSTANT_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EnumConstantDeclaration result = new EnumConstantDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setName((SimpleName) getName().clone(target));
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ result.setAnonymousClassDeclaration(
+ (AnonymousClassDeclaration) ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.arguments);
+ acceptChild(visitor, getAnonymousClassDeclaration());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of the constant declared in this enum declaration.
+ *
+ * @return the constant name node
+ */
+ public SimpleName getName() {
+ if (this.constantName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.constantName == null) {
+ preLazyInit();
+ this.constantName = new SimpleName(this.ast);
+ postLazyInit(this.constantName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.constantName;
+ }
+
+ /**
+ * Sets the name of the constant declared in this enum declaration to the
+ * given name.
+ *
+ * @param constantName the new constant name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName constantName) {
+ if (constantName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.constantName;
+ preReplaceChild(oldChild, constantName, NAME_PROPERTY);
+ this.constantName = constantName;
+ postReplaceChild(oldChild, constantName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this enumeration
+ * constant declaration. Note that an empty list of arguments is equivalent
+ * to not explicitly specifying arguments.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Returns the anonymous class declaration introduced by this
+ * enum constant declaration, if it has one.
+ *
+ * @return the anonymous class declaration, or <code>null</code> if none
+ */
+ public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+ return this.optionalAnonymousClassDeclaration;
+ }
+
+ /**
+ * Sets whether this enum constant declaration declares
+ * an anonymous class (that is, has class body declarations).
+ *
+ * @param decl the anonymous class declaration, or <code>null</code>
+ * if none
+ */
+ public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+ ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+ preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ this.optionalAnonymousClassDeclaration = decl;
+ postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * enum constant.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the constructor binding, or <code>null</code> if the binding
+ * cannot be resolved
+ */
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /**
+ * Resolves and returns the field binding for this enum constant.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public IVariableBinding resolveVariable() {
+ return this.ast.getBindingResolver().resolveVariable(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + this.modifiers.listSize()
+ + (this.constantName == null ? 0 : getName().treeSize())
+ + this.arguments.listSize()
+ + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java
new file mode 100644
index 000000000..d6f61c878
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/EnumDeclaration.java
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enum declaration AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnumDeclaration:
+ * [ Javadoc ] { ExtendedModifier } <b>enum</b> Identifier
+ * [ <b>implements</b> Type { <b>,</b> Type } ]
+ * <b>{</b>
+ * [ EnumConstantDeclaration { <b>,</b> EnumConstantDeclaration } ] [ <b>,</b> ]
+ * [ <b>;</b> { ClassBodyDeclaration | <b>;</b> } ]
+ * <b>}</b>
+ * </pre>
+ * The {@link #enumConstants()} list holds the enum constant declarations,
+ * while the {@link #bodyDeclarations()} list holds the class body declarations
+ * that appear after the semicolon.
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier or annotation (if present), or the
+ * first character of the "enum" keyword (if no
+ * modifiers or annotations). The source range extends through the last
+ * character of the "}" token following the body declarations.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnumDeclaration extends AbstractTypeDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(EnumDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(EnumDeclaration.class);
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(EnumDeclaration.class);
+
+ /**
+ * The "superInterfaceTypes" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY =
+ new ChildListPropertyDescriptor(EnumDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "enumConstants" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor ENUM_CONSTANTS_PROPERTY =
+ new ChildListPropertyDescriptor(EnumDeclaration.class, "enumConstants", EnumConstantDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "bodyDeclarations" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ internalBodyDeclarationPropertyFactory(EnumDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(6);
+ createPropertyList(EnumDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(SUPER_INTERFACE_TYPES_PROPERTY, properyList);
+ addProperty(ENUM_CONSTANTS_PROPERTY, properyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The superinterface types (element type: <code>Type</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList superInterfaceTypes =
+ new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
+
+ /**
+ * The enum constant declarations
+ * (element type: <code>EnumConstantDeclaration</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList enumConstants =
+ new ASTNode.NodeList(ENUM_CONSTANTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an enum declaration owned by the given
+ * AST. By default, the enum declaration has an unspecified, but legal,
+ * name; no modifiers; no javadoc; no superinterfaces;
+ * and empty lists of enum constants and body declarations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ EnumDeclaration(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == SUPER_INTERFACE_TYPES_PROPERTY) {
+ return superInterfaceTypes();
+ }
+ if (property == ENUM_CONSTANTS_PROPERTY) {
+ return enumConstants();
+ }
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ // this property will not be asked for (node type did not exist in JLS2)
+ return null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+ return BODY_DECLARATIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ENUM_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EnumDeclaration result = new EnumDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setName((SimpleName) getName().clone(target));
+ result.superInterfaceTypes().addAll(
+ ASTNode.copySubtrees(target, superInterfaceTypes()));
+ result.enumConstants().addAll(
+ ASTNode.copySubtrees(target, enumConstants()));
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.superInterfaceTypes);
+ acceptChildren(visitor, this.enumConstants);
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of superinterfaces of this enum
+ * declaration.
+ *
+ * @return the live list of super interface types
+ * (element type: <code>Type</code>)
+ */
+ public List superInterfaceTypes() {
+ return this.superInterfaceTypes;
+ }
+
+ /**
+ * Returns the live ordered list of enum constant declarations
+ * of this enum declaration.
+ *
+ * @return the live list of enum constant declarations
+ * (element type: {@link EnumConstantDeclaration})
+ */
+ public List enumConstants() {
+ return this.enumConstants;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AsbtractTypeDeclaration.
+ */
+ ITypeBinding internalResolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + this.modifiers.listSize()
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + this.superInterfaceTypes.listSize()
+ + this.enumConstants.listSize()
+ + this.bodyDeclarations.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java
new file mode 100644
index 000000000..f0ed33ed2
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent expressions.
+ * There are several kinds of expressions.
+ * <p>
+ * <pre>
+ * Expression:
+ * Name
+ * IntegerLiteral (includes decimal, hex, and octal forms; and long)
+ * FloatingPointLiteral (includes both float and double)
+ * CharacterLiteral
+ * NullLiteral
+ * BooleanLiteral
+ * StringLiteral
+ * TypeLiteral
+ * ThisExpression
+ * SuperFieldAccess
+ * FieldAccess
+ * Assignment
+ * ParenthesizedExpression
+ * ClassInstanceCreation
+ * ArrayCreation
+ * ArrayInitializer
+ * MethodInvocation
+ * SuperMethodInvocation
+ * ArrayAccess
+ * InfixExpression
+ * InstanceofExpression
+ * ConditionalExpression
+ * PostfixExpression
+ * PrefixExpression
+ * CastExpression
+ * VariableDeclarationExpression
+ * </pre>
+ * </p>
+ *
+ * @since 2.0
+ */
+public abstract class Expression extends ASTNode {
+
+ /**
+ * Creates a new AST node for an expression owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Expression(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Resolves and returns the compile-time constant expression value as
+ * specified in JLS2 15.28, if this expression has one. Constant expression
+ * values are unavailable unless bindings are requested when the AST is
+ * being built. If the type of the value is a primitive type, the result
+ * is the boxed equivalent (i.e., int returned as an <code>Integer</code>);
+ * if the type of the value is <code>String</code>, the result is the string
+ * itself. If the expression does not have a compile-time constant expression
+ * value, the result is <code>null</code>.
+ * <p>
+ * Resolving constant expressions takes into account the value of simple
+ * and qualified names that refer to constant variables (JLS2 4.12.4).
+ * </p>
+ * <p>
+ * Note 1: enum constants are not considered constant expressions.
+ * The result is always <code>null</code> for these.
+ * </p>
+ * <p>
+ * Note 2: Compile-time constant expressions cannot denote <code>null</code>.
+ * So technically {@link NullLiteral} nodes are not constant expressions.
+ * The result is <code>null</code> for these nonetheless.
+ * </p>
+ *
+ * @return the constant expression value, or <code>null</code> if this
+ * expression has no constant expression value or if bindings were not
+ * requested when the AST was created
+ * @since 3.1
+ */
+ public final Object resolveConstantExpressionValue() {
+ return this.ast.getBindingResolver().resolveConstantExpressionValue(this);
+ }
+
+ /**
+ * Resolves and returns the binding for the type of this expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding for the type of this expression, or
+ * <code>null</code> if the type cannot be resolved
+ */
+ public final ITypeBinding resolveTypeBinding() {
+ return this.ast.getBindingResolver().resolveExpressionType(this);
+ }
+
+ /**
+ * Returns whether this expression node is the site of a boxing
+ * conversion (JLS3 5.1.7). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return <code>true</code> if this expression is the site of a
+ * boxing conversion, or <code>false</code> if either no boxing conversion
+ * is involved or if bindings were not requested when the AST was created
+ * @since 3.1
+ */
+ public final boolean resolveBoxing() {
+ return this.ast.getBindingResolver().resolveBoxing(this);
+ }
+
+ /**
+ * Returns whether this expression node is the site of an unboxing
+ * conversion (JLS3 5.1.8). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return <code>true</code> if this expression is the site of an
+ * unboxing conversion, or <code>false</code> if either no unboxing
+ * conversion is involved or if bindings were not requested when the
+ * AST was created
+ * @since 3.1
+ */
+ public final boolean resolveUnboxing() {
+ return this.ast.getBindingResolver().resolveUnboxing(this);
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java
new file mode 100644
index 000000000..14854db28
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionStatement.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Expression statement AST node type.
+ * <p>
+ * This kind of node is used to convert an expression (<code>Expression</code>)
+ * into a statement (<code>Statement</code>) by wrapping it.
+ * </p>
+ * <pre>
+ * ExpressionStatement:
+ * StatementExpression <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ExpressionStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ExpressionStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ExpressionStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented expression statement node owned by the given
+ * AST. By default, the expression statement is unspecified, but legal,
+ * method invocation expression.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ExpressionStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return EXPRESSION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ExpressionStatement result = new ExpressionStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this expression statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new MethodInvocation(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this expression statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
new file mode 100644
index 000000000..ad9ac5140
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field access expression AST node type.
+ *
+ * <pre>
+ * FieldAccess:
+ * Expression <b>.</b> Identifier
+ * </pre>
+ *
+ * <p>
+ * Note that there are several kinds of expressions that resemble field access
+ * expressions: qualified names, this expressions, and super field access
+ * expressions. The following guidelines help with correct usage:
+ * <ul>
+ * <li>An expression like "foo.this" can only be represented as a this
+ * expression (<code>ThisExpression</code>) containing a simple name.
+ * "this" is a keyword, and therefore invalid as an identifier.</li>
+ * <li>An expression like "this.foo" can only be represented as a field
+ * access expression (<code>FieldAccess</code>) containing a this expression
+ * and a simple name. Again, this is because "this" is a keyword, and
+ * therefore invalid as an identifier.</li>
+ * <li>An expression with "super" can only be represented as a super field
+ * access expression (<code>SuperFieldAccess</code>). "super" is a also
+ * keyword, and therefore invalid as an identifier.</li>
+ * <li>An expression like "foo.bar" can be represented either as a
+ * qualified name (<code>QualifiedName</code>) or as a field access
+ * expression (<code>FieldAccess</code>) containing simple names. Either
+ * is acceptable, and there is no way to choose between them without
+ * information about what the names resolve to
+ * (<code>ASTParser</code> may return either).</li>
+ * <li>Other expressions ending in an identifier, such as "foo().bar" can
+ * only be represented as field access expressions
+ * (<code>FieldAccess</code>).</li>
+ * </ul>
+ * </p>
+ *
+ * @see QualifiedName
+ * @see ThisExpression
+ * @see SuperFieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class FieldAccess extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(FieldAccess.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(FieldAccess.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression expression = null;
+
+ /**
+ * The field; lazily initialized; defaults to an unspecified,
+ * but legal, simple field name.
+ */
+ private SimpleName fieldName = null;
+
+ /**
+ * Creates a new unparented node for a field access expression owned by the
+ * given AST. By default, the expression and field are both unspecified,
+ * but legal, names.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ FieldAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FIELD_ACCESS;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FieldAccess result = new FieldAccess(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setName((SimpleName) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this field access expression.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this field access expression.
+ *
+ * @param expression the new expression
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the field accessed in this field access expression.
+ *
+ * @return the field name
+ */
+ public SimpleName getName() {
+ if (this.fieldName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.fieldName == null) {
+ preLazyInit();
+ this.fieldName = new SimpleName(this.ast);
+ postLazyInit(this.fieldName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.fieldName;
+ }
+
+ /**
+ * Sets the name of the field accessed in this field access expression.
+ *
+ * @param fieldName the field name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName fieldName) {
+ if (fieldName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.fieldName;
+ preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ this.fieldName = fieldName;
+ postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /**
+ * Resolves and returns the binding for the field accessed by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the variable binding, or <code>null</code> if the binding cannot
+ * be resolved
+ * @since 3.0
+ */
+ public IVariableBinding resolveFieldBinding() {
+ return this.ast.getBindingResolver().resolveField(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.fieldName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccessSpec.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccessSpec.java
new file mode 100644
index 000000000..9b587c43d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccessSpec.java
@@ -0,0 +1,294 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: FieldAccessSpec.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT
+ *
+ *
+ * Represents DOM-ASTNode for callout binding to a field of the corresponding base class (OTJLD §3.5),
+ * which has to handle code from e.g. :
+ * get value
+ * set value
+ * to e.g. :
+ * get int value
+ * set String value
+ *
+ * This class has following properties:
+ * modifiers (JLS2) or isSetter (JLS3)
+ * fieldType,
+ * name,
+ * signature
+ *
+ * This node can be used only in CalloutMethodDeclaration.
+ *
+ * @author jsv
+ */
+public class FieldAccessSpec extends MethodMappingElement
+{
+ /**
+ * The "signature" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor SIGNATURE_PROPERTY =
+ internalSignaturePropertyFactory(FieldAccessSpec.class);
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(FieldAccessSpec.class);
+
+ /**
+ * The "fieldType" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor FIELD_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(FieldAccessSpec.class, "fieldType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static
+ {
+ List propertyList = new ArrayList(4);
+ createPropertyList(FieldAccessSpec.class, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(FIELD_TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(FieldAccessSpec.class, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(FIELD_TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ if (apiLevel == AST.JLS2_INTERNAL)
+ return PROPERTY_DESCRIPTORS_2_0;
+ else
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+
+ boolean isSetter = false;
+
+ /**
+ * The field type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type _fieldType = null;
+
+ FieldAccessSpec(AST ast)
+ {
+ super(ast);
+ }
+
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean isGetRequest, boolean value)
+ {
+ if (property == SIGNATURE_PROPERTY)
+ {
+ if (isGetRequest)
+ {
+ return hasSignature();
+ }
+ else
+ {
+ setSignatureFlag(value);
+ return false;
+ }
+ }
+ return super.internalGetSetBooleanProperty(property, isGetRequest, value);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean isGetRequest, ASTNode child)
+ {
+ if (property == NAME_PROPERTY)
+ {
+ if (isGetRequest)
+ {
+ return getName();
+ }
+ else
+ {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == FIELD_TYPE_PROPERTY)
+ {
+ if (isGetRequest)
+ {
+ return getFieldType();
+ }
+ else
+ {
+ setFieldType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, isGetRequest, child);
+ }
+
+ SimplePropertyDescriptor internalSignatureProperty() {
+ return SIGNATURE_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ final int getNodeType0()
+ {
+ return FIELD_ACCESS_SPEC;
+ }
+
+ ASTNode clone0(AST target)
+ {
+ FieldAccessSpec result = new FieldAccessSpec(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setSignatureFlag(this.hasSignature());
+ result.setName((SimpleName) this.getName().clone(target));
+ result.setFieldType(
+ (Type) ASTNode.copySubtree(target, getFieldType()));
+ return result;
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getFieldType());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ int treeSize()
+ {
+ return memSize()
+ + (this.getName() == null ? 0 : getName().treeSize())
+ + (this.getFieldType() == null ? 0 : getFieldType().treeSize());
+ }
+
+ int memSize()
+ {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /**
+ * Returns the field type of the field in this FieldAccessSpec,
+ * exclusive of any extra array dimensions (JLS2 API only).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available.
+ * </p>
+ *
+ * @return the return type, possibly the void primitive type
+ */
+ public Type getFieldType()
+ {
+ if (this._fieldType == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this._fieldType == null)
+ {
+ preLazyInit();
+ this._fieldType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this._fieldType, FIELD_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this._fieldType;
+ }
+
+ /**
+ * Sets the field type of the field declared in this FieldAccessSpec
+ * declaration to the given type, exclusive of any extra array dimensions
+ * (JLS2 API only). This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * </p>
+ *
+ * @param type the new return type, possibly the void primitive type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setFieldType(Type type)
+ {
+ if (type == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this._fieldType;
+ preReplaceChild(oldChild, type, FIELD_TYPE_PROPERTY);
+ this._fieldType = type;
+ postReplaceChild(oldChild, type, FIELD_TYPE_PROPERTY);
+ }
+
+ public IVariableBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveVariable(this);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
new file mode 100644
index 000000000..d82bf6f4b
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field declaration node type.
+ * <p>
+ * This kind of node collects several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a single body declaration
+ * (<code>BodyDeclaration</code>), all sharing the same modifiers and base type.
+ * </p>
+ * <pre>
+ * FieldDeclaration:
+ * [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
+ * { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source range begins with the first
+ * character of the "/**" comment delimiter. When there is no Javadoc comment,
+ * the source range begins with the first character of the initial modifier or
+ * type. The source range extends through the last character of the final ";".
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class FieldDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(FieldDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(FieldDeclaration.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(FieldDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(FRAGMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(5);
+ createPropertyList(FieldDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(FRAGMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable declaration fragments (element type:
+ * {@link VariableDeclarationFragment}). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented field declaration statement node owned
+ * by the given AST. By default, the field declaration has: no modifiers,
+ * an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ FieldDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FIELD_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FieldDeclaration result = new FieldDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the base type declared in this field declaration.
+ * <p>
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ * </p>
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this field declaration to the given type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this field
+ * declaration. Adding and removing nodes from this list affects this node
+ * dynamically. All nodes in this list must be
+ * <code>VariableDeclarationFragment</code>s; attempts to add any other
+ * type of node will trigger an exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * statement (element type: <code>VariableDeclarationFragment</code>)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
new file mode 100644
index 000000000..e9f56202e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * For statement AST node type.
+ *
+ * <pre>
+ * ForStatement:
+ * <b>for</b> <b>(</b>
+ * [ ForInit ]<b>;</b>
+ * [ Expression ] <b>;</b>
+ * [ ForUpdate ] <b>)</b>
+ * Statement
+ * ForInit:
+ * Expression { <b>,</b> Expression }
+ * ForUpdate:
+ * Expression { <b>,</b> Expression }
+ * </pre>
+ * <p>
+ * Note: When variables are declared in the initializer
+ * of a for statement such as "<code>for (int a=1, b=2;;);</code>",
+ * they should be represented as a single
+ * <code>VariableDeclarationExpression</code>
+ * with two fragments, rather than being split up into a pair
+ * of expressions.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ForStatement extends Statement {
+
+ /**
+ * The "initializers" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor INITIALIZERS_PROPERTY =
+ new ChildListPropertyDescriptor(ForStatement.class, "initializers", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ForStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "updaters" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor UPDATERS_PROPERTY =
+ new ChildListPropertyDescriptor(ForStatement.class, "updaters", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(ForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(ForStatement.class, properyList);
+ addProperty(INITIALIZERS_PROPERTY, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(UPDATERS_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of initializer expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList initializers =
+ new ASTNode.NodeList(INITIALIZERS_PROPERTY);
+
+ /**
+ * The condition expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalConditionExpression = null;
+
+ /**
+ * The list of update expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList updaters =
+ new ASTNode.NodeList(UPDATERS_PROPERTY);
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for a for statement owned by the given AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ForStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == INITIALIZERS_PROPERTY) {
+ return initializers();
+ }
+ if (property == UPDATERS_PROPERTY) {
+ return updaters();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FOR_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ForStatement result = new ForStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.initializers().addAll(ASTNode.copySubtrees(target, initializers()));
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ result.updaters().addAll(ASTNode.copySubtrees(target, updaters()));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.initializers);
+ acceptChild(visitor, getExpression());
+ acceptChildren(visitor, this.updaters);
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of initializer expressions in this for
+ * statement.
+ * <p>
+ * The list should consist of either a list of so called statement
+ * expressions (JLS2, 14.8), or a single <code>VariableDeclarationExpression</code>.
+ * Otherwise, the for statement would have no Java source equivalent.
+ * </p>
+ *
+ * @return the live list of initializer expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List initializers() {
+ return this.initializers;
+ }
+
+ /**
+ * Returns the condition expression of this for statement, or
+ * <code>null</code> if there is none.
+ *
+ * @return the condition expression node, or <code>null</code> if
+ * there is none
+ */
+ public Expression getExpression() {
+ return this.optionalConditionExpression;
+ }
+
+ /**
+ * Sets or clears the condition expression of this return statement.
+ *
+ * @param expression the condition expression node, or <code>null</code>
+ * if there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalConditionExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalConditionExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of update expressions in this for
+ * statement.
+ * <p>
+ * The list should consist of so called statement expressions. Otherwise,
+ * the for statement would have no Java source equivalent.
+ * </p>
+ *
+ * @return the live list of update expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List updaters() {
+ return this.updaters;
+ }
+
+ /**
+ * Returns the body of this for statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this for statement.
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the body of a for statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the body of a <code>ForStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + this.initializers.listSize()
+ + this.updaters.listSize()
+ + (this.optionalConditionExpression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardPredicateDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardPredicateDeclaration.java
new file mode 100644
index 000000000..ee9ace527
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardPredicateDeclaration.java
@@ -0,0 +1,199 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: GuardPredicateDeclaration.java 23417 2010-02-03 20:13:55Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a declaration of a guard predicate in OT/J (OTJLD §5.4).
+ *
+ * @author stephan
+ */
+public class GuardPredicateDeclaration extends ASTNode {
+
+ /**
+ * Structural property for the boolean expression that represents the guard's implementation.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(GuardPredicateDeclaration.class, "expression", Expression.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "base" structural property of this node type, marking whether it is a "base guard" or not.
+ */
+ public static final SimplePropertyDescriptor BASE_PROPERTY =
+ new SimplePropertyDescriptor(GuardPredicateDeclaration.class, "base", boolean.class, MANDATORY); //$NON-NLS-1$
+
+
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(GuardPredicateDeclaration.class, propertyList);
+ addProperty(BASE_PROPERTY, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("JLS2 not supported"); //$NON-NLS-1$
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ private Expression expression = null;
+ private boolean isBase = false;
+
+ GuardPredicateDeclaration(AST ast)
+ {
+ super(ast);
+ }
+
+ @Override
+ boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)
+ {
+ if (property == BASE_PROPERTY) {
+ if (get) {
+ return isBase();
+ } else {
+ setBase(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ @Override
+ ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression)child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ @Override
+ int getNodeType0() {
+ return GUARD_PREDICATE_DECLARATION;
+ }
+
+ @Override
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ unsupportedIn2();
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, this.expression);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ @Override
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ @Override
+ ASTNode clone0(AST target) {
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL)
+ unsupportedIn2();
+ GuardPredicateDeclaration result = new GuardPredicateDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setBase(this.isBase());
+ result.setExpression((Expression)ASTNode.copySubtree(target, getExpression()));
+ return result;
+ }
+
+ public boolean isBase()
+ {
+ return isBase;
+ }
+
+ public void setBase(boolean isBase)
+ {
+ preValueChange(BASE_PROPERTY);
+ this.isBase = isBase;
+ postValueChange(BASE_PROPERTY);
+ }
+
+
+ public ASTNode getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ @Override
+ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ @Override
+ void appendDebugString(StringBuffer buffer) {
+ if (this.isBase)
+ buffer.append("base "); //$NON-NLS-1$
+ buffer.append("when ("); //$NON-NLS-1$
+ this.expression.appendDebugString(buffer);
+ buffer.append(")"); //$NON-NLS-1$
+ }
+
+ @Override
+ int memSize() {
+ return BASE_NODE_SIZE; // FIXME(SH) + plus some constant??
+ }
+
+ @Override
+ int treeSize() {
+ return memSize() + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IAnnotationBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IAnnotationBinding.java
new file mode 100644
index 000000000..5f6c10e5f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IAnnotationBinding.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ * IBM Corporation - changed interface to extend IBinding
+ * IBM Corporation - renamed from IResolvedAnnotation to IAnnotationBinding
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Represents a resolved annotation. Resolved annotations are computed along with other
+ * bindings; they correspond to {@link Annotation} nodes.
+ *
+ * @since 3.2
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IAnnotationBinding extends IBinding {
+
+ /**
+ * Returns the complete list of member value pairs for this annotation, including
+ * ones explicitly listed in the annotation as well as entries for
+ * annotation type members with default values that are implied.
+ *
+ * @return a possibly empty list of resolved member value pairs
+ */
+ IMemberValuePairBinding[] getAllMemberValuePairs();
+
+ /**
+ * Returns the type of the annotation. The resulting type binding will always
+ * return <code>true</code> to <code>ITypeBinding.isAnnotation()</code>.
+ *
+ * @return the type of the annotation
+ */
+ ITypeBinding getAnnotationType();
+
+ /**
+ * Returns the list of declared member value pairs for this annotation.
+ * Returns an empty list for a {@link MarkerAnnotation}, a one element
+ * list for a {@link SingleMemberAnnotation}, and one entry for each
+ * of the explicitly listed values in a {@link NormalAnnotation}.
+ * <p>
+ * Note that the list only includes entries for annotation type members that are
+ * explicitly mentioned in the annotation. The list does not include any
+ * annotation type members with default values that are merely implied.
+ * Use {@link #getAllMemberValuePairs()} to get those as well.
+ * </p>
+ *
+ * @return a possibly empty list of resolved member value pairs
+ */
+ IMemberValuePairBinding[] getDeclaredMemberValuePairs();
+
+ /**
+ * Returns the name of the annotation type.
+ *
+ * @return the name of the annotation type
+ */
+ public String getName();
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
new file mode 100644
index 000000000..b185e662f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: IBinding.java 19895 2009-04-15 13:52:23Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IAnnotation;
+import org.eclipse.jdt.core.IJavaElement;
+
+/**
+ * A binding represents a named entity in the Java language. The world of
+ * bindings provides an integrated picture of the structure of the program as
+ * seen from the compiler's point of view. This interface declare protocol
+ * common to the various different kinds of named entities in the Java language:
+ * packages, types, fields, methods, constructors, and local variables.
+ *
+ * @see IPackageBinding
+ * @see ITypeBinding
+ * @see IVariableBinding
+ * @see IMethodBinding
+ * @see IAnnotationBinding
+ * @see IMemberValuePairBinding
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IBinding {
+
+ /**
+ * Kind constant (value 1) indicating a package binding.
+ * Bindings of this kind can be safely cast to <code>IPackageBinding</code>.
+ *
+ * @see #getKind()
+ * @see IPackageBinding
+ */
+ public static final int PACKAGE = 1;
+
+ /**
+ * Kind constant (value 2) indicating a type binding.
+ * Bindings of this kind can be safely cast to <code>ITypeBinding</code>.
+ *
+ * @see #getKind()
+ * @see ITypeBinding
+ */
+ public static final int TYPE = 2;
+
+ /**
+ * Kind constant (value 3) indicating a field or local variable binding.
+ * Bindings of this kind can be safely cast to <code>IVariableBinding</code>.
+ *
+ * @see #getKind()
+ * @see IVariableBinding
+ */
+ public static final int VARIABLE = 3;
+
+ /**
+ * Kind constant (value 4) indicating a method or constructor binding.
+ * Bindings of this kind can be safely cast to <code>IMethodBinding</code>.
+ *
+ * @see #getKind()
+ * @see IMethodBinding
+ */
+ public static final int METHOD = 4;
+
+ /**
+ * Kind constant (value 5) indicating an annotation binding.
+ * Bindings of this kind can be safely cast to <code>IAnnotationBinding</code>.
+ *
+ * @see #getKind()
+ * @see IAnnotationBinding
+ * @since 3.2
+ */
+ public static final int ANNOTATION = 5;
+
+ /**
+ * Kind constant (value 6) indicating a member value pair binding.
+ * Bindings of this kind can be safely cast to <code>IMemberValuePairBinding</code>.
+ *
+ * @see #getKind()
+ * @see IMemberValuePairBinding
+ * @since 3.2
+ */
+ public static final int MEMBER_VALUE_PAIR = 6;
+
+//{ObjectTeams: Binding for method mappings.
+ /**
+ * Kind constant (value 7) indicating a callin/callout method mapping.
+ * Bindings of this kind can be safely cast to <code>IMethodMappingBinding</code>.
+ *
+ * @see #getKind()
+ * @see IMethodMappingBinding
+ */
+ public static final int METHOD_MAPPING = 7;
+//mkr}
+
+ /**
+ * Return the resolved annotations associated with this binding.
+ * <ul>
+ * <li>Package bindings - these are annotations on a package declaration.
+ * </li>
+ * <li>Type bindings - these are annotations on a class, interface, enum,
+ * or annotation type declaration. The result is the same regardless of
+ * whether the type is parameterized.</li>
+ * <li>Method bindings - these are annotations on a method or constructor
+ * declaration. The result is the same regardless of whether the method is
+ * parameterized.</li>
+ * <li>Variable bindings - these are annotations on a field, enum constant,
+ * or formal parameter declaration.</li>
+ * <li>Annotation bindings - an empty array is always returned</li>
+ * <li>Member value pair bindings - an empty array is always returned</li>
+ * </ul>
+ *
+ * @return the list of resolved annotations, or the empty list if there are no
+ * annotations associated with the object
+ * @since 3.2
+ */
+ public IAnnotationBinding[] getAnnotations();
+
+ /**
+ * Returns the kind of bindings this is. That is one of the kind constants:
+ * <code>PACKAGE</code>,
+ * <code>TYPE</code>,
+ * <code>VARIABLE</code>,
+ * <code>METHOD</code>,
+ * <code>ANNOTATION</code>,
+ * or <code>MEMBER_VALUE_PAIR</code>.
+ * <p>
+ * Note that additional kinds might be added in the
+ * future, so clients should not assume this list is exhaustive and
+ * should program defensively, e.g. by having a reasonable default
+ * in a switch statement.
+ * </p>
+ * @return one of the kind constants
+ */
+ public int getKind();
+
+ /**
+ * Returns the name of this binding.
+ * Details of the name are specified with each specific kind of binding.
+ *
+ * @return the name of this binding
+ */
+ public String getName();
+
+ /**
+ * Returns the modifiers for this binding.
+ * <p>
+ * Note that deprecated is not included among the modifiers.
+ * Use <code>isDeprecated</code> to find out whether a binding is deprecated.
+ * </p>
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see Modifier
+ */
+ public int getModifiers();
+
+ /**
+ * Return whether this binding is for something that is deprecated.
+ * A deprecated class, interface, field, method, or constructor is one that
+ * is marked with the 'deprecated' tag in its Javadoc comment.
+ *
+ * @return <code>true</code> if this binding is deprecated, and
+ * <code>false</code> otherwise
+ */
+ public boolean isDeprecated();
+
+ /**
+ * Return whether this binding is created because the bindings recovery is enabled. This binding is considered
+ * to be incomplete. Its internal state might be incomplete.
+ *
+ * @return <code>true</code> if this binding is a recovered binding, and
+ * <code>false</code> otherwise
+ * @since 3.3
+ */
+ public boolean isRecovered();
+
+ /**
+ * Returns whether this binding is synthetic. A synthetic binding is one that
+ * was made up by the compiler, rather than something declared in the
+ * source code. Note that default constructors (the 0-argument constructor that
+ * the compiler generates for class declarations with no explicit constructors
+ * declarations) are not generally considered synthetic (although they
+ * may be if the class itself is synthetic).
+ * But see {@link IMethodBinding#isDefaultConstructor() IMethodBinding.isDefaultConstructor}
+ * for cases where the compiled-generated default constructor can be recognized
+ * instead.
+ *
+ * @return <code>true</code> if this binding is synthetic, and
+ * <code>false</code> otherwise
+ * @see IMethodBinding#isDefaultConstructor()
+ */
+ public boolean isSynthetic();
+
+ /**
+ * Returns the Java element that corresponds to this binding.
+ * Returns <code>null</code> if this binding has no corresponding
+ * Java element.
+ * <p>
+ * For array types, this method returns the Java element that corresponds
+ * to the array's element type. For raw and parameterized types, this method
+ * returns the Java element of the erasure. For annotations, this method
+ * returns the Java element of the annotation (i.e. an {@link IAnnotation}).
+ * </p>
+ * <p>
+ * Here are the cases where a <code>null</code> should be expected:
+ * <ul>
+ * <li>primitive types, including void</li>
+ * <li>null type</li>
+ * <li>wildcard types</li>
+ * <li>capture types</li>
+ * <li>array types of any of the above</li>
+ * <li>the "length" field of an array type</li>
+ * <li>the default constructor of a source class</li>
+ * <li>the constructor of an anonymous class</li>
+ * <li>member value pairs</li>
+ * </ul>
+ * For all other kind of type, method, variable, annotation and package bindings,
+ * this method returns non-<code>null</code>.
+ * </p>
+ *
+ * @return the Java element that corresponds to this binding,
+ * or <code>null</code> if none
+ * @since 3.1
+ */
+ public IJavaElement getJavaElement();
+
+ /**
+ * Returns the key for this binding.
+ * <p>
+ * Within a connected cluster of bindings (for example, all bindings
+ * reachable from a given AST), each binding will have a distinct keys.
+ * The keys are generated in a manner that is predictable and as
+ * stable as possible. This last property makes these keys useful for
+ * comparing bindings between disconnected clusters of bindings (for example,
+ * the bindings between the "before" and "after" ASTs of the same
+ * compilation unit).
+ * </p>
+ * <p>
+ * The exact details of how the keys are generated is unspecified.
+ * However, it is a function of the following information:
+ * <ul>
+ * <li>packages - the name of the package (for an unnamed package,
+ * some internal id)</li>
+ * <li>classes or interfaces - the VM name of the type and the key
+ * of its package</li>
+ * <li>array types - the key of the component type and number of
+ * dimensions</li>
+ * <li>primitive types - the name of the primitive type</li>
+ * <li>fields - the name of the field and the key of its declaring
+ * type</li>
+ * <li>methods - the name of the method, the key of its declaring
+ * type, and the keys of the parameter types</li>
+ * <li>constructors - the key of its declaring class, and the
+ * keys of the parameter types</li>
+ * <li>local variables - the name of the local variable, the index of the
+ * declaring block relative to its parent, the key of its method</li>
+ * <li>local types - the name of the type, the index of the declaring
+ * block relative to its parent, the key of its method</li>
+ * <li>anonymous types - the occurence count of the anonymous
+ * type relative to its declaring type, the key of its declaring type</li>
+ * <li>enum types - treated like classes</li>
+ * <li>annotation types - treated like interfaces</li>
+ * <li>type variables - the name of the type variable and
+ * the key of the generic type or generic method that declares that
+ * type variable</li>
+ * <li>wildcard types - the key of the optional wildcard type bound</li>
+ * <li>capture type bindings - the key of the wildcard captured</li>
+ * <li>generic type instances - the key of the generic type and the keys
+ * of the type arguments used to instantiate it, and whether the
+ * instance is explicit (a parameterized type reference) or
+ * implicit (a raw type reference)</li>
+ * <li>generic method instances - the key of the generic method and the keys
+ * of the type arguments used to instantiate it, and whether the
+ * instance is explicit (a parameterized method reference) or
+ * implicit (a raw method reference)</li>
+ * <li>members of generic type instances - the key of the generic type
+ * instance and the key of the corresponding member in the generic
+ * type</li>
+ * <li>annotations - the key of the annotated element and the key of
+ * the annotation type</li>
+ * </ul>
+ * </p>
+ * <p>Note that the key for member value pair bindings is
+ * not yet implemented. This returns <code>null</code> for this kind of bindings.<br>
+ * Recovered bindings have a unique key.
+ * </p>
+ *
+ * @return the key for this binding
+ */
+ public String getKey();
+
+ /**
+ * There is no special definition of equality for bindings; equality is
+ * simply object identity. Within the context of a single cluster of
+ * bindings, each binding is represented by a distinct object. However,
+ * between different clusters of bindings, the binding objects may or may
+ * not be different; in these cases, the client should compare bindings
+ * using {@link #isEqualTo(IBinding)}, which checks their keys.
+ *
+ * @param obj {@inheritDoc}
+ * @return {@inheritDoc}
+ */
+ public boolean equals(Object obj);
+
+ /**
+ * Returns whether this binding has the same key as that of the given
+ * binding. Within the context of a single cluster of bindings, each
+ * binding is represented by a distinct object. However, between
+ * different clusters of bindings, the binding objects may or may
+ * not be different objects; in these cases, the binding keys
+ * are used where available.
+ *
+ * @param binding the other binding, or <code>null</code>
+ * @return <code>true</code> if the given binding is the identical
+ * object as this binding, or if the keys of both bindings are the
+ * same string; <code>false</code> if the given binding is
+ * <code>null</code>, or if the bindings do not have the same key,
+ * or if one or both of the bindings have no key
+ * @see #getKey()
+ * @since 3.1
+ */
+ public boolean isEqualTo(IBinding binding);
+
+ /**
+ * Returns a string representation of this binding suitable for debugging
+ * purposes only.
+ *
+ * @return a debug string
+ */
+ public String toString();
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java
new file mode 100644
index 000000000..d492a90a2
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Internal marker-type interface used to tag node types that can legitimately
+ * be included in {@link TagElement#fragments() TagElement.fragments()}.
+ *
+ * @since 3.0
+ */
+interface IDocElement {
+ // marker-type interfaces have no members
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IExtendedModifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IExtendedModifier.java
new file mode 100644
index 000000000..50b831cf3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IExtendedModifier.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Common interface for AST nodes that represent modifiers or
+ * annotations.
+ * <pre>
+ * ExtendedModifier:
+ * Modifier
+ * Annotation
+ * </pre>
+ * @since 3.1
+ */
+public interface IExtendedModifier {
+
+ /**
+ * Returns whether this extended modifier is a standard modifier.
+ *
+ * @return <code>true</code> if this is a standard modifier
+ * (instance of {@link Modifier}), and <code>false</code> otherwise
+ */
+ public boolean isModifier();
+
+ /**
+ * Returns whether this extended modifier is an annotation.
+ *
+ * @return <code>true</code> if this is an annotation
+ * (instance of a subclass of {@link Annotation}), and
+ * <code>false</code> otherwise
+ */
+ public boolean isAnnotation();
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMemberValuePairBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMemberValuePairBinding.java
new file mode 100644
index 000000000..1d8fb5183
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMemberValuePairBinding.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ * IBM Corporation - changed interface to extend IBinding
+ * IBM Corporation - renamed from IResolvedMemberValuePair to IMemberValuePairBinding
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Represents a resolved instance of an annotation's member value pair.
+ * Resolved annotation are computed along with other bindings; these objects
+ * correspond to {@link MemberValuePair} nodes.
+ *
+ * @since 3.2
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMemberValuePairBinding extends IBinding {
+/**
+ * Returns the name of the annotation type member.
+ *
+ * @return the name of the member
+ */
+public String getName();
+
+/**
+ * Returns the method binding corresponding to the named annotation type member.
+ *
+ * @return the method binding for the annotation type member
+ */
+public IMethodBinding getMethodBinding();
+
+/**
+ * Returns the resolved value. Resolved values are represented as follows:
+ * <ul>
+ * <li>Primitive type - the equivalent boxed object</li>
+ * <li>java.lang.Class - the <code>ITypeBinding</code> for the class object</li>
+ * <li>java.lang.String - the string value itself</li>
+ * <li>enum type - the <code>IVariableBinding</code> for the enum constant</li>
+ * <li>annotation type - an <code>IAnnotationBinding</code></li>
+ * <li>array type - an <code>Object[]</code> whose elements are as per above
+ * (the language only allows single dimensional arrays in annotations)</li>
+ * </ul>
+ *
+ * @return the resolved value, or <code>null</code> if none exists
+ */
+public Object getValue();
+
+/**
+ * @return <code>true</code> iff this member value pair's value is the default value.
+ * Returns <code>false</code> otherwise.
+ */
+public boolean isDefault();
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
new file mode 100644
index 000000000..e6ee64fc6
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * A method binding represents a method or constructor of a class or interface.
+ * Method bindings usually correspond directly to method or
+ * constructor declarations found in the source code.
+ * However, in certain cases of references to a generic method,
+ * the method binding may correspond to a copy of a generic method
+ * declaration with substitutions for the method's type parameters
+ * (for these, <code>getTypeArguments</code> returns a non-empty
+ * list, and either <code>isParameterizedMethod</code> or
+ * <code>isRawMethod</code> returns <code>true</code>).
+ * And in certain cases of references to a method declared in a
+ * generic type, the method binding may correspond to a copy of a
+ * method declaration with substitutions for the type's type
+ * parameters (for these, <code>getTypeArguments</code> returns
+ * an empty list, and both <code>isParameterizedMethod</code> and
+ * <code>isRawMethod</code> return <code>false</code>).
+ *
+ * @see ITypeBinding#getDeclaredMethods()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMethodBinding extends IBinding {
+
+ /**
+ * Returns whether this binding is for a constructor or a method.
+ *
+ * @return <code>true</code> if this is the binding for a constructor,
+ * and <code>false</code> if this is the binding for a method
+ */
+ public boolean isConstructor();
+
+ /**
+ * Returns whether this binding is known to be a compiler-generated
+ * default constructor.
+ * <p>
+ * This method returns <code>false</code> for:
+ * <ul>
+ * <li>methods</li>
+ * <li>constructors with more than one parameter</li>
+ * <li>0-argument constructors where the binding information was obtained
+ * from a Java source file containing an explicit 0-argument constructor
+ * declaration</li>
+ * <li>0-argument constructors where the binding information was obtained
+ * from a Java class file (it is not possible to determine from a
+ * class file whether a 0-argument constructor was present in the source
+ * code versus generated automatically by a Java compiler)</li>
+ * </ul>
+ *
+ * @return <code>true</code> if this is known to be the binding for a
+ * compiler-generated default constructor, and <code>false</code>
+ * otherwise
+ * @since 3.0
+ */
+ public boolean isDefaultConstructor();
+
+ /**
+ * Returns the name of the method declared in this binding. The method name
+ * is always a simple identifier. The name of a constructor is always the
+ * same as the declared name of its declaring class.
+ *
+ * @return the name of this method, or the declared name of this
+ * constructor's declaring class
+ */
+ public String getName();
+
+ /**
+ * Returns the type binding representing the class or interface
+ * that declares this method or constructor.
+ *
+ * @return the binding of the class or interface that declares this method
+ * or constructor
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the resolved default value of an annotation type member,
+ * or <code>null</code> if the member has no default value, or if this
+ * is not the binding for an annotation type member.
+ * <p>
+ * Resolved values are represented as follows (same as for
+ * {@link IMemberValuePairBinding#getValue()}):
+ * <ul>
+ * <li>Primitive type - the equivalent boxed object</li>
+ * <li>java.lang.Class - the <code>ITypeBinding</code> for the class object</li>
+ * <li>java.lang.String - the string value itself</li>
+ * <li>enum type - the <code>IVariableBinding</code> for the enum constant</li>
+ * <li>annotation type - an <code>IAnnotationBinding</code></li>
+ * <li>array type - an <code>Object[]</code> whose elements are as per above
+ * (the language only allows single dimensional arrays in annotations)</li>
+ * </ul>
+ *
+ * @return the default value of this annotation type member, or <code>null</code>
+ * if none or not applicable
+ * @since 3.2
+ */
+ public Object getDefaultValue();
+
+ /**
+ * Returns the resolved annotations of a parameter of this method.
+ * The result returned is the same regardless of whether
+ * this is a parameterized method.
+ *
+ * @param paramIndex the index of the parameter of interest
+ * @return the resolved annotations of the <code>paramIndex</code>th parameter,
+ * or an empty list if there are none
+ * @throws ArrayIndexOutOfBoundsException if <code>paramIndex</code> is
+ * not a valid index
+ * @since 3.2
+ */
+ public IAnnotationBinding[] getParameterAnnotations(int paramIndex);
+
+ /**
+ * Returns a list of type bindings representing the formal parameter types,
+ * in declaration order, of this method or constructor. Returns an array of
+ * length 0 if this method or constructor does not takes any parameters.
+ * <p>
+ * Note that the binding for the last parameter type of a vararg method
+ * declaration like <code>void fun(Foo... args)</code> is always for
+ * an array type (i.e., <code>Foo[]</code>) reflecting the the way varargs
+ * get compiled. However, the type binding obtained directly from
+ * the <code>SingleVariableDeclaration</code> for the vararg parameter
+ * is always for the type as written; i.e., the type binding for
+ * <code>Foo</code>.
+ * </p>
+ * <p>
+ * Note: The result does not include synthetic parameters introduced by
+ * inner class emulation.
+ * </p>
+ *
+ * @return a (possibly empty) list of type bindings for the formal
+ * parameters of this method or constructor
+ */
+ public ITypeBinding[] getParameterTypes();
+
+ /**
+ * Returns the binding for the return type of this method. Returns the
+ * special primitive <code>void</code> return type for constructors.
+ *
+ * @return the binding for the return type of this method, or the
+ * <code>void</code> return type for constructors
+ */
+ public ITypeBinding getReturnType();
+
+ /**
+ * Returns a list of type bindings representing the types of the exceptions thrown
+ * by this method or constructor. Returns an array of length 0 if this method
+ * throws no exceptions. The resulting types are in no particular order.
+ *
+ * @return a list of type bindings for exceptions
+ * thrown by this method or constructor
+ */
+ public ITypeBinding[] getExceptionTypes();
+
+ /**
+ * Returns the type parameters of this method or constructor binding.
+ * <p>
+ * Note that type parameters only occur on the binding of the
+ * declaring generic method. Type bindings corresponding to a raw or
+ * parameterized reference to a generic method do not carry type
+ * parameters (they instead have non-empty type arguments
+ * and non-trivial erasure).
+ * </p>
+ *
+ * @return the list of binding for the type variables for the type
+ * parameters of this method, or otherwise the empty list
+ * @see ITypeBinding#isTypeVariable()
+ * @since 3.1
+ */
+ public ITypeBinding[] getTypeParameters();
+
+ /**
+ * Returns whether this is the binding for an annotation type member.
+ *
+ * @return <code>true</code> iff this is the binding for an annotation type member
+ * and <code>false</code> otherwise
+ * @since 3.2
+ */
+ public boolean isAnnotationMember();
+
+ /**
+ * Returns whether this method binding represents a declaration of
+ * a generic method.
+ * <p>
+ * Note that type parameters only occur on the binding of the
+ * declaring generic method; e.g., <code>public &lt;T&gt; T identity(T t);</code>.
+ * Method bindings corresponding to a raw or parameterized reference to a generic
+ * method do not carry type parameters (they instead have non-empty type arguments
+ * and non-trivial erasure).
+ * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+ * </p>
+ * <p>
+ * Note that {@link #isGenericMethod()},
+ * {@link #isParameterizedMethod()},
+ * and {@link #isRawMethod()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this method binding represents a
+ * declaration of a generic method, and <code>false</code> otherwise
+ * @see #getTypeParameters()
+ * @since 3.1
+ */
+ public boolean isGenericMethod();
+
+ /**
+ * Returns whether this method binding represents an instance of
+ * a generic method corresponding to a parameterized method reference.
+ * <p>
+ * Note that {@link #isGenericMethod()},
+ * {@link #isParameterizedMethod()},
+ * and {@link #isRawMethod()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this method binding represents a
+ * an instance of a generic method corresponding to a parameterized
+ * method reference, and <code>false</code> otherwise
+ * @see #getMethodDeclaration()
+ * @see #getTypeArguments()
+ * @since 3.1
+ */
+ public boolean isParameterizedMethod();
+
+ /**
+ * Returns the type arguments of this generic method instance, or the
+ * empty list for other method bindings.
+ * <p>
+ * Note that type arguments only occur on a method binding that represents
+ * an instance of a generic method corresponding to a raw or parameterized
+ * reference to a generic method. Do not confuse these with type parameters
+ * which only occur on the method binding corresponding directly to the
+ * declaration of a generic method.
+ * </p>
+ *
+ * @return the list of type bindings for the type arguments used to
+ * instantiate the corrresponding generic method, or otherwise the empty list
+ * @see #getMethodDeclaration()
+ * @see #isParameterizedMethod()
+ * @see #isRawMethod()
+ * @since 3.1
+ */
+ public ITypeBinding[] getTypeArguments();
+
+ /**
+ * Returns the binding for the method declaration corresponding to this
+ * method binding. For parameterized methods ({@link #isParameterizedMethod()})
+ * and raw methods ({@link #isRawMethod()}), this method returns the binding
+ * for the corresponding generic method. For other method bindings, this
+ * returns the same binding.
+ *
+ * <p>Note: The one notable exception is the method <code>Object.getClass()</code>,
+ * which is declared to return <code>Class&lt;? extends Object&gt;</code>, but
+ * when invoked its return type becomes <code>Class&lt;? extends
+ * </code><em>R</em><code>&gt;</code>, where <em>R</em> is the compile type of
+ * the receiver of the method invocation.</p>
+ *
+ * @return the method binding
+ * @since 3.1
+ */
+ public IMethodBinding getMethodDeclaration();
+
+ /**
+ * Returns whether this method binding represents an instance of
+ * a generic method corresponding to a raw method reference.
+ * <p>
+ * Note that {@link #isGenericMethod()},
+ * {@link #isParameterizedMethod()},
+ * and {@link #isRawMethod()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this method binding represents a
+ * an instance of a generic method corresponding to a raw
+ * method reference, and <code>false</code> otherwise
+ * @see #getMethodDeclaration()
+ * @see #getTypeArguments()
+ * @since 3.1
+ */
+ public boolean isRawMethod();
+
+ /**
+ * Returns whether this method's signature is a subsignature of the given method as
+ * specified in section 8.4.2 of <em>The Java Language Specification, Third Edition</em> (JLS3).
+ *
+ * @return <code>true</code> if this method's signature is a subsignature of the given method
+ * @since 3.1
+ */
+ public boolean isSubsignature(IMethodBinding otherMethod);
+
+ /**
+ * Returns whether this is a variable arity method.
+ * <p>
+ * Note: Variable arity ("varargs") methods were added in JLS3.
+ * </p>
+ *
+ * @return <code>true</code> if this is a variable arity method,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isVarargs();
+
+ /**
+ * Returns whether this method overrides the given method,
+ * as specified in section 8.4.8.1 of <em>The Java Language
+ * Specification, Third Edition</em> (JLS3).
+ *
+ * @param method the method that is possibly overriden
+ * @return <code>true</code> if this method overrides the given method,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean overrides(IMethodBinding method);
+
+//{ObjectTeams:
+ /**
+ * Is method copied due to implicit inheritance?
+ * (beware: copied methods don't have a java element.)
+ *
+ * @since OTDT 1.1.3
+ */
+ public boolean isCopied();
+// SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodMappingBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodMappingBinding.java
new file mode 100644
index 000000000..d354b2a4f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodMappingBinding.java
@@ -0,0 +1,60 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2005, 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: IMethodMappingBinding.java 23417 2010-02-03 20:13:55Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.objectteams.otdt.core.compiler.InferenceKind;
+
+/**
+ * A callin/callout binding represents a callin-/callout method mapping
+ * or a callout to field.
+ *
+ * @author mkr
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMethodMappingBinding extends IBinding
+{
+
+ public String getName();
+
+ /**
+ * Returns the type binding representing the role class
+ * that declares this callin-/callout mapping.
+ *
+ * @return the binding of the role class that declares this mapping
+ */
+ public ITypeBinding getDeclaringRoleClass();
+
+ public ITypeBinding getReferencedBaseClass();
+
+ public IMethodBinding getRoleMethod();
+
+ public IMethodBinding[] getBaseMethods();
+
+ public String[] getBaseArgumentNames();
+
+ /**
+ * @return true if this is a callin binding (vs. callout)
+ */
+ public boolean isCallin();
+
+ /** Is this mapping an inferred callout? Which kind? */
+ public InferenceKind getInferenceKind();
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java
new file mode 100644
index 000000000..8f3c7aa87
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IPackageBinding.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * A package binding represents a named or unnamed package.
+ *
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IPackageBinding extends IBinding {
+
+ /**
+ * Returns the name of the package represented by this binding. For named
+ * packages, this is the fully qualified package name (using "." for
+ * separators). For unnamed packages, this is an empty string.
+ *
+ * @return the name of the package represented by this binding, or
+ * an empty string for an unnamed package
+ */
+ public String getName();
+
+ /**
+ * Returns whether this package is an unnamed package.
+ * See <em>The Java Language Specification</em> section 7.4.2 for details.
+ *
+ * @return <code>true</code> if this is an unnamed package, and
+ * <code>false</code> otherwise
+ */
+ public boolean isUnnamed();
+
+ /**
+ * Returns the list of name component making up the name of the package
+ * represented by this binding. For example, for the package named
+ * "com.example.tool", this method returns {"com", "example", "tool"}.
+ * Returns the empty list for unnamed packages.
+ *
+ * @return the name of the package represented by this binding, or the
+ * empty list for unnamed packages
+ */
+ public String[] getNameComponents();
+
+// /**
+// * Finds and returns the binding for the class or interface with the given
+// * name declared in this package.
+// * <p>
+// * For top-level classes and interfaces, the name here is just the simple
+// * name of the class or interface. For nested classes and interfaces, the
+// * name is the VM class name (in other words, a name like
+// * <code>"Outer$Inner"</code> as used to name the class file; see
+// * <code>ITypeBinding.getName</code>).
+// * </p>
+// *
+// * @param name the name of a class or interface
+// * @return the type binding for the class or interface with the
+// * given name declared in this package, or <code>null</code>
+// * if there is no such type
+// */
+// public ITypeBinding findTypeBinding(String name);
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
new file mode 100644
index 000000000..c5d8b48a3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -0,0 +1,1041 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ITypeBinding.java 21855 2009-07-14 18:55:31Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+
+/**
+ * MIGRATION_STATE: 3.4
+ *
+ * <h4>OTDT changes:</h4>
+ * <dl>
+ * <dt>What:<dd> new lookup functions for teams and roles.
+ * </dl>
+ * <hr>
+ * A type binding represents fully-resolved type. There are a number of
+ * different kinds of type bindings:
+ * <ul>
+ * <li>a class - represents the class declaration;
+ * possibly with type parameters</li>
+ * <li>an interface - represents the class declaration;
+ * possibly with type parameters</li>
+ * <li>an enum - represents the enum declaration (enum types do not have
+ * have type parameters)</li>
+ * <li>an annotation - represents the annotation type declaration
+ * (annotation types do not have have type parameters)</li>
+ * <li>an array type - array types are referenced but not explicitly
+ * declared</li>
+ * <li>a primitive type (including the special return type <code>void</code>)
+ * - primitive types are referenced but not explicitly declared</li>
+ * <li>the null type - this is the special type of <code>null</code></li>
+ * <li>a type variable - represents the declaration of a type variable;
+ * possibly with type bounds</li>
+ * <li>a wildcard type - represents a wild card used as a type argument in
+ * a parameterized type reference</li>
+ * <li>a raw type - represents a legacy non-parameterized reference to
+ * a generic type</li>
+ * <li>a parameterized type - represents an copy of a type declaration
+ * with substitutions for its type parameters</li>
+ * <li>a capture - represents a capture binding</li>
+ * </ul>
+ *
+ * @see ITypeBinding#getDeclaredTypes()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ITypeBinding extends IBinding {
+
+
+ /**
+ * Answer an array type binding using the receiver and the given dimension.
+ *
+ * <p>If the receiver is an array binding, then the resulting dimension is the given dimension
+ * plus the dimension of the receiver. Otherwise the resulting dimension is the given
+ * dimension.</p>
+ *
+ * @param dimension the given dimension
+ * @return an array type binding
+ * @throws IllegalArgumentException:<ul>
+ * <li>if the receiver represents the void type</li>
+ * <li>if the resulting dimensions is lower than one or greater than 255</li>
+ * </ul>
+ * @since 3.3
+ */
+ public ITypeBinding createArrayType(int dimension);
+
+ /**
+ * Returns the binary name of this type binding.
+ * The binary name of a class is defined in the Java Language
+ * Specification 3rd edition, section 13.1.
+ * <p>
+ * Note that in some cases, the binary name may be unavailable.
+ * This may happen, for example, for a local type declared in
+ * unreachable code.
+ * </p>
+ *
+ * @return the binary name of this type, or <code>null</code>
+ * if the binary name is unknown
+ * @since 3.0
+ */
+ public String getBinaryName();
+
+ /**
+ * Returns the bound of this wildcard type if it has one.
+ * Returns <code>null</code> if this is not a wildcard type.
+ *
+ * @return the bound of this wildcard type, or <code>null</code> if none
+ * @see #isWildcardType()
+ * @see #isUpperbound()
+ * @since 3.1
+ */
+ public ITypeBinding getBound();
+
+ /**
+ * Returns the generic type associated with this wildcard type, if it has one.
+ * Returns <code>null</code> if this is not a wildcard type.
+ *
+ * @return the generic type associated with this wildcard type, or <code>null</code> if none
+ * @see #isWildcardType()
+ * @since 3.5
+ */
+ public ITypeBinding getGenericTypeOfWildcardType();
+
+ /**
+ * Returns the rank associated with this wildcard type. The rank of this wild card type is the relative
+ * position of the wild card type in the parameterization of the associated generic type.
+ * Returns <code>-1</code> if this is not a wildcard type.
+ *
+ * @return the rank associated with this wildcard type, or <code>-1</code> if none
+ * @see #isWildcardType()
+ * @since 3.5
+ */
+ public int getRank();
+
+ /**
+ * Returns the binding representing the component type of this array type,
+ * or <code>null</code> if this is not an array type binding. The component
+ * type of an array might be an array type.
+ * <p>This is subject to change before 3.2 release.</p>
+ *
+ * @return the component type binding, or <code>null</code> if this is
+ * not an array type
+ * @since 3.2
+ */
+ public ITypeBinding getComponentType();
+
+ /**
+ * Returns a list of bindings representing all the fields declared
+ * as members of this class, interface, or enum type.
+ *
+ * <p>These include public, protected, default (package-private) access,
+ * and private fields declared by the class, but excludes inherited fields.
+ * Synthetic fields may or may not be included. Fields from binary types that
+ * reference unresolvable types may not be included.</p>
+ *
+ * <p>Returns an empty list if the class, interface, or enum declares no fields,
+ * and for other kinds of type bindings that do not directly have members.</p>
+ *
+ * <p>The resulting bindings are in no particular order.</p>
+ *
+ * @return the list of bindings for the field members of this type,
+ * or the empty list if this type does not have field members
+ */
+ public IVariableBinding[] getDeclaredFields();
+
+ /**
+ * Returns a list of method bindings representing all the methods and
+ * constructors declared for this class, interface, enum, or annotation
+ * type.
+ * <p>These include public, protected, default (package-private) access,
+ * and private methods Synthetic methods and constructors may or may not be
+ * included. Returns an empty list if the class, interface, or enum,
+ * type declares no methods or constructors, if the annotation type declares
+ * no members, or if this type binding represents some other kind of type
+ * binding. Methods from binary types that reference unresolvable types may
+ * not be included.</p>
+ * <p>The resulting bindings are in no particular order.</p>
+ *
+ * @return the list of method bindings for the methods and constructors
+ * declared by this class, interface, enum type, or annotation type,
+ * or the empty list if this type does not declare any methods or constructors
+ */
+ public IMethodBinding[] getDeclaredMethods();
+
+//{ObjecgtTeams:
+ IMethodMappingBinding[] getResolvedMethodMappings();
+// SH}
+ /**
+ * Returns the declared modifiers for this class or interface binding
+ * as specified in the original source declaration of the class or
+ * interface. The result may not correspond to the modifiers in the compiled
+ * binary, since the compiler may change them (in particular, for inner
+ * class emulation). The <code>getModifiers</code> method should be used if
+ * the compiled modifiers are needed. Returns -1 if this type does not
+ * represent a class or interface.
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see #getModifiers()
+ * @see Modifier
+ */
+ public int getDeclaredModifiers();
+
+ /**
+ * Returns a list of type bindings representing all the types declared as
+ * members of this class, interface, or enum type.
+ * These include public, protected, default (package-private) access,
+ * and private classes, interfaces, enum types, and annotation types
+ * declared by the type, but excludes inherited types. Returns an empty
+ * list if the type declares no type members, or if this type
+ * binding represents an array type, a primitive type, a type variable,
+ * a wildcard type, a capture, or the null type.
+ * The resulting bindings are in no particular order.
+ *
+ * @return the list of type bindings for the member types of this type,
+ * or the empty list if this type does not have member types
+ */
+ public ITypeBinding[] getDeclaredTypes();
+
+ /**
+ * Returns the type binding representing the class, interface, or enum
+ * that declares this binding.
+ * <p>
+ * The declaring class of a member class, interface, enum, annotation
+ * type is the class, interface, or enum type of which it is a member.
+ * The declaring class of a local class or interface (including anonymous
+ * classes) is the innermost class or interface containing the expression
+ * or statement in which this type is declared.
+ * </p>
+ * <p>The declaring class of a type variable is the class in which the type
+ * variable is declared if it is declared on a type. It returns
+ * <code>null</code> otherwise.
+ * </p>
+ * <p>The declaring class of a capture binding is the innermost class or
+ * interface containing the expression or statement in which this capture is
+ * declared.
+ * </p>
+ * <p>Array types, primitive types, the null type, top-level types,
+ * wildcard types, recovered binding have no declaring class.
+ * </p>
+ *
+ * @return the binding of the type that declares this type, or
+ * <code>null</code> if none
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the method binding representing the method that declares this binding
+ * of a local type or type variable.
+ * <p>
+ * The declaring method of a local class or interface (including anonymous
+ * classes) is the innermost method containing the expression or statement in
+ * which this type is declared. Returns <code>null</code> if the type
+ * is declared in an initializer.
+ * </p>
+ * <p>
+ * The declaring method of a type variable is the method in which the type
+ * variable is declared if it is declared on a method. It
+ * returns <code>null</code> otherwise.
+ * </p>
+ * <p>Array types, primitive types, the null type, top-level types,
+ * wildcard types, capture bindings, and recovered binding have no
+ * declaring method.
+ * </p>
+ *
+ * @return the binding of the method that declares this type, or
+ * <code>null</code> if none
+ * @since 3.1
+ */
+ public IMethodBinding getDeclaringMethod();
+
+ /**
+ * Returns the dimensionality of this array type, or <code>0</code> if this
+ * is not an array type binding.
+ *
+ * @return the number of dimension of this array type binding, or
+ * <code>0</code> if this is not an array type
+ */
+ public int getDimensions();
+
+ /**
+ * Returns the binding representing the element type of this array type,
+ * or <code>null</code> if this is not an array type binding. The element
+ * type of an array is never itself an array type.
+ *
+ * @return the element type binding, or <code>null</code> if this is
+ * not an array type
+ */
+ public ITypeBinding getElementType();
+
+ /**
+ * Returns the erasure of this type binding.
+ * <ul>
+ * <li>For parameterized types ({@link #isParameterizedType()})
+ * - returns the binding for the corresponding generic type.</li>
+ * <li>For raw types ({@link #isRawType()})
+ * - returns the binding for the corresponding generic type.</li>
+ * <li>For wildcard types ({@link #isWildcardType()})
+ * - returns the binding for the upper bound if it has one and
+ * java.lang.Object in other cases.</li>
+ * <li>For type variables ({@link #isTypeVariable()})
+ * - returns the binding for the erasure of the leftmost bound
+ * if it has bounds and java.lang.Object if it does not.</li>
+ * <li>For captures ({@link #isCapture()})
+ * - returns the binding for the erasure of the leftmost bound
+ * if it has bounds and java.lang.Object if it does not.</li>
+ * <li>For array types ({@link #isArray()}) - returns an array type of
+ * the same dimension ({@link #getDimensions()}) as this type
+ * binding for which the element type is the erasure of the element type
+ * ({@link #getElementType()}) of this type binding.</li>
+ * <li>For all other type bindings - returns the identical binding.</li>
+ * </ul>
+ *
+ * @return the erasure type binding
+ * @since 3.1
+ */
+ public ITypeBinding getErasure();
+
+ /**
+ * Returns a list of type bindings representing the direct superinterfaces
+ * of the class, interface, or enum type represented by this type binding.
+ * <p>
+ * If this type binding represents a class or enum type, the return value
+ * is an array containing type bindings representing all interfaces
+ * directly implemented by this class. The number and order of the interface
+ * objects in the array corresponds to the number and order of the interface
+ * names in the <code>implements</code> clause of the original declaration
+ * of this type.
+ * </p>
+ * <p>
+ * If this type binding represents an interface, the array contains
+ * type bindings representing all interfaces directly extended by this
+ * interface. The number and order of the interface objects in the array
+ * corresponds to the number and order of the interface names in the
+ * <code>extends</code> clause of the original declaration of this interface.
+ * </p>
+ * <p>
+ * If the class or enum implements no interfaces, or the interface extends
+ * no interfaces, or if this type binding represents an array type, a
+ * primitive type, the null type, a type variable, an annotation type,
+ * a wildcard type, or a capture binding, this method returns an array of
+ * length 0.
+ * </p>
+ *
+ * @return the list of type bindings for the interfaces extended by this
+ * class or enum, or interfaces extended by this interface, or otherwise
+ * the empty list
+ */
+ public ITypeBinding[] getInterfaces();
+
+ /**
+ * Returns the compiled modifiers for this class, interface, enum,
+ * or annotation type binding.
+ * The result may not correspond to the modifiers as declared in the
+ * original source, since the compiler may change them (in particular,
+ * for inner class emulation). The <code>getDeclaredModifiers</code> method
+ * should be used if the original modifiers are needed.
+ * Returns 0 if this type does not represent a class, an interface, an enum, an annotation
+ * type or a recovered type.
+ *
+ * @return the compiled modifiers for this type binding or 0
+ * if this type does not represent a class, an interface, an enum, an annotation
+ * type or a recovered type.
+ * @see #getDeclaredModifiers()
+ */
+ public int getModifiers();
+
+ /**
+ * Returns the unqualified name of the type represented by this binding
+ * if it has one.
+ * <ul>
+ * <li>For top-level types, member types, and local types,
+ * the name is the simple name of the type.
+ * Example: <code>"String"</code> or <code>"Collection"</code>.
+ * Note that the type parameters of a generic type are not included.</li>
+ * <li>For primitive types, the name is the keyword for the primitive type.
+ * Example: <code>"int"</code>.</li>
+ * <li>For the null type, the name is the string "null".</li>
+ * <li>For anonymous classes, which do not have a name,
+ * this method returns an empty string.</li>
+ * <li>For array types, the name is the unqualified name of the component
+ * type (as computed by this method) followed by "[]".
+ * Example: <code>"String[]"</code>. Note that the component type is never an
+ * an anonymous class.</li>
+ * <li>For type variables, the name is just the simple name of the
+ * type variable (type bounds are not included).
+ * Example: <code>"X"</code>.</li>
+ * <li>For type bindings that correspond to particular instances of a generic
+ * type arising from a parameterized type reference,
+ * the name is the unqualified name of the erasure type (as computed by this method)
+ * followed by the names (again, as computed by this method) of the type arguments
+ * surrounded by "&lt;&gt;" and separated by ",".
+ * Example: <code>"Collection&lt;String&gt;"</code>.
+ * </li>
+ * <li>For type bindings that correspond to particular instances of a generic
+ * type arising from a raw type reference, the name is the unqualified name of
+ * the erasure type (as computed by this method).
+ * Example: <code>"Collection"</code>.</li>
+ * <li>For wildcard types, the name is "?" optionally followed by
+ * a single space followed by the keyword "extends" or "super"
+ * followed a single space followed by the name of the bound (as computed by
+ * this method) when present.
+ * Example: <code>"? extends InputStream"</code>.
+ * </li>
+ * <li>Capture types do not have a name. For these types,
+ * and array types thereof, this method returns an empty string.</li>
+ * </ul>
+ *
+ * @return the unqualified name of the type represented by this binding,
+ * or the empty string if it has none
+ * @see #getQualifiedName()
+ */
+ public String getName();
+
+ /**
+ * Returns the binding for the package in which this type is declared.
+ *
+ * <p>The package of a recovered type reference binding is either
+ * the package of the enclosing type, or, if the type name is the name of a
+ * {@linkplain AST#resolveWellKnownType(String) well-known type},
+ * the package of the matching well-known type.</p>
+ *
+ * @return the binding for the package in which this class, interface,
+ * enum, or annotation type is declared, or <code>null</code> if this type
+ * binding represents a primitive type, an array type, the null type,
+ * a type variable, a wildcard type, a capture binding.
+ */
+ public IPackageBinding getPackage();
+
+ /**
+ * Returns the fully qualified name of the type represented by this
+ * binding if it has one.
+ * <ul>
+ * <li>For top-level types, the fully qualified name is the simple name of
+ * the type preceded by the package name (or unqualified if in a default package)
+ * and a ".".
+ * Example: <code>"java.lang.String"</code> or <code>"java.util.Collection"</code>.
+ * Note that the type parameters of a generic type are not included.</li>
+ * <li>For members of top-level types, the fully qualified name is the
+ * simple name of the type preceded by the fully qualified name of the
+ * enclosing type (as computed by this method) and a ".".
+ * Example: <code>"java.io.ObjectInputStream.GetField"</code>.
+ * If the binding is for a member type that corresponds to a particular instance
+ * of a generic type arising from a parameterized type reference, the simple
+ * name of the type is followed by the fully qualified names of the type arguments
+ * (as computed by this method) surrounded by "&lt;&gt;" and separated by ",".
+ * Example: <code>"pkg.Outer.Inner&lt;java.lang.String&gt;"</code>.
+ * </li>
+ * <li>For primitive types, the fully qualified name is the keyword for
+ * the primitive type.
+ * Example: <code>"int"</code>.</li>
+ * <li>For the null type, the fully qualified name is the string
+ * "null".</li>
+ * <li>Local types (including anonymous classes) and members of local
+ * types do not have a fully qualified name. For these types, and array
+ * types thereof, this method returns an empty string.</li>
+ * <li>For array types whose component type has a fully qualified name,
+ * the fully qualified name is the fully qualified name of the component
+ * type (as computed by this method) followed by "[]".
+ * Example: <code>"java.lang.String[]"</code>.</li>
+ * <li>For type variables, the fully qualified name is just the name of the
+ * type variable (type bounds are not included).
+ * Example: <code>"X"</code>.</li>
+ * <li>For type bindings that correspond to particular instances of a generic
+ * type arising from a parameterized type reference,
+ * the fully qualified name is the fully qualified name of the erasure
+ * type followed by the fully qualified names of the type arguments surrounded by "&lt;&gt;" and separated by ",".
+ * Example: <code>"java.util.Collection&lt;java.lang.String&gt;"</code>.
+ * </li>
+ * <li>For type bindings that correspond to particular instances of a generic
+ * type arising from a raw type reference,
+ * the fully qualified name is the fully qualified name of the erasure type.
+ * Example: <code>"java.util.Collection"</code>. Note that the
+ * the type parameters are omitted.</li>
+ * <li>For wildcard types, the fully qualified name is "?" optionally followed by
+ * a single space followed by the keyword "extends" or "super"
+ * followed a single space followed by the fully qualified name of the bound
+ * (as computed by this method) when present.
+ * Example: <code>"? extends java.io.InputStream"</code>.
+ * </li>
+ * <li>Capture types do not have a fully qualified name. For these types,
+ * and array types thereof, this method returns an empty string.</li>
+ * </ul>
+ *
+ * @return the fully qualified name of the type represented by this
+ * binding, or the empty string if it has none
+ * @see #getName()
+ * @since 2.1
+ */
+ public String getQualifiedName();
+
+ /**
+ * Returns the type binding for the superclass of the type represented
+ * by this class binding.
+ * <p>
+ * If this type binding represents any class other than the class
+ * <code>java.lang.Object</code>, then the type binding for the direct
+ * superclass of this class is returned. If this type binding represents
+ * the class <code>java.lang.Object</code>, then <code>null</code> is
+ * returned.
+ * <p>
+ * Loops that ascend the class hierarchy need a suitable termination test.
+ * Rather than test the superclass for <code>null</code>, it is more
+ * transparent to check whether the class is <code>Object</code>, by
+ * comparing whether the class binding is identical to
+ * <code>ast.resolveWellKnownType("java.lang.Object")</code>.
+ * </p>
+ * <p>
+ * If this type binding represents an interface, an array type, a
+ * primitive type, the null type, a type variable, an enum type,
+ * an annotation type, a wildcard type, or a capture binding then
+ * <code>null</code> is returned.
+ * </p>
+ *
+ * @return the superclass of the class represented by this type binding,
+ * or <code>null</code> if none
+ * @see AST#resolveWellKnownType(String)
+ */
+ public ITypeBinding getSuperclass();
+
+ /**
+ * Returns the type arguments of this generic type instance, or the
+ * empty list for other type bindings.
+ * <p>
+ * Note that type arguments only occur on a type binding that represents
+ * an instance of a generic type corresponding to a parameterized type
+ * reference (e.g., <code>Collection&lt;String&gt;</code>).
+ * Do not confuse these with type parameters which only occur on the
+ * type binding corresponding directly to the declaration of the
+ * generic class or interface (e.g., <code>Collection&lt;T&gt;</code>).
+ * </p>
+ *
+ * @return the list of type bindings for the type arguments used to
+ * instantiate the corresponding generic type, or otherwise the empty list
+ * @see #getTypeDeclaration()
+ * @see #isGenericType()
+ * @see #isParameterizedType()
+ * @see #isRawType()
+ * @since 3.1
+ */
+ public ITypeBinding[] getTypeArguments();
+
+ /**
+ * Returns the declared type bounds of this type variable or capture. If the
+ * variable or the capture had no explicit bound, then it returns an empty list.
+ * <p>
+ * Note that per construction, it can only contain one class or array type,
+ * at most, and then it is located in first position.
+ * </p>
+ * <p>
+ * Also note that array type bound may only occur in the case of a capture
+ * binding, e.g. <code>capture-of ? extends Object[]</code>
+ * </p>
+ *
+ * @return the list of type bindings for this type variable or capture,
+ * or otherwise the empty list
+ * @see #isCapture()
+ * @see #isTypeVariable()
+ * @since 3.1
+ */
+ public ITypeBinding[] getTypeBounds();
+
+ /**
+ * Returns the binding for the type declaration corresponding to this type
+ * binding.
+ * <p>For parameterized types ({@link #isParameterizedType()})
+ * and most raw types ({@link #isRawType()}), this method returns the binding
+ * for the corresponding generic type.</p>
+ * <p>For raw member types ({@link #isRawType()}, {@link #isMember()})
+ * of a raw declaring class, the type declaration is a generic or a non-generic
+ * type.</p>
+ * <p>A different non-generic binding will be returned when one of the declaring
+ * types/methods was parameterized.</p>
+ * <p>For other type bindings, this returns the same binding.</p>
+ *
+ * @return the type binding
+ * @since 3.1
+ */
+ public ITypeBinding getTypeDeclaration();
+
+ /**
+ * Returns the type parameters of this class or interface type binding.
+ * <p>
+ * Note that type parameters only occur on the binding of the
+ * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+ * Type bindings corresponding to a raw or parameterized reference to a generic
+ * type do not carry type parameters (they instead have non-empty type arguments
+ * and non-trivial erasure).
+ * </p>
+ *
+ * @return the list of binding for the type variables for the type
+ * parameters of this type, or otherwise the empty list
+ * @see #isTypeVariable()
+ * @since 3.1
+ */
+ // TODO (jeem) - clarify whether binding for a generic type instance carries a copy of the generic type's type parameters as well as type arguments
+ public ITypeBinding[] getTypeParameters();
+
+ /**
+ * Returns the corresponding wildcard binding of this capture binding.
+ * Returns <code>null</code> if this type bindings does not represent
+ * a capture binding.
+ *
+ * @return the corresponding wildcard binding for a capture
+ * binding, <code>null</code> otherwise
+ * @since 3.1
+ */
+ public ITypeBinding getWildcard();
+
+ /**
+ * Returns whether this type binding represents an annotation type.
+ * <p>
+ * Note that an annotation type is always an interface.
+ * </p>
+ *
+ * @return <code>true</code> if this object represents an annotation type,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isAnnotation();
+
+ /**
+ * Returns whether this type binding represents an anonymous class.
+ * <p>
+ * An anonymous class is a subspecies of local class, and therefore mutually
+ * exclusive with member types. Note that anonymous classes have no name
+ * (<code>getName</code> returns the empty string).
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for an anonymous class,
+ * and <code>false</code> otherwise
+ */
+ public boolean isAnonymous();
+
+ /**
+ * Returns whether this type binding represents an array type.
+ *
+ * @return <code>true</code> if this type binding is for an array type,
+ * and <code>false</code> otherwise
+ * @see #getElementType()
+ * @see #getDimensions()
+ */
+ public boolean isArray();
+
+ /**
+ * Returns whether an expression of this type can be assigned to a variable
+ * of the given type, as specified in section 5.2 of <em>The Java Language
+ * Specification, Third Edition</em> (JLS3).
+ *
+ * <p>If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+ *
+ * @param variableType the type of a variable to check compatibility against
+ * @return <code>true</code> if an expression of this type can be assigned to a
+ * variable of the given type, and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isAssignmentCompatible(ITypeBinding variableType);
+
+ /**
+ * Returns whether this type binding represents a capture binding.
+ * <p>
+ * Capture bindings result from capture conversion as specified
+ * in section 5.1.10 of <em>The Java Language Specification,
+ * Third Edition</em> (JLS3).
+ * </p>
+ * <p>
+ * A capture binding may have upper bounds and a lower bound.
+ * Upper bounds may be accessed using {@link #getTypeBounds()},
+ * the lower bound must be accessed indirectly through the associated
+ * wildcard {@link #getWildcard()} when it is a lower bound wildcard.
+ * </p>
+ * <p>
+ * Note that capture bindings are distinct from type variables
+ * (even though they are often depicted as synthetic type
+ * variables); as such, {@link #isTypeVariable()} answers
+ * <code>false</code> for capture bindings, and
+ * {@link #isCapture()} answers <code>false</code> for type variables.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is a capture,
+ * and <code>false</code> otherwise
+ * @see #getTypeBounds()
+ * @see #getWildcard()
+ * @since 3.1
+ */
+ public boolean isCapture();
+
+ /**
+ * Returns whether this type is cast compatible with the given type,
+ * as specified in section 5.5 of <em>The Java Language
+ * Specification, Third Edition</em> (JLS3).
+ * <p>
+ * NOTE: The cast compatibility check performs backwards.
+ * When testing whether type B can be cast to type A, one would use:
+ * <code>A.isCastCompatible(B)</code>
+ * </p>
+ *
+ * <p>If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+ *
+ * @param type the type to check compatibility against
+ * @return <code>true</code> if this type is cast compatible with the
+ * given type, and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isCastCompatible(ITypeBinding type);
+
+ /**
+ * Returns whether this type binding represents a class type or a recovered binding.
+ *
+ * @return <code>true</code> if this object represents a class or a recovered binding,
+ * and <code>false</code> otherwise
+ */
+ public boolean isClass();
+
+ /**
+ * Returns whether this type binding represents an enum type.
+ *
+ * @return <code>true</code> if this object represents an enum type,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isEnum();
+
+ /**
+ * Returns whether this type binding originated in source code.
+ * Returns <code>false</code> for all primitive types, the null type,
+ * array types, and for all classes, interfaces, enums, annotation
+ * types, type variables, parameterized type references,
+ * raw type references, wildcard types, and capture bindings
+ * whose information came from a pre-compiled binary class file.
+ *
+ * @return <code>true</code> if the type is in source code,
+ * and <code>false</code> otherwise
+ */
+ public boolean isFromSource();
+
+ /**
+ * Returns whether this type binding represents a declaration of
+ * a generic class or interface.
+ * <p>
+ * Note that type parameters only occur on the binding of the
+ * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+ * Type bindings corresponding to a raw or parameterized reference to a generic
+ * type do not carry type parameters (they instead have non-empty type arguments
+ * and non-trivial erasure).
+ * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+ * </p>
+ * <p>
+ * Note that {@link #isGenericType()},
+ * {@link #isParameterizedType()},
+ * and {@link #isRawType()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding represents a
+ * declaration of a generic class or interface, and <code>false</code> otherwise
+ * @see #getTypeParameters()
+ * @since 3.1
+ */
+ public boolean isGenericType();
+
+ /**
+ * Returns whether this type binding represents an interface type.
+ * <p>
+ * Note that an interface can also be an annotation type.
+ * </p>
+ *
+ * @return <code>true</code> if this object represents an interface,
+ * and <code>false</code> otherwise
+ */
+ public boolean isInterface();
+
+//{ObjectTeams: added isTeam(), isRole(), getBaseClass(), isClassPartOf(), getOptimalName()
+ /**
+ * Returns whether this type binding represents a team type.
+ *
+ * @return <code>true</code> if this object represents a team,
+ * and <code>false</code> otherwise
+ */
+ public boolean isTeam();
+
+ /**
+ * Returns whether this type binding represents a role type.
+ *
+ * @return <code>true</code> if this object represents a role,
+ * and <code>false</code> otherwise
+ */
+ public boolean isRole();
+
+ /**
+ * Returns whether this binding is the classpart of other binding
+ * (which must then be the interface part ;-)
+ *
+ * @param other
+ * @return
+ */
+ public boolean isClassPartOf(ITypeBinding other);
+
+ /**
+ * Returns whether this binding is the synthetic interface part of a role
+ */
+ public boolean isSynthRoleIfc();
+
+ /**
+ * For a role class returns the corresponding interface part.
+ */
+ public ITypeBinding getIfcPart();
+
+ /**
+ * Returns the type binding for the baseclass of the type represented
+ * by this class binding.
+ * @return the baseclass of the class represented by this type binding,
+ * or <code>null</code> if none
+ */
+ public ITypeBinding getBaseClass();
+
+ /**
+ * Returns the name of this type as getQualifiedName() would do,
+ * but respect anchored types.
+ *
+ * @return
+ */
+ public String getOptimalName();
+//km}
+
+//{ObjectTeams: tsuper types for roles via role model:
+ /**
+ * Returns the super roles of this type.
+ * @return super roles or null, if not a role.
+ */
+ public ITypeBinding[] getSuperRoles();
+//mkr}
+ /**
+ * Returns whether this type binding represents a local class.
+ * <p>
+ * A local class is any nested class or enum type not declared as a member
+ * of another class or interface. A local class is a subspecies of nested
+ * type, and mutually exclusive with member types. Note that anonymous
+ * classes are a subspecies of local classes.
+ * </p>
+ * <p>
+ * Also note that interfaces and annotation types cannot be local.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a local class or
+ * enum type, and <code>false</code> otherwise
+ */
+ public boolean isLocal();
+
+ /**
+ * Returns whether this type binding represents a member class or
+ * interface.
+ * <p>
+ * A member type is any type declared as a member of
+ * another type. A member type is a subspecies of nested
+ * type, and mutually exclusive with local types.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a member class,
+ * interface, enum, or annotation type, and <code>false</code> otherwise
+ */
+ public boolean isMember();
+
+ /**
+ * Returns whether this type binding represents a nested class, interface,
+ * enum, or annotation type.
+ * <p>
+ * A nested type is any type whose declaration occurs within
+ * the body of another. The set of nested types is disjoint from the set of
+ * top-level types. Nested types further subdivide into member types, local
+ * types, and anonymous types.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a nested class,
+ * interface, enum, or annotation type, and <code>false</code> otherwise
+ */
+ public boolean isNested();
+
+ /**
+ * Returns whether this type binding represents the null type.
+ * <p>
+ * The null type is the type of a <code>NullLiteral</code> node.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for the null type,
+ * and <code>false</code> otherwise
+ */
+ public boolean isNullType();
+
+ /**
+ * Returns whether this type binding represents an instance of
+ * a generic type corresponding to a parameterized type reference.
+ * <p>
+ * For example, an AST type like
+ * <code>Collection&lt;String&gt;</code> typically resolves to a
+ * type binding whose type argument is the type binding for the
+ * class <code>java.lang.String</code> and whose erasure is the type
+ * binding for the generic type <code>java.util.Collection</code>.
+ * </p>
+ * <p>
+ * Note that {@link #isGenericType()},
+ * {@link #isParameterizedType()},
+ * and {@link #isRawType()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding represents a
+ * an instance of a generic type corresponding to a parameterized
+ * type reference, and <code>false</code> otherwise
+ * @see #getTypeArguments()
+ * @see #getTypeDeclaration()
+ * @since 3.1
+ */
+ public boolean isParameterizedType();
+
+ /**
+ * Returns whether this type binding represents a primitive type.
+ * <p>
+ * There are nine predefined type bindings to represent the eight primitive
+ * types and <code>void</code>. These have the same names as the primitive
+ * types that they represent, namely boolean, byte, char, short, int,
+ * long, float, and double, and void.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a primitive type,
+ * and <code>false</code> otherwise
+ */
+ public boolean isPrimitive();
+
+ /**
+ * Returns whether this type binding represents an instance of
+ * a generic type corresponding to a raw type reference.
+ * <p>
+ * For example, an AST type like
+ * <code>Collection</code> typically resolves to a
+ * type binding whose type argument is the type binding for
+ * the class <code>java.lang.Object</code> (the
+ * default bound for the single type parameter of
+ * <code>java.util.Collection</code>) and whose erasure is the
+ * type binding for the generic type
+ * <code>java.util.Collection</code>.
+ * </p>
+ * <p>
+ * Note that {@link #isGenericType()},
+ * {@link #isParameterizedType()},
+ * and {@link #isRawType()} are mutually exclusive.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding represents a
+ * an instance of a generic type corresponding to a raw
+ * type reference, and <code>false</code> otherwise
+ * @see #getTypeDeclaration()
+ * @see #getTypeArguments()
+ * @since 3.1
+ */
+ public boolean isRawType();
+
+ /**
+ * Returns whether this type is subtype compatible with the given type,
+ * as specified in section 4.10 of <em>The Java Language
+ * Specification, Third Edition</em> (JLS3).
+ *
+ * <p>If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+ *
+ * @param type the type to check compatibility against
+ * @return <code>true</code> if this type is subtype compatible with the
+ * given type, and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isSubTypeCompatible(ITypeBinding type);
+
+ /**
+ * Returns whether this type binding represents a top-level class,
+ * interface, enum, or annotation type.
+ * <p>
+ * A top-level type is any type whose declaration does not occur within the
+ * body of another type declaration. The set of top level types is disjoint
+ * from the set of nested types.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a top-level class,
+ * interface, enum, or annotation type, and <code>false</code> otherwise
+ */
+ public boolean isTopLevel();
+
+ /**
+ * Returns whether this type binding represents a type variable.
+ * Type variables bindings carry the type variable's bounds.
+ * <p>
+ * Note that type variables are distinct from capture bindings
+ * (even though capture bindings are often depicted as synthetic
+ * type variables); as such, {@link #isTypeVariable()} answers
+ * <code>false</code> for capture bindings, and
+ * {@link #isCapture()} answers <code>false</code> for type variables.
+ * </p>
+ *
+ * @return <code>true</code> if this type binding is for a type variable,
+ * and <code>false</code> otherwise
+ * @see #getName()
+ * @see #getTypeBounds()
+ * @since 3.1
+ */
+ public boolean isTypeVariable();
+
+ /**
+ * Returns whether this wildcard type is an upper bound
+ * ("extends") as opposed to a lower bound ("super").
+ * Note that this property is only relevant for wildcards
+ * that have a bound.
+ *
+ * @return <code>true</code> if this wildcard type has a bound that is
+ * an upper bound, and <code>false</code> in all other cases
+ * @see #isWildcardType()
+ * @see #getBound()
+ * @since 3.1
+ */
+ public boolean isUpperbound();
+
+ /**
+ * Returns whether this type binding represents a wildcard type. A wildcard
+ * type occus only as an argument to a parameterized type reference.
+ * <p>
+ * For example, a AST type like
+ * <code>Collection&lt;? extends Object&gt;</code> typically resolves to a
+ * parameterized type binding whose type argument is a wildcard type
+ * with upper type bound <code>java.util.Object</code>.
+ * </p>
+ *
+ * @return <code>true</code> if this object represents a wildcard type,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ * @see #getBound()
+ * @see #isUpperbound()
+ */
+ public boolean isWildcardType();
+
+//{ObjectTeams: new queries
+ /**
+ * Returns whether this type binding represents a dependent type.
+ * @param onlyRelevant only report dependence on relevant (non-tthis) anchors
+ */
+ boolean isDependentType(boolean onlyRelevant);
+
+ /**
+ * If this type binding represents a dependent type
+ * return the path of its type anchor.
+ * @return path or empty array.
+ */
+ public String[] getAnchorPath();
+// SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java
new file mode 100644
index 000000000..c86e397c4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IVariableBinding.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * A variable binding represents either a field of a class or interface, or
+ * a local variable declaration (including formal parameters, local variables,
+ * and exception variables).
+ *
+ * @see ITypeBinding#getDeclaredFields()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IVariableBinding extends IBinding {
+
+ /**
+ * Returns whether this binding is for a field.
+ * Note that this method returns <code>true</code> for constants,
+ * including enum constants. This method returns <code>false</code>
+ * for local variables.
+ *
+ * @return <code>true</code> if this is the binding for a field,
+ * and <code>false</code> otherwise
+ */
+ public boolean isField();
+
+ /**
+ * Returns whether this binding is for an enum constant.
+ * Note that this method returns <code>false</code> for local variables
+ * and for fields other than enum constants.
+ *
+ * @return <code>true</code> if this is the binding for an enum constant,
+ * and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public boolean isEnumConstant();
+
+ /**
+ * Returns whether this binding corresponds to a parameter.
+ *
+ * @return <code>true</code> if this is the binding for a parameter,
+ * and <code>false</code> otherwise
+ * @since 3.2
+ */
+ public boolean isParameter();
+
+ /**
+ * Returns the name of the field or local variable declared in this binding.
+ * The name is always a simple identifier.
+ *
+ * @return the name of this field or local variable
+ */
+ public String getName();
+
+ /**
+ * Returns the type binding representing the class or interface
+ * that declares this field.
+ * <p>
+ * The declaring class of a field is the class or interface of which it is
+ * a member. Local variables have no declaring class. The field length of an
+ * array type has no declaring class.
+ * </p>
+ *
+ * @return the binding of the class or interface that declares this field,
+ * or <code>null</code> if none
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the binding for the type of this field or local variable.
+ *
+ * @return the binding for the type of this field or local variable
+ */
+ public ITypeBinding getType();
+
+ /**
+ * Returns a small integer variable id for this variable binding.
+ * <p>
+ * <b>Local variables inside methods:</b> Local variables (and parameters)
+ * declared within a single method are assigned ascending ids in normal
+ * code reading order; var1.getVariableId()&lt;var2.getVariableId() means that var1 is
+ * declared before var2.
+ * </p>
+ * <p>
+ * <b>Local variables outside methods:</b> Local variables declared in a
+ * type's static initializers (or initializer expressions of static fields)
+ * are assigned ascending ids in normal code reading order. Local variables
+ * declared in a type's instance initializers (or initializer expressions
+ * of non-static fields) are assigned ascending ids in normal code reading
+ * order. These ids are useful when checking definite assignment for
+ * static initializers (JLS 16.7) and instance initializers (JLS 16.8),
+ * respectively.
+ * </p>
+ * <p>
+ * <b>Fields:</b> Fields declared as members of a type are assigned
+ * ascending ids in normal code reading order;
+ * field1.getVariableId()&lt;field2.getVariableId() means that field1 is declared before
+ * field2.
+ * </p>
+ *
+ * @return a small non-negative variable id
+ */
+ public int getVariableId();
+
+ /**
+ * Returns this binding's constant value if it has one.
+ * Some variables may have a value computed at compile-time. If the type of
+ * the value is a primitive type, the result is the boxed equivalent (i.e.,
+ * int returned as an <code>Integer</code>). If the type of the value is
+ * <code>String</code>, the result is the string itself. If the variable has
+ * no compile-time computed value, the result is <code>null</code>.
+ * (Note: compile-time constant expressions cannot denote <code>null</code>;
+ * JLS2 15.28.). The result is always <code>null</code> for enum constants.
+ *
+ * @return the constant value, or <code>null</code> if none
+ * @since 3.0
+ */
+ public Object getConstantValue();
+
+ /**
+ * Returns the method binding representing the method containing the scope
+ * in which this local variable is declared.
+ * <p>
+ * The declaring method of a method formal parameter is the method itself.
+ * For a local variable declared somewhere within the body of a method,
+ * the declaring method is the enclosing method. When local or anonymous
+ * classes are involved, the declaring method is the innermost such method.
+ * There is no declaring method for a field, or for a local variable
+ * declared in a static or instance initializer; this method returns
+ * <code>null</code> in those cases.
+ * </p>
+ *
+ * @return the binding of the method or constructor that declares this
+ * local variable, or <code>null</code> if none
+ * @since 3.1
+ */
+ public IMethodBinding getDeclaringMethod();
+
+ /**
+ * Returns the binding for the variable declaration corresponding to this
+ * variable binding. For a binding for a field declaration in an instance
+ * of a generic type, this method returns the binding for the corresponding
+ * field declaration in the generic type. For other variable bindings,
+ * including all ones for local variables and parameters, this method
+ * returns the same binding.
+ *
+ * @return the variable binding for the originating declaration
+ * @since 3.1
+ */
+ public IVariableBinding getVariableDeclaration();
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
new file mode 100644
index 000000000..e35db215e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * If statement AST node type.
+ * <pre>
+ * IfStatement:
+ * <b>if</b> <b>(</b> Expression <b>)</b> Statement [ <b>else</b> Statement]
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class IfStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thenStatement" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor THEN_STATEMENT_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "thenStatement", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "elseStatement" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor ELSE_STATEMENT_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "elseStatement", Statement.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(IfStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(THEN_STATEMENT_PROPERTY, properyList);
+ addProperty(ELSE_STATEMENT_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The then statement; lazily initialized; defaults to an unspecified, but
+ * legal, statement.
+ */
+ private Statement thenStatement = null;
+
+ /**
+ * The else statement; <code>null</code> for none; defaults to none.
+ */
+ private Statement optionalElseStatement = null;
+
+ /**
+ * Creates a new unparented if statement node owned by the given
+ * AST. By default, the expresssion is unspecified,
+ * but legal, the then statement is an empty block, and there is no else
+ * statement.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ IfStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == THEN_STATEMENT_PROPERTY) {
+ if (get) {
+ return getThenStatement();
+ } else {
+ setThenStatement((Statement) child);
+ return null;
+ }
+ }
+ if (property == ELSE_STATEMENT_PROPERTY) {
+ if (get) {
+ return getElseStatement();
+ } else {
+ setElseStatement((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return IF_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ IfStatement result = new IfStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setThenStatement(
+ (Statement) getThenStatement().clone(target));
+ result.setElseStatement(
+ (Statement) ASTNode.copySubtree(target, getElseStatement()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getThenStatement());
+ acceptChild(visitor, getElseStatement());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this if statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the condition of this if statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "then" part of this if statement.
+ *
+ * @return the "then" statement node
+ */
+ public Statement getThenStatement() {
+ if (this.thenStatement == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.thenStatement == null) {
+ preLazyInit();
+ this.thenStatement = new Block(this.ast);
+ postLazyInit(this.thenStatement, THEN_STATEMENT_PROPERTY);
+ }
+ }
+ }
+ return this.thenStatement;
+ }
+
+ /**
+ * Sets the "then" part of this if statement.
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the "then" part of an if statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the thenStatement of a <code>IfStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the "then" statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setThenStatement(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.thenStatement;
+ preReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+ this.thenStatement = statement;
+ postReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+ }
+
+ /**
+ * Returns the "else" part of this if statement, or <code>null</code> if
+ * this if statement has <b>no</b> "else" part.
+ * <p>
+ * Note that there is a subtle difference between having no else
+ * statement and having an empty statement ("{}") or null statement (";").
+ * </p>
+ *
+ * @return the "else" statement node, or <code>null</code> if none
+ */
+ public Statement getElseStatement() {
+ return this.optionalElseStatement;
+ }
+
+ /**
+ * Sets or clears the "else" part of this if statement.
+ * <p>
+ * Note that there is a subtle difference between having no else part
+ * (as in <code>"if(true){}"</code>) and having an empty block (as in
+ * "if(true){}else{}") or null statement (as in "if(true){}else;").
+ * </p>
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the "else" part of an if statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the elseStatement of a <code>IfStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the "else" statement node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setElseStatement(Statement statement) {
+ ASTNode oldChild = this.optionalElseStatement;
+ preReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+ this.optionalElseStatement = statement;
+ postReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.thenStatement == null ? 0 : getThenStatement().treeSize())
+ + (this.optionalElseStatement == null ? 0 : getElseStatement().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java
new file mode 100644
index 000000000..7ad6c7da7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ImportDeclaration.java
@@ -0,0 +1,446 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Import declaration AST node type.
+ *
+ * For JLS2:
+ * <pre>
+ * ImportDeclaration:
+ * <b>import</b> Name [ <b>.</b> <b>*</b> ] <b>;</b>
+ * </pre>
+ * For JLS3, static was added:
+ * <pre>
+ * ImportDeclaration:
+ * <b>import</b> [ <b>static</b> ] Name [ <b>.</b> <b>*</b> ] <b>;</b>
+ * </pre>
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ImportDeclaration extends ASTNode {
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(ImportDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "onDemand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor ON_DEMAND_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "onDemand", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "static" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final SimplePropertyDescriptor STATIC_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "static", boolean.class, MANDATORY); //$NON-NLS-1$
+
+//{ObjectTeams: new flag
+ /**
+ * The "base" structural property of this node type (added in JLS3 API).
+ * @since 3.2
+ */
+ public static final SimplePropertyDescriptor BASE_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "base", boolean.class, MANDATORY); //$NON-NLS-1$
+// SH}
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ImportDeclaration.class, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ON_DEMAND_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(4);
+ createPropertyList(ImportDeclaration.class, properyList);
+ addProperty(STATIC_PROPERTY, properyList);
+//{ObjectTeams: base imports:
+ addProperty(BASE_PROPERTY, properyList);
+// SH}
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ON_DEMAND_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The import name; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private Name importName = null;
+
+ /**
+ * On demand versus single type import; defaults to single type import.
+ */
+ private boolean onDemand = false;
+
+ /**
+ * Static versus regular; defaults to regular import.
+ * Added in JLS3; not used in JLS2.
+ * @since 3.1
+ */
+ private boolean isStatic = false;
+
+//{ObjectTeams:
+ /**
+ * Base versus regular; defaults to regular import.
+ * Added in JLS3; not used in JLS2.
+ * @since 3.2
+ */
+ private boolean isBase = false;
+// SH}
+ /**
+ * Creates a new AST node for an import declaration owned by the
+ * given AST. The import declaration initially is a regular (non-static)
+ * single type import for an unspecified, but legal, Java type name.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ImportDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == ON_DEMAND_PROPERTY) {
+ if (get) {
+ return isOnDemand();
+ } else {
+ setOnDemand(value);
+ return false;
+ }
+ }
+ if (property == STATIC_PROPERTY) {
+ if (get) {
+ return isStatic();
+ } else {
+ setStatic(value);
+ return false;
+ }
+ }
+//{ObjectTeams:
+ if (property == BASE_PROPERTY) {
+ if (get) {
+ return isBase();
+ } else {
+ setBase(value);
+ return false;
+ }
+ }
+// SH}
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return IMPORT_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ImportDeclaration result = new ImportDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setOnDemand(isOnDemand());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setStatic(isStatic());
+ }
+//{ObjectTeams:
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setBase(isBase());
+ }
+// SH}
+ result.setName((Name) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name imported by this declaration.
+ * <p>
+ * For a regular on-demand import, this is the name of a package.
+ * For a static on-demand import, this is the qualified name of
+ * a type. For a regular single-type import, this is the qualified name
+ * of a type. For a static single-type import, this is the qualified name
+ * of a static member of a type.
+ * </p>
+ *
+ * @return the imported name node
+ */
+ public Name getName() {
+ if (this.importName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.importName == null) {
+ preLazyInit();
+ this.importName =this.ast.newQualifiedName(
+ new SimpleName(this.ast), new SimpleName(this.ast));
+ postLazyInit(this.importName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.importName;
+ }
+
+ /**
+ * Sets the name of this import declaration to the given name.
+ * <p>
+ * For a regular on-demand import, this is the name of a package.
+ * For a static on-demand import, this is the qualified name of
+ * a type. For a regular single-type import, this is the qualified name
+ * of a type. For a static single-type import, this is the qualified name
+ * of a static member of a type.
+ * </p>
+ *
+ * @param name the new import name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(Name name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.importName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.importName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns whether this import declaration is an on-demand or a
+ * single-type import.
+ *
+ * @return <code>true</code> if this is an on-demand import,
+ * and <code>false</code> if this is a single type import
+ */
+ public boolean isOnDemand() {
+ return this.onDemand;
+ }
+
+ /**
+ * Sets whether this import declaration is an on-demand or a
+ * single-type import.
+ *
+ * @param onDemand <code>true</code> if this is an on-demand import,
+ * and <code>false</code> if this is a single type import
+ */
+ public void setOnDemand(boolean onDemand) {
+ preValueChange(ON_DEMAND_PROPERTY);
+ this.onDemand = onDemand;
+ postValueChange(ON_DEMAND_PROPERTY);
+ }
+
+ /**
+ * Returns whether this import declaration is a static import (added in JLS3 API).
+ *
+ * @return <code>true</code> if this is a static import,
+ * and <code>false</code> if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public boolean isStatic() {
+ unsupportedIn2();
+ return this.isStatic;
+ }
+
+ /**
+ * Sets whether this import declaration is a static import (added in JLS3 API).
+ *
+ * @param isStatic <code>true</code> if this is a static import,
+ * and <code>false</code> if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public void setStatic(boolean isStatic) {
+ unsupportedIn2();
+ preValueChange(STATIC_PROPERTY);
+ this.isStatic = isStatic;
+ postValueChange(STATIC_PROPERTY);
+ }
+
+//{ObjectTeams: new flag:
+ /**
+ * Returns whether this import declaration is a base import (added in JLS3 API).
+ *
+ * @return <code>true</code> if this is a base import,
+ * and <code>false</code> if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.2
+ */
+ public boolean isBase() {
+ unsupportedIn2();
+ return isBase;
+ }
+
+ /**
+ * Sets whether this import declaration is a base import (added in JLS3 API).
+ *
+ * @param isBase <code>true</code> if this is a base import,
+ * and <code>false</code> if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public void setBase(boolean isBase) {
+ unsupportedIn2();
+ preValueChange(BASE_PROPERTY);
+ this.isBase = isBase;
+ postValueChange(BASE_PROPERTY);
+ }
+// SH}
+
+ /**
+ * Resolves and returns the binding for the package, type, field, or
+ * method named in this import declaration.
+ * <p>
+ * The name specified in a non-static single-type import can resolve
+ * to a type (only). The name specified in a non-static on-demand
+ * import can itself resolve to either a package or a type.
+ * For static imports (introduced in JLS3), the name specified in a
+ * static on-demand import can itself resolve to a type (only).
+ * The name specified in a static single import can resolve to a
+ * type, field, or method; in cases where the name could be resolved
+ * to more than one element with that name (for example, two
+ * methods both named "max", or a method and a field), this method
+ * returns one of the plausible bindings.
+ * </p>
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return a package, type, field, or method binding, or <code>null</code>
+ * if the binding cannot be resolved
+ */
+ public IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveImport(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.importName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java
new file mode 100644
index 000000000..314aef52f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InfixExpression.java
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Infix expression AST node type.
+ * <pre>
+ * InfixExpression:
+ * Expression InfixOperator Expression { InfixOperator Expression }
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class InfixExpression extends Expression {
+
+ /**
+ * Infix operators (typesafe enumeration).
+ * <pre>
+ * InfixOperator:<code>
+ * <b>*</b> TIMES
+ * <b>/</b> DIVIDE
+ * <b>%</b> REMAINDER
+ * <b>+</b> PLUS
+ * <b>-</b> MINUS
+ * <b>&lt;&lt;</b> LEFT_SHIFT
+ * <b>&gt;&gt;</b> RIGHT_SHIFT_SIGNED
+ * <b>&gt;&gt;&gt;</b> RIGHT_SHIFT_UNSIGNED
+ * <b>&lt;</b> LESS
+ * <b>&gt;</b> GREATER
+ * <b>&lt;=</b> LESS_EQUALS
+ * <b>&gt;=</b> GREATER_EQUALS
+ * <b>==</b> EQUALS
+ * <b>!=</b> NOT_EQUALS
+ * <b>^</b> XOR
+ * <b>&amp;</b> AND
+ * <b>|</b> OR
+ * <b>&amp;&amp;</b> CONDITIONAL_AND
+ * <b>||</b> CONDITIONAL_OR</code>
+ * </pre>
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new infix operator with the given token.
+ * <p>
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return this.token;
+ }
+
+ /** Multiplication "*" operator. */
+ public static final Operator TIMES = new Operator("*");//$NON-NLS-1$
+ /** Division "/" operator. */
+ public static final Operator DIVIDE = new Operator("/");//$NON-NLS-1$
+ /** Remainder "%" operator. */
+ public static final Operator REMAINDER = new Operator("%");//$NON-NLS-1$
+ /** Addition (or string concatenation) "+" operator. */
+ public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+ /** Subtraction "-" operator. */
+ public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+ /** Left shift "&lt;&lt;" operator. */
+ public static final Operator LEFT_SHIFT = new Operator("<<");//$NON-NLS-1$
+ /** Signed right shift "&gt;&gt;" operator. */
+ public static final Operator RIGHT_SHIFT_SIGNED = new Operator(">>");//$NON-NLS-1$
+ /** Unsigned right shift "&gt;&gt;&gt;" operator. */
+ public static final Operator RIGHT_SHIFT_UNSIGNED =
+ new Operator(">>>");//$NON-NLS-1$
+ /** Less than "&lt;" operator. */
+ public static final Operator LESS = new Operator("<");//$NON-NLS-1$
+ /** Greater than "&gt;" operator. */
+ public static final Operator GREATER = new Operator(">");//$NON-NLS-1$
+ /** Less than or equals "&lt;=" operator. */
+ public static final Operator LESS_EQUALS = new Operator("<=");//$NON-NLS-1$
+ /** Greater than or equals "&gt=;" operator. */
+ public static final Operator GREATER_EQUALS = new Operator(">=");//$NON-NLS-1$
+ /** Equals "==" operator. */
+ public static final Operator EQUALS = new Operator("==");//$NON-NLS-1$
+ /** Not equals "!=" operator. */
+ public static final Operator NOT_EQUALS = new Operator("!=");//$NON-NLS-1$
+ /** Exclusive OR "^" operator. */
+ public static final Operator XOR = new Operator("^");//$NON-NLS-1$
+ /** Inclusive OR "|" operator. */
+ public static final Operator OR = new Operator("|");//$NON-NLS-1$
+ /** AND "&amp;" operator. */
+ public static final Operator AND = new Operator("&");//$NON-NLS-1$
+ /** Conditional OR "||" operator. */
+ public static final Operator CONDITIONAL_OR = new Operator("||");//$NON-NLS-1$
+ /** Conditional AND "&amp;&amp;" operator. */
+ public static final Operator CONDITIONAL_AND = new Operator("&&");//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ TIMES,
+ DIVIDE,
+ REMAINDER,
+ PLUS,
+ MINUS,
+ LEFT_SHIFT,
+ RIGHT_SHIFT_SIGNED,
+ RIGHT_SHIFT_UNSIGNED,
+ LESS,
+ GREATER,
+ LESS_EQUALS,
+ GREATER_EQUALS,
+ EQUALS,
+ NOT_EQUALS,
+ XOR,
+ OR,
+ AND,
+ CONDITIONAL_OR,
+ CONDITIONAL_AND,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the infix operator corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toOperator</code> is the converse of <code>toString</code>:
+ * that is, <code>Operator.toOperator(op.toString()) == op</code> for
+ * all operators <code>op</code>.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ * @return the infix operator, or <code>null</code> if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+
+ }
+
+ /**
+ * The "leftOperand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InfixExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "operator" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(InfixExpression.class, "operator", InfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "rightOperand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InfixExpression.class, "rightOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extendedOperands" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor EXTENDED_OPERANDS_PROPERTY =
+ new ChildListPropertyDescriptor(InfixExpression.class, "extendedOperands", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(InfixExpression.class, properyList);
+ addProperty(LEFT_OPERAND_PROPERTY, properyList);
+ addProperty(OPERATOR_PROPERTY, properyList);
+ addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+ addProperty(EXTENDED_OPERANDS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The infix operator; defaults to InfixExpression.Operator.PLUS.
+ */
+ private InfixExpression.Operator operator = InfixExpression.Operator.PLUS;
+
+ /**
+ * The left operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftOperand = null;
+
+ /**
+ * The right operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression rightOperand = null;
+
+ /**
+ * The list of extended operand expressions (element type:
+ * <code>Expression</code>). Lazily initialized; defaults to an empty list.
+ */
+ private ASTNode.NodeList extendedOperands = null;
+
+ /**
+ * Creates a new AST node for an infix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator,
+ * left and right operands, and an empty list of additional operands.
+ *
+ * @param ast the AST that is to own this node
+ */
+ InfixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_OPERAND_PROPERTY) {
+ if (get) {
+ return getLeftOperand();
+ } else {
+ setLeftOperand((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_OPERAND_PROPERTY) {
+ if (get) {
+ return getRightOperand();
+ } else {
+ setRightOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == EXTENDED_OPERANDS_PROPERTY) {
+ return extendedOperands();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ InfixExpression result = new InfixExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setOperator(getOperator());
+ result.setLeftOperand((Expression) getLeftOperand().clone(target));
+ result.setRightOperand((Expression) getRightOperand().clone(target));
+ if (this.extendedOperands != null) {
+ // be careful not to trigger lazy creation of list
+ result.extendedOperands().addAll(
+ ASTNode.copySubtrees(target, extendedOperands()));
+ }
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftOperand());
+ acceptChild(visitor, getRightOperand());
+ if (this.extendedOperands != null) {
+ // be careful not to trigger lazy creation of list
+ acceptChildren(visitor, this.extendedOperands);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this infix expression.
+ *
+ * @return the infix operator
+ */
+ public InfixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this infix expression.
+ *
+ * @param operator the infix operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(InfixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the left operand of this infix expression.
+ *
+ * @return the left operand node
+ */
+ public Expression getLeftOperand() {
+ if (this.leftOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftOperand == null) {
+ preLazyInit();
+ this.leftOperand= new SimpleName(this.ast);
+ postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.leftOperand;
+ }
+
+ /**
+ * Sets the left operand of this infix expression.
+ *
+ * @param expression the left operand node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setLeftOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.leftOperand;
+ preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ this.leftOperand = expression;
+ postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns the right operand of this infix expression.
+ *
+ * @return the right operand node
+ */
+ public Expression getRightOperand() {
+ if (this.rightOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightOperand == null) {
+ preLazyInit();
+ this.rightOperand= new SimpleName(this.ast);
+ postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.rightOperand;
+ }
+
+ /**
+ * Sets the right operand of this infix expression.
+ *
+ * @param expression the right operand node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setRightOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.rightOperand;
+ preReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+ this.rightOperand = expression;
+ postReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns where there are any extended operands.
+ *
+ * @return <code>true</code> if there are one or more extended operands,
+ * and <code>false</code> if there are no extended operands
+ */
+ public boolean hasExtendedOperands() {
+ return
+ (this.extendedOperands != null) && this.extendedOperands.size() > 0;
+ }
+
+ /**
+ * Returns the live list of extended operands.
+ * <p>
+ * The extended operands is the preferred way of representing deeply nested
+ * expressions of the form <code>L op R op R2 op R3...</code> where
+ * the same operator appears between all the operands (the most
+ * common case being lengthy string concatenation expressions). Using
+ * the extended operands keeps the trees from getting too deep; this
+ * decreases the risk is running out of thread stack space at runtime
+ * when traversing such trees.
+ * ((a + b) + c) + d would be translated to:
+ * leftOperand: a
+ * rightOperand: b
+ * extendedOperands: {c, d}
+ * operator: +
+ * </p>
+ *
+ * @return the live list of extended operands
+ * (element type: <code>Expression</code>)
+ */
+ public List extendedOperands() {
+ if (this.extendedOperands == null) {
+ // lazily initialize
+ this.extendedOperands = new ASTNode.NodeList(EXTENDED_OPERANDS_PROPERTY);
+ }
+ return this.extendedOperands;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+ + (this.rightOperand == null ? 0 : getRightOperand().treeSize())
+ + (this.extendedOperands == null ? 0 : this.extendedOperands.listSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
new file mode 100644
index 000000000..b0d5382ed
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Static or instance initializer AST node type.
+ * <pre>
+ * Initializer:
+ * [ <b>static</b> ] Block
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Initializer extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(Initializer.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(Initializer.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(Initializer.class);
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(Initializer.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(Initializer.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(4);
+ createPropertyList(Initializer.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The initializer body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * Creates a new AST node for an initializer declaration owned by the given
+ * AST. By default, the initializer has no modifiers and an empty block.
+ * The javadoc comment is not used for initializers.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Initializer(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INITIALIZER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Initializer result = new Initializer(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.setBody((Block) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the body of this initializer declaration.
+ *
+ * @return the initializer body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body= new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this initializer declaration.
+ *
+ * @param body the block node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java
new file mode 100644
index 000000000..9c8396060
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InstanceofExpression.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Instanceof expression AST node type.
+ * <pre>
+ * InstanceofExpression:
+ * Expression <b>instanceof</b> Type
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class InstanceofExpression extends Expression {
+
+ /**
+ * The "leftOperand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InstanceofExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "rightOperand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InstanceofExpression.class, "rightOperand", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(InstanceofExpression.class, properyList);
+ addProperty(LEFT_OPERAND_PROPERTY, properyList);
+ addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The left operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftOperand = null;
+
+ /**
+ * The right operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple type.
+ */
+ private Type rightOperand = null;
+
+ /**
+ * Creates a new AST node for an instanceof expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator,
+ * left and right operands.
+ *
+ * @param ast the AST that is to own this node
+ */
+ InstanceofExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_OPERAND_PROPERTY) {
+ if (get) {
+ return getLeftOperand();
+ } else {
+ setLeftOperand((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_OPERAND_PROPERTY) {
+ if (get) {
+ return getRightOperand();
+ } else {
+ setRightOperand((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INSTANCEOF_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ InstanceofExpression result = new InstanceofExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setLeftOperand((Expression) getLeftOperand().clone(target));
+ result.setRightOperand((Type) getRightOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftOperand());
+ acceptChild(visitor, getRightOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the left operand of this instanceof expression.
+ *
+ * @return the left operand node
+ */
+ public Expression getLeftOperand() {
+ if (this.leftOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftOperand == null) {
+ preLazyInit();
+ this.leftOperand= new SimpleName(this.ast);
+ postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.leftOperand;
+ }
+
+ /**
+ * Sets the left operand of this instanceof expression.
+ *
+ * @param expression the left operand node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setLeftOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.leftOperand;
+ preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ this.leftOperand = expression;
+ postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns the right operand of this instanceof expression.
+ *
+ * @return the right operand node
+ */
+ public Type getRightOperand() {
+ if (this.rightOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightOperand == null) {
+ preLazyInit();
+ this.rightOperand= new SimpleType(this.ast);
+ postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.rightOperand;
+ }
+
+ /**
+ * Sets the right operand of this instanceof expression.
+ *
+ * @param referenceType the right operand node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setRightOperand(Type referenceType) {
+ if (referenceType == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.rightOperand;
+ preReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+ this.rightOperand = referenceType;
+ postReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+ + (this.rightOperand == null ? 0 : getRightOperand().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java
new file mode 100644
index 000000000..09cf2ff78
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.SimplePropertyDescriptor;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
+import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;
+
+/**
+ * Internal class: not intended to be used by client.
+ * When AST modifications recording is enabled, all changes are recorded by this class.
+ */
+class InternalASTRewrite extends NodeEventHandler {
+
+ /** root node for the rewrite: Only nodes under this root are accepted */
+ private CompilationUnit root;
+
+ protected final RewriteEventStore eventStore;
+ protected final NodeInfoStore nodeStore;
+ protected final Hashtable clonedNodes;
+
+ int cloneDepth = 0;
+
+ /**
+ * Constructor
+ * @param root root node of the recorded ast.
+ */
+ public InternalASTRewrite(CompilationUnit root) {
+ this.root = root;
+ this.eventStore = new RewriteEventStore();
+ this.nodeStore = new NodeInfoStore(root.getAST());
+ this.clonedNodes = new Hashtable();
+ }
+
+ /**
+ * Performs the rewrite: The rewrite events are translated to the corresponding in text changes.
+ * The given options can be null in which case the global options {@link JavaCore#getOptions() JavaCore.getOptions()}
+ * will be used.
+ *
+ * @param document Document which describes the code of the AST that is passed in in the
+ * constructor. This document is accessed read-only.
+ * @param options the given options
+ * @throws IllegalArgumentException if the rewrite fails
+ * @return Returns the edit describing the text changes.
+ */
+ public TextEdit rewriteAST(IDocument document, Map options) {
+ TextEdit result = new MultiTextEdit();
+
+ final CompilationUnit rootNode = getRootNode();
+ if (rootNode != null) {
+ TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
+ /**
+ * This implementation of
+ * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
+ * is specialized to work in the case of internal AST rewriting, where the
+ * original AST has been modified from its original form. This means that
+ * one cannot trust that the root of the given node is the compilation unit.
+ */
+ public SourceRange computeSourceRange(ASTNode node) {
+ int extendedStartPosition = rootNode.getExtendedStartPosition(node);
+ int extendedLength = rootNode.getExtendedLength(node);
+ return new SourceRange(extendedStartPosition, extendedLength);
+ }
+ };
+ char[] content= document.get().toCharArray();
+ LineInformation lineInfo= LineInformation.create(document);
+ String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+ List comments= rootNode.getCommentList();
+
+ Map currentOptions = options == null ? JavaCore.getOptions() : options;
+ ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, currentOptions, xsrComputer, (RecoveryScannerData)rootNode.getStatementsRecoveryData());
+ rootNode.accept(visitor);
+ }
+ return result;
+ }
+
+ private void markAsMoveOrCopyTarget(ASTNode node, ASTNode newChild) {
+ ASTNode source = (ASTNode)this.clonedNodes.get(newChild);
+ if(source != null) {
+ if(this.cloneDepth == 0) {
+ PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(source, RewriteEventStore.ORIGINAL);
+ CopySourceInfo sourceInfo =
+ this.eventStore.markAsCopySource(
+ propertyLocation.getParent(),
+ propertyLocation.getProperty(),
+ source,
+ false);
+ this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+ }
+ } else if((newChild.getFlags() & ASTNode.ORIGINAL) != 0) {
+ PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChild, RewriteEventStore.ORIGINAL);
+ CopySourceInfo sourceInfo =
+ this.eventStore.markAsCopySource(
+ propertyLocation.getParent(),
+ propertyLocation.getProperty(),
+ newChild,
+ true);
+ this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+ }
+ }
+
+ private CompilationUnit getRootNode() {
+ return this.root;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("Events:\n"); //$NON-NLS-1$
+ buf.append(this.eventStore.toString());
+ return buf.toString();
+ }
+
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // force event creation
+ getNodeEvent(node, property);
+ }
+
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(node.getStructuralProperty(property));
+ }
+
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(child);
+ if(child != null) {
+ markAsMoveOrCopyTarget(node, child);
+ }
+ } else if(property.isChildListProperty()) {
+ // force event creation
+ getListEvent(node, property);
+ }
+ }
+
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildListProperty()) {
+
+ ListRewriteEvent event = getListEvent(node, property);
+ List list = (List)node.getStructuralProperty(property);
+ int i = list.indexOf(child);
+ int s = list.size();
+ int index;
+ if(i + 1 < s) {
+ ASTNode nextNode = (ASTNode)list.get(i + 1);
+ index = event.getIndex(nextNode, ListRewriteEvent.NEW);
+ } else {
+ index = -1;
+ }
+ event.insert(child, index);
+ if(child != null) {
+ markAsMoveOrCopyTarget(node, child);
+ }
+ }
+ }
+
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(null);
+ } else if(property.isChildListProperty()) {
+ ListRewriteEvent event = getListEvent(node, property);
+ int i = event.getIndex(child, ListRewriteEvent.NEW);
+ NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+ if(nodeEvent.getOriginalValue() == null) {
+ event.revertChange(nodeEvent);
+ } else {
+ nodeEvent.setNewValue(null);
+ }
+ }
+ }
+
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(newChild);
+ if(newChild != null) {
+ markAsMoveOrCopyTarget(node, newChild);
+ }
+ } else if(property.isChildListProperty()) {
+ ListRewriteEvent event = getListEvent(node, property);
+ int i = event.getIndex(child, ListRewriteEvent.NEW);
+ NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+ nodeEvent.setNewValue(newChild);
+ if(newChild != null) {
+ markAsMoveOrCopyTarget(node, newChild);
+ }
+ }
+ }
+
+
+ void preCloneNodeEvent(ASTNode node) {
+ this.cloneDepth++;
+ }
+
+
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ if(node.ast == this.root.ast && clone.ast == this.root.ast) {
+ if((node.getFlags() & ASTNode.ORIGINAL) != 0) {
+ this.clonedNodes.put(clone, node);
+ } else {
+ // node can be a cloned node
+ Object original = this.clonedNodes.get(node);
+ if(original != null) {
+ this.clonedNodes.put(clone, original);
+ }
+ }
+ }
+ this.cloneDepth--;
+ }
+
+ private NodeRewriteEvent getNodeEvent(ASTNode node, StructuralPropertyDescriptor property) {
+ return this.eventStore.getNodeEvent(node, property, true);
+ }
+
+ private ListRewriteEvent getListEvent(ASTNode node, StructuralPropertyDescriptor property) {
+ return this.eventStore.getListEvent(node, property, true);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java
new file mode 100644
index 000000000..952039b0b
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Javadoc.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a Javadoc-style doc comment.
+ * <pre>
+ * Javadoc:
+ * <b>/** </b> { TagElement } <b>*</b><b>/</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Javadoc extends Comment {
+
+ /**
+ * The "comment" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ * @deprecated Replaced by {@link #TAGS_PROPERTY} in the JLS3 API.
+ */
+ public static final SimplePropertyDescriptor COMMENT_PROPERTY =
+ new SimplePropertyDescriptor(Javadoc.class, "comment", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "tags" structural property of this node type.
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TAGS_PROPERTY =
+ new ChildListPropertyDescriptor(Javadoc.class, "tags", TagElement.class, CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(Javadoc.class, properyList);
+ addProperty(COMMENT_PROPERTY, properyList);
+ addProperty(TAGS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(2);
+ createPropertyList(Javadoc.class, properyList);
+ addProperty(TAGS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * Canonical minimal doc comment.
+ * @since 3.0
+ */
+ private static final String MINIMAL_DOC_COMMENT = "/** */";//$NON-NLS-1$
+
+ /**
+ * The doc comment string, including opening and closing comment
+ * delimiters; defaults to a minimal Javadoc comment.
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * For backwards compatibility, it is still funcational as before.
+ */
+ private String comment = MINIMAL_DOC_COMMENT;
+
+ /**
+ * The list of tag elements (element type: <code>TagElement</code>).
+ * Defaults to an empty list.
+ * @since 3.0
+ */
+ private ASTNode.NodeList tags =
+ new ASTNode.NodeList(TAGS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a doc comment owned by the given AST.
+ * The new node has an empty list of tag elements (and, for backwards
+ * compatability, an unspecified, but legal, doc comment string).
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Javadoc(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == COMMENT_PROPERTY) {
+ if (get) {
+ return getComment();
+ } else {
+ setComment((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == TAGS_PROPERTY) {
+ return tags();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return JAVADOC;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Javadoc result = new Javadoc(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setComment(getComment());
+ }
+ result.tags().addAll(ASTNode.copySubtrees(target, tags()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.tags);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the doc comment string, including the starting
+ * and ending comment delimiters, and any embedded line breaks.
+ *
+ * @return the doc comment string
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * See {@link #tags() tags}.
+ */
+ public String getComment() {
+ supportedOnlyIn2();
+ return this.comment;
+ }
+
+ /**
+ * Sets or clears the doc comment string. The documentation
+ * string must include the starting and ending comment delimiters,
+ * and any embedded line breaks.
+ *
+ * @param docComment the doc comment string
+ * @exception IllegalArgumentException if the Java comment string is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * See {@link #tags() tags}.
+ */
+ public void setComment(String docComment) {
+ supportedOnlyIn2();
+ if (docComment == null) {
+ throw new IllegalArgumentException();
+ }
+ char[] source = docComment.toCharArray();
+ Scanner scanner = this.ast.scanner;
+ scanner.resetTo(0, source.length);
+ scanner.setSource(source);
+ try {
+ int token;
+ boolean onlyOneComment = false;
+ while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ if (onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ onlyOneComment = true;
+ break;
+ default:
+ onlyOneComment = false;
+ }
+ }
+ if (!onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(COMMENT_PROPERTY);
+ this.comment = docComment;
+ postValueChange(COMMENT_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of tag elements that make up this doc
+ * comment.
+ * <p>
+ * The tag elements cover everything except the starting and ending
+ * comment delimiters, and generally omit leading whitespace
+ * (including a leading "*") and embedded line breaks.
+ * The first tag element of a typical doc comment represents
+ * all the material before the first explicit doc tag; this
+ * first tag element has a <code>null</code> tag name and
+ * generally contains 1 or more {@link TextElement}s,
+ * and possibly interspersed with tag elements for nested tags
+ * like "{@link String String}".
+ * Subsequent tag elements represent successive top-level doc
+ * tag (e.g., "@param", "@return", "@see").
+ * </p>
+ * <p>
+ * Adding and removing nodes from this list affects this node
+ * dynamically.
+ * </p>
+ *
+ * @return the live list of tag elements in this doc comment
+ * (element type: <code>TagElement</code>)
+ * @since 3.0
+ */
+ public List tags() {
+ return this.tags;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = super.memSize() + 2 * 4;
+ if (this.comment != MINIMAL_DOC_COMMENT) {
+ // anything other than the default string takes space
+ size += stringSize(this.comment);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.tags.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
new file mode 100644
index 000000000..b1e9c4c02
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Labeled statement AST node type.
+ *
+ * <pre>
+ * LabeledStatement:
+ * Identifier <b>:</b> Statement
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class LabeledStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(LabeledStatement.class, "label", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(LabeledStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(LabeledStatement.class, propertyList);
+ addProperty(LABEL_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName labelName = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an unspecified, but
+ * legal, statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for a labeled statement owned by the given
+ * AST. By default, the statement has an unspecified (but legal) label
+ * and an unspecified (but legal) statement.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ LabeledStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return LABELED_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ LabeledStatement result = new LabeledStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setLabel(
+ (SimpleName) ASTNode.copySubtree(target, getLabel()));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLabel());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this labeled statement.
+ *
+ * @return the variable name node
+ */
+ public SimpleName getLabel() {
+ if (this.labelName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.labelName == null) {
+ preLazyInit();
+ this.labelName= new SimpleName(this.ast);
+ postLazyInit(this.labelName, LABEL_PROPERTY);
+ }
+ }
+ }
+ return this.labelName;
+ }
+
+ /**
+ * Sets the label of this labeled statement.
+ *
+ * @param label the new label
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setLabel(SimpleName label) {
+ if (label == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.labelName;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.labelName = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this labeled statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body= new EmptyStatement(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this labeled statement.
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the body of a labeled statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the body of a <code>LabeledStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.labelName == null ? 0 : getLabel().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LiftingType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LiftingType.java
new file mode 100644
index 000000000..4a432c4a1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LiftingType.java
@@ -0,0 +1,343 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: LiftingType.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT
+ *
+ * Represents DOM-ASTNode for declared lifting (OTJLD §2.3.2)
+ * which has to handle code like:
+ * (MyClass as MyRole role)
+ *
+ * This class has following properties:
+ * Name
+ * baseType
+ * roleType
+ *
+ * This node represents a Type.
+ *
+ * This node inherits from Type and is handled like other types.
+ * - typically used in team level methods (declared lifting)
+ *
+ * @author jsv
+ */
+
+public class LiftingType extends Type
+{
+
+ /**
+ * The "BaseType" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BASE_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(LiftingType.class, "baseType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "roleType" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ROLE_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(LiftingType.class, "roleType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(LiftingType.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ List propertyList = new ArrayList(4);
+ createPropertyList(LiftingType.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(BASE_TYPE_PROPERTY, propertyList);
+ addProperty(ROLE_TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type name node; lazily initialized; defaults to a type with
+ * an unspecified, but legal, name.
+ */
+ private Name typeName = null;
+
+ /**
+ * The base type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type _baseType = null;
+
+ /**
+ * The role type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type _roleType = null;
+
+ /**
+ * Creates a new unparented node for a lifting type owned by the given AST.
+ * By default, an unspecified, but legal, name.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ LiftingType(AST ast)
+ {
+ super(ast);
+ }
+
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == NAME_PROPERTY)
+ {
+ if (get)
+ {
+ return getName();
+ }
+ else
+ {
+ setName((Name) child);
+ return null;
+ }
+ }
+
+ if (property == BASE_TYPE_PROPERTY)
+ {
+ if (get)
+ {
+ return getBaseType();
+ }
+ else
+ {
+ setBaseType((Type) child);
+ return null;
+ }
+ }
+
+ if (property == ROLE_TYPE_PROPERTY)
+ {
+ if (get)
+ {
+ return getRoleType();
+ }
+ else
+ {
+ setRoleType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ final int getNodeType0()
+ {
+ return LIFTING_TYPE;
+ }
+
+ ASTNode clone0(AST target)
+ {
+ LiftingType result = new LiftingType(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((Name) (getName()).clone(target));
+ result.setBaseType((Type) ASTNode.copySubtree(target, getBaseType()));
+ result.setRoleType((Type) ASTNode.copySubtree(target, getRoleType()));
+
+ return result;
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getBaseType());
+ acceptChild(visitor, getRoleType());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of this lifting type.
+ *
+ * @return the name of this lifting type
+ */
+ public Name getName()
+ {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of this lifting type to the given name.
+ *
+ * @param typeName the new name of this lifting type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(Name typeName)
+ {
+ if (typeName == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the base type in this LiftingType,
+ */
+ public Type getBaseType()
+ {
+ if (this._baseType == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this._baseType == null)
+ {
+ preLazyInit();
+ this._baseType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this._baseType, BASE_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this._baseType;
+ }
+
+ /**
+ * Returns the role type in this LiftingType,
+ */
+ public Type getRoleType()
+ {
+ if (this._roleType == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this._roleType == null)
+ {
+ preLazyInit();
+ this._roleType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this._roleType, ROLE_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this._roleType;
+ }
+
+ /**
+ * Sets the base type of in this LiftingType
+ */
+ public void setBaseType(Type type)
+ {
+ if (type == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this._baseType;
+ preReplaceChild(oldChild, type, BASE_TYPE_PROPERTY);
+ this._baseType = type;
+ postReplaceChild(oldChild, type, BASE_TYPE_PROPERTY);
+ }
+
+ /**
+ * Sets the role type of in this LiftingType
+ */
+ public void setRoleType(Type type)
+ {
+ if (type == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this._roleType;
+ preReplaceChild(oldChild, type, ROLE_TYPE_PROPERTY);
+ this._roleType = type;
+ postReplaceChild(oldChild, type, ROLE_TYPE_PROPERTY);
+ }
+
+ int memSize()
+ {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ int treeSize()
+ {
+ return memSize()
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.getBaseType() == null ? 0 : getBaseType().treeSize())
+ + (this.getRoleType() == null ? 0 : getRoleType().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java
new file mode 100644
index 000000000..d1f73ef69
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LineComment.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * End-of-line comment AST node type.
+ * <p>
+ * End-of-line comments begin with "//",
+ * must end with a line delimiter (as per JLS 3.7),
+ * and must not contain line breaks.
+ * </p>
+ * <p>
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ * </p>
+ *
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class LineComment extends Comment {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(1);
+ createPropertyList(LineComment.class, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new line comment node owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ LineComment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return LINE_COMMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ LineComment result = new LineComment(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java
new file mode 100644
index 000000000..46e303fd6
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MarkerAnnotation.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Marker annotation node (added in JLS3 API). The marker annotation
+ * "@foo" is equivalent to the normal annotation "@foo()".
+ * <p>
+ * <pre>
+ * MarkerAnnotation:
+ * <b>@</b> TypeName
+ * </pre>
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class MarkerAnnotation extends Annotation {
+
+ /**
+ * The "typeName" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY =
+ internalTypeNamePropertyFactory(MarkerAnnotation.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(MarkerAnnotation.class, propertyList);
+ addProperty(TYPE_NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented marker annotation node owned
+ * by the given AST. By default, the annotation has an
+ * unspecified type name .
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MarkerAnnotation(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_NAME_PROPERTY) {
+ if (get) {
+ return getTypeName();
+ } else {
+ setTypeName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalTypeNameProperty() {
+ return TYPE_NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return MARKER_ANNOTATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MarkerAnnotation result = new MarkerAnnotation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getTypeName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getTypeName().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java
new file mode 100644
index 000000000..da4d55b19
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberRef.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a member reference within a doc comment
+ * ({@link Javadoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to field members (and occasionally to method
+ * and constructor members).
+ * <pre>
+ * MemberRef:
+ * [ Name ] <b>#</b> Identifier
+ * </pre>
+ *
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MemberRef extends ASTNode implements IDocElement {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(MemberRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MemberRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(MemberRef.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; <code>null</code> for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The member name; lazily initialized; defaults to a unspecified,
+ * legal Java method name.
+ */
+ private SimpleName memberName = null;
+
+ /**
+ * Creates a new AST node for a member reference owned by the given
+ * AST. By default, the method reference is for a member with an
+ * unspecified, but legal, name; and no qualifier.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MemberRef(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return MEMBER_REF;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MemberRef result = new MemberRef(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this member reference, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this member reference.
+ *
+ * @param name the qualifier name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the referenced member.
+ *
+ * @return the member name node
+ */
+ public SimpleName getName() {
+ if (this.memberName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.memberName == null) {
+ preLazyInit();
+ this.memberName = new SimpleName(this.ast);
+ postLazyInit(this.memberName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.memberName;
+ }
+
+ /**
+ * Sets the name of the referenced member to the given name.
+ *
+ * @param name the new member name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the name is <code>null</code></li>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.memberName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.memberName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by
+ * this member reference.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveReference(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.memberName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java
new file mode 100644
index 000000000..fcf231904
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePair.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Member value pair node (added in JLS3 API). Member value pairs appear in annotations.
+ * <p>
+ * <pre>
+ * MemberValuePair:
+ * SimpleName <b>=</b> Expression
+ * </pre>
+ * Within annotations, only certain kinds of expressions are meaningful,
+ * including other annotations.
+ * </p>
+ *
+ * @see NormalAnnotation
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MemberValuePair extends ASTNode {
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MemberValuePair.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "value" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor VALUE_PROPERTY =
+ new ChildPropertyDescriptor(MemberValuePair.class, "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(MemberValuePair.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(VALUE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The member name; lazily initialized; defaults to a unspecified,
+ * legal name.
+ */
+ private SimpleName name = null;
+
+ /**
+ * The value; lazily initialized; defaults to a unspecified,
+ * legal expression.
+ */
+ private Expression value = null;
+
+ /**
+ * Creates a new AST node for a member value pair owned by the given
+ * AST. By default, the node has an unspecified (but legal) member
+ * name and value.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MemberValuePair(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == VALUE_PROPERTY) {
+ if (get) {
+ return getValue();
+ } else {
+ setValue((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return MEMBER_VALUE_PAIR;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MemberValuePair result = new MemberValuePair(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ result.setValue((Expression) ASTNode.copySubtree(target, getValue()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getValue());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the member name.
+ *
+ * @return the member name node
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Resolves and returns the member value pair binding for this member value pair.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ * @since 3.2
+ */
+ public final IMemberValuePairBinding resolveMemberValuePairBinding() {
+ return this.ast.getBindingResolver().resolveMemberValuePair(this);
+ }
+
+ /**
+ * Sets the member name.
+ *
+ * @param name the member name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the value expression.
+ *
+ * @return the value expression
+ */
+ public Expression getValue() {
+ if (this.value == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.value == null) {
+ preLazyInit();
+ this.value= new SimpleName(this.ast);
+ postLazyInit(this.value, VALUE_PROPERTY);
+ }
+ }
+ }
+ return this.value;
+ }
+
+ /**
+ * Sets the value of this pair.
+ *
+ * @param value the new value
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setValue(Expression value) {
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.value;
+ preReplaceChild(oldChild, value, VALUE_PROPERTY);
+ this.value = value;
+ postReplaceChild(oldChild, value, VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.name == null ? 0 : getName().treeSize())
+ + (this.value == null ? 0 : getValue().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePairBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePairBinding.java
new file mode 100644
index 000000000..6f2c13bb3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MemberValuePairBinding.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ * IBM Corporation - implemented methods from IBinding
+ * IBM Corporation - renamed from ResolvedMemberValuePair to MemberValuePairBinding
+ * jgarms@bea.com - Fix for IllegalStateException
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+
+/**
+ * Internal class.
+ */
+class MemberValuePairBinding implements IMemberValuePairBinding {
+ static final MemberValuePairBinding[] NoPair = new MemberValuePairBinding[0];
+ private static final Object NoValue = new Object();
+ private static final Object[] EmptyArray = new Object[0];
+
+ private ElementValuePair internalPair;
+ protected Object value = null;
+ protected BindingResolver bindingResolver;
+
+ static void appendValue(Object value, StringBuffer buffer) {
+ if (value instanceof Object[]) {
+ Object[] values = (Object[]) value;
+ buffer.append('{');
+ for (int i = 0, l = values.length; i < l; i++) {
+ if (i != 0)
+ buffer.append(", "); //$NON-NLS-1$
+ appendValue(values[i], buffer);
+ }
+ buffer.append('}');
+ } else if (value instanceof ITypeBinding) {
+ buffer.append(((ITypeBinding) value).getName());
+ buffer.append(".class"); //$NON-NLS-1$
+ } else {
+ buffer.append(value);
+ }
+ }
+
+ static Object buildDOMValue(final Object internalObject, BindingResolver resolver) {
+ if (internalObject == null)
+ return null;
+
+ if (internalObject instanceof Constant) {
+ Constant constant = (Constant) internalObject;
+ switch (constant.typeID()) {
+ case TypeIds.T_boolean:
+ return Boolean.valueOf(constant.booleanValue());
+ case TypeIds.T_byte:
+ return new Byte(constant.byteValue());
+ case TypeIds.T_char:
+ return new Character(constant.charValue());
+ case TypeIds.T_double:
+ return new Double(constant.doubleValue());
+ case TypeIds.T_float:
+ return new Float(constant.floatValue());
+ case TypeIds.T_int:
+ return new Integer(constant.intValue());
+ case TypeIds.T_long:
+ return new Long(constant.longValue());
+ case TypeIds.T_short:
+ return new Short(constant.shortValue());
+ case TypeIds.T_JavaLangString:
+ return constant.stringValue();
+ }
+ } else if (internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+ return resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding) internalObject);
+ } else if (internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding) {
+ return resolver.getAnnotationInstance((org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding) internalObject);
+ } else if (internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.FieldBinding) {
+ return resolver.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.FieldBinding) internalObject);
+ } else if (internalObject instanceof Object[]) {
+ Object[] elements = (Object[]) internalObject;
+ int length = elements.length;
+ Object[] values = length == 0 ? EmptyArray : new Object[length];
+ for (int i = 0; i < length; i++)
+ values[i] = buildDOMValue(elements[i], resolver);
+ return values;
+ }
+ return null;
+ }
+
+ MemberValuePairBinding(ElementValuePair pair, BindingResolver resolver) {
+ this.internalPair = pair;
+ this.bindingResolver = resolver;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ return AnnotationBinding.NoAnnotations;
+ }
+
+ public IJavaElement getJavaElement() {
+ return null;
+ }
+
+ public String getKey() {
+ // TODO when implementing, update spec in IBinding
+ return null;
+ }
+
+ public int getKind() {
+ return IBinding.MEMBER_VALUE_PAIR;
+ }
+
+ public IMethodBinding getMethodBinding() {
+ return this.bindingResolver.getMethodBinding(this.internalPair.getMethodBinding());
+ }
+
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ public String getName() {
+ if (this.internalPair == null)
+ return null;
+ final char[] membername = this.internalPair.getName();
+ return membername == null ? null : new String(membername);
+ }
+
+ public Object getValue() {
+ if (this.value == null)
+ init();
+ return this.value == NoValue ? null : this.value;
+ }
+
+ private void init() {
+ this.value = buildDOMValue(this.internalPair.getValue(), this.bindingResolver);
+ if (this.value == null)
+ this.value = NoValue;
+ }
+
+ char[] internalName() {
+ return this.internalPair == null ? null : this.internalPair.getName();
+ }
+
+ public boolean isDefault() {
+ Object value2 = getValue();
+ Object defaultValue = getMethodBinding().getDefaultValue();
+ if (value2 instanceof IBinding) {
+ if (defaultValue instanceof IBinding) {
+ return ((IBinding) value2).isEqualTo((IBinding) defaultValue);
+ }
+ return false;
+ }
+ if (defaultValue == null) return false;
+ return defaultValue.equals(value2);
+ }
+
+ public boolean isDeprecated() {
+ MethodBinding methodBinding = this.internalPair.getMethodBinding();
+ return methodBinding == null ? false : methodBinding.isDeprecated();
+ }
+
+ public boolean isEqualTo(IBinding binding) {
+ if (this == binding)
+ return true;
+ if (binding.getKind() != IBinding.MEMBER_VALUE_PAIR)
+ return false;
+ IMemberValuePairBinding other = (IMemberValuePairBinding) binding;
+ if (!getMethodBinding().isEqualTo(other.getMethodBinding())) {
+ return false;
+ }
+ Object otherValue = other.getValue();
+ Object currentValue = getValue();
+ if (currentValue == null) {
+ return otherValue == null;
+ }
+ if (currentValue instanceof IBinding) {
+ if (otherValue instanceof IBinding) {
+ return ((IBinding) currentValue).isEqualTo((IBinding) otherValue);
+ }
+ return false;
+ }
+ return currentValue.equals(otherValue);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getName());
+ buffer.append(" = "); //$NON-NLS-1$
+ appendValue(getValue(), buffer);
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Message.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Message.java
new file mode 100644
index 000000000..998cb8e11
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Message.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Error message used to report potential errors found during the AST parsing
+ * or name resolution. Instances of this class are immutable.
+ *
+ * @since 2.0
+ */
+public class Message {
+
+ /**
+ * The message.
+ */
+ private String message;
+
+ /**
+ * The character index into the original source string, or -1 if none.
+ */
+ private int startPosition;
+
+ /**
+ * The length in characters of the original source file indicating
+ * where the source fragment corresponding to this message ends.
+ */
+ private int length;
+
+ /**
+ * Creates a message.
+ *
+ * @param message the localized message reported by the compiler
+ * @param startPosition the 0-based character index into the
+ * original source file, or <code>-1</code> if no source position
+ * information is to be recorded for this message
+ * @throws IllegalArgumentException if the message is null
+ * @throws IllegalArgumentException if the startPosition is lower than -1.
+ */
+ public Message(String message, int startPosition) {
+ if (message == null) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.message = message;
+ this.startPosition = startPosition;
+ this.length = 0;
+ }
+
+ /**
+ * Creates a message.
+ *
+ * @param message the localized message reported by the compiler
+ * @param startPosition the 0-based character index into the
+ * original source file, or <code>-1</code> if no source position
+ * information is to be recorded for this message
+ * @param length the length in character of the original source file indicating
+ * where the source fragment corresponding to this message ends. 0 or a negative number
+ * if none. A negative number will be converted to a 0-length.
+ * @throws IllegalArgumentException if the message is null
+ * @throws IllegalArgumentException if the startPosition is lower than -1.
+ */
+ public Message(String message, int startPosition, int length) {
+ if (message == null) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.message = message;
+ this.startPosition = startPosition;
+ if (length <= 0) {
+ this.length = 0;
+ } else {
+ this.length = length;
+ }
+ }
+
+ /**
+ * Returns the localized message.
+ *
+ * @return the localized message
+ */
+ public String getMessage() {
+ return this.message;
+ }
+
+ /**
+ * Returns the character index into the original source file.
+ *
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is recorded for this
+ * message
+ * @deprecated Use {@link #getStartPosition()} instead.
+ * @see #getLength()
+ */
+ public int getSourcePosition() {
+ return getStartPosition();
+ }
+
+ /**
+ * Returns the character index into the original source file.
+ *
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is recorded for this
+ * message
+ * @see #getLength()
+ */
+ public int getStartPosition() {
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the length in characters of the original source file indicating
+ * where the source fragment corresponding to this message ends.
+ *
+ * @return a length, or <code>0</code>
+ * if no source length information is recorded for this message
+ * @see #getStartPosition()
+ */
+ public int getLength() {
+ return this.length;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
new file mode 100644
index 000000000..d3cb6df8d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -0,0 +1,473 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: MethodBinding.java 23404 2010-02-03 14:10:22Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
+import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
+
+/**
+ * Internal implementation of method bindings.
+ */
+class MethodBinding implements IMethodBinding {
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+//{ObjectTeams: callin:
+ Modifier.OT_CALLIN |
+// SH}
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
+ Modifier.STRICTFP;
+ private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+ private org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding;
+ private BindingResolver resolver;
+ private ITypeBinding[] parameterTypes;
+ private ITypeBinding[] exceptionTypes;
+ private String name;
+ private ITypeBinding declaringClass;
+ private ITypeBinding returnType;
+ private String key;
+ private ITypeBinding[] typeParameters;
+ private ITypeBinding[] typeArguments;
+ private IAnnotationBinding[] annotations;
+ private IAnnotationBinding[][] parameterAnnotations;
+
+ MethodBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding) {
+ this.resolver = resolver;
+ this.binding = binding;
+ }
+
+ public boolean isAnnotationMember() {
+ return getDeclaringClass().isAnnotation();
+ }
+
+ /**
+ * @see IMethodBinding#isConstructor()
+ */
+ public boolean isConstructor() {
+ return this.binding.isConstructor();
+ }
+
+ /**
+ * @see IMethodBinding#isDefaultConstructor()
+ * @since 3.0
+ */
+ public boolean isDefaultConstructor() {
+ final ReferenceBinding declaringClassBinding = this.binding.declaringClass;
+ if (declaringClassBinding.isRawType()) {
+ RawTypeBinding rawTypeBinding = (RawTypeBinding) declaringClassBinding;
+ if (rawTypeBinding.genericType().isBinaryBinding()) {
+ return false;
+ }
+ return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
+ }
+ if (declaringClassBinding.isBinaryBinding()) {
+ return false;
+ }
+ return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
+ }
+
+ /**
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (this.name == null) {
+ if (this.binding.isConstructor()) {
+ this.name = getDeclaringClass().getName();
+ } else {
+ this.name = new String(this.binding.selector);
+ }
+ }
+ return this.name;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ if (this.annotations != null) {
+ return this.annotations;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
+ int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+ if (length != 0) {
+ IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+ int convertedAnnotationCount = 0;
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+ final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+ if (annotationInstance == null) {
+ continue;
+ }
+ tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+ }
+ if (convertedAnnotationCount != length) {
+ if (convertedAnnotationCount == 0) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+ }
+ return this.annotations = tempAnnotations;
+ }
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+
+ /**
+ * @see IMethodBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ if (this.declaringClass == null) {
+//{ObjectTeams: a role-ifc-method representing a one that is inherited from a non-role?
+ if (this.binding.copyInheritanceSrc != null)
+ {
+ this.declaringClass = this.resolver.getTypeBinding(this.binding.copyInheritanceSrc.declaringClass);
+ if (!this.declaringClass.isRole())
+ return this.declaringClass;
+ }
+// SH}
+ this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
+ }
+ return this.declaringClass;
+ }
+
+ public IAnnotationBinding[] getParameterAnnotations(int index) {
+ if (getParameterTypes() == NO_TYPE_BINDINGS) {
+ return AnnotationBinding.NoAnnotations;
+ }
+ if (this.parameterAnnotations != null) {
+ return this.parameterAnnotations[index];
+ }
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[][] bindingAnnotations = this.binding.getParameterAnnotations();
+ if (bindingAnnotations == null) return AnnotationBinding.NoAnnotations;
+
+ int length = bindingAnnotations.length;
+ IAnnotationBinding[][] domAnnotations = new IAnnotationBinding[length][];
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] paramBindingAnnotations = bindingAnnotations[i];
+ int pLength = paramBindingAnnotations.length;
+ domAnnotations[i] = new AnnotationBinding[pLength];
+ for (int j=0; j<pLength; j++) {
+ IAnnotationBinding domAnnotation = this.resolver.getAnnotationInstance(paramBindingAnnotations[j]);
+ if (domAnnotation == null) {
+ domAnnotations[i] = AnnotationBinding.NoAnnotations;
+ break;
+ }
+ domAnnotations[i][j] = domAnnotation;
+ }
+ }
+ this.parameterAnnotations = domAnnotations;
+
+ return this.parameterAnnotations[index];
+ }
+
+ /**
+ * @see IMethodBinding#getParameterTypes()
+ */
+ public ITypeBinding[] getParameterTypes() {
+ if (this.parameterTypes != null) {
+ return this.parameterTypes;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
+//{ObjectTeams: retrench callin method:
+ if ((this.getModifiers() & ExtraCompilerModifiers.AccCallin) != 0)
+ parameters = MethodSignatureEnhancer.retrenchParameterTypes(parameters);
+// SH}
+ int length = parameters == null ? 0 : parameters.length;
+ if (length == 0) {
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ } else {
+ ITypeBinding[] paramTypes = new ITypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ final TypeBinding parameterBinding = parameters[i];
+ if (parameterBinding != null) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(parameterBinding);
+ if (typeBinding == null) {
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ }
+ paramTypes[i] = typeBinding;
+ } else {
+ // log error
+ StringBuffer message = new StringBuffer("Report method binding where a parameter is null:\n"); //$NON-NLS-1$
+ message.append(toString());
+ Util.log(new IllegalArgumentException(), message.toString());
+ // report no binding since one or more parameter has no binding
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ }
+ }
+ return this.parameterTypes = paramTypes;
+ }
+ }
+
+ /**
+ * @see IMethodBinding#getReturnType()
+ */
+ public ITypeBinding getReturnType() {
+ if (this.returnType == null) {
+//{ObjectTeams: retrench callin method:
+ if ((this.getModifiers() & ExtraCompilerModifiers.AccCallin) != 0) {
+ TypeBinding realReturnType = MethodModel.getReturnType(this.binding);
+ this.returnType = this.resolver.getTypeBinding(realReturnType);
+ } else
+// SH}
+ this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
+ }
+ return this.returnType;
+ }
+
+ public Object getDefaultValue() {
+ if (isAnnotationMember())
+ return MemberValuePairBinding.buildDOMValue(this.binding.getDefaultValue(), this.resolver);
+ return null;
+ }
+
+ /**
+ * @see IMethodBinding#getExceptionTypes()
+ */
+ public ITypeBinding[] getExceptionTypes() {
+ if (this.exceptionTypes != null) {
+ return this.exceptionTypes;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
+ int length = exceptions == null ? 0 : exceptions.length;
+ if (length == 0) {
+ return this.exceptionTypes = NO_TYPE_BINDINGS;
+ }
+ ITypeBinding[] exTypes = new ITypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(exceptions[i]);
+ if (typeBinding == null) {
+ return this.exceptionTypes = NO_TYPE_BINDINGS;
+ }
+ exTypes[i] = typeBinding;
+ }
+ return this.exceptionTypes = exTypes;
+ }
+
+ public IJavaElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+
+ DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+ return Util.getUnresolvedJavaElement(
+ this.binding,
+ defaultBindingResolver.workingCopyOwner,
+ defaultBindingResolver.getBindingsToNodesMap());
+ }
+
+ /**
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.METHOD;
+ }
+
+ /**
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return this.binding.getAccessFlags() & VALID_MODIFIERS;
+ }
+
+ /**
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return this.binding.isDeprecated();
+ }
+
+ /**
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /**
+ * @see IBinding#isSynthetic()
+ */
+ public boolean isSynthetic() {
+ return this.binding.isSynthetic();
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
+ * @since 3.1
+ */
+ public boolean isVarargs() {
+ return this.binding.isVarargs();
+ }
+
+ /**
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /**
+ * @see IBinding#isEqualTo(IBinding)
+ * @since 3.1
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof MethodBinding)) {
+ return false;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
+ return BindingComparator.isEqual(this.binding, otherBinding);
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
+ */
+ public ITypeBinding[] getTypeParameters() {
+ if (this.typeParameters != null) {
+ return this.typeParameters;
+ }
+ TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+ int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
+ if (typeVariableBindingsLength == 0) {
+ return this.typeParameters = NO_TYPE_BINDINGS;
+ }
+ ITypeBinding[] tParameters = new ITypeBinding[typeVariableBindingsLength];
+ for (int i = 0; i < typeVariableBindingsLength; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
+ if (typeBinding == null) {
+ return this.typeParameters = NO_TYPE_BINDINGS;
+ }
+ tParameters[i] = typeBinding;
+ }
+ return this.typeParameters = tParameters;
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#isGenericMethod()
+ * @since 3.1
+ */
+ public boolean isGenericMethod() {
+ // equivalent to return getTypeParameters().length > 0;
+ if (this.typeParameters != null) {
+ return this.typeParameters.length > 0;
+ }
+ TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+ return (typeVariableBindings != null && typeVariableBindings.length > 0);
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
+ */
+ public ITypeBinding[] getTypeArguments() {
+ if (this.typeArguments != null) {
+ return this.typeArguments;
+ }
+
+ if (this.binding instanceof ParameterizedGenericMethodBinding) {
+ ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) this.binding;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] typeArgumentsBindings = genericMethodBinding.typeArguments;
+ int typeArgumentsLength = typeArgumentsBindings == null ? 0 : typeArgumentsBindings.length;
+ if (typeArgumentsLength != 0) {
+ ITypeBinding[] tArguments = new ITypeBinding[typeArgumentsLength];
+ for (int i = 0; i < typeArgumentsLength; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(typeArgumentsBindings[i]);
+ if (typeBinding == null) {
+ return this.typeArguments = NO_TYPE_BINDINGS;
+ }
+ tArguments[i] = typeBinding;
+ }
+ return this.typeArguments = tArguments;
+ }
+ }
+ return this.typeArguments = NO_TYPE_BINDINGS;
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
+ */
+ public boolean isParameterizedMethod() {
+ return (this.binding instanceof ParameterizedGenericMethodBinding)
+ && !((ParameterizedGenericMethodBinding) this.binding).isRaw;
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
+ */
+ public boolean isRawMethod() {
+ return (this.binding instanceof ParameterizedGenericMethodBinding)
+ && ((ParameterizedGenericMethodBinding) this.binding).isRaw;
+ }
+
+ public boolean isSubsignature(IMethodBinding otherMethod) {
+ try {
+ LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+ return lookupEnvironment != null
+ && lookupEnvironment.methodVerifier().isMethodSubsignature(this.binding, ((MethodBinding) otherMethod).binding);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.IMethodBinding#getMethodDeclaration()
+ */
+ public IMethodBinding getMethodDeclaration() {
+ return this.resolver.getMethodBinding(this.binding.original());
+ }
+
+ /**
+ * @see IMethodBinding#overrides(IMethodBinding)
+ */
+ public boolean overrides(IMethodBinding otherMethod) {
+ LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+ return lookupEnvironment != null
+ && lookupEnvironment.methodVerifier().doesMethodOverride(this.binding, ((MethodBinding) otherMethod).binding);
+ }
+
+ /**
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+//{ObjectTeams: new query:
+ public boolean isCopied() {
+ return this.binding.copyInheritanceSrc != null;
+ }
+// SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBindingOperator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBindingOperator.java
new file mode 100644
index 000000000..152053869
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBindingOperator.java
@@ -0,0 +1,244 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2009 Stephan Herrmann
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents all information concerning HOW a method mapping connects
+ * its role/base features:
+ * <ul>
+ * <li>The binding kind as marked by one of the tokens <code>-&gt;,=&gt;,&lt;-</code>
+ * <li>An optional modifier, one of <code>before,replace,after</code> (callin) or <code>get,set</code> (callout-to-field).
+ * </ul>
+ * @author stephan
+ * @since 1.3.1
+ */
+@SuppressWarnings("unchecked")
+public class MethodBindingOperator extends ASTNode {
+
+ public static final int KIND_CALLOUT = 1;
+ public static final int KIND_CALLOUT_OVERRIDE = 2;
+ public static final int KIND_CALLIN = 3;
+
+ /**
+ * The "binding-kind" property of this node type.
+ */
+ public static final SimplePropertyDescriptor BINDING_KIND_PROPERTY =
+ new SimplePropertyDescriptor(MethodBindingOperator.class, "bindingKind", int.class, MANDATORY);
+
+ /**
+ * The "binding-modifier" structural property of this node type, none if regular callout.
+ */
+ public static final ChildPropertyDescriptor BINDING_MODIFIER_PROPERTY =
+ new ChildPropertyDescriptor(MethodBindingOperator.class, "bindingModifier", Modifier.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static
+ {
+ List propertyList = new ArrayList(1);
+ createPropertyList(MethodBindingOperator.class, propertyList);
+ addProperty(BINDING_KIND_PROPERTY, propertyList);
+ addProperty(BINDING_MODIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(1);
+ createPropertyList(MethodBindingOperator.class, propertyList);
+ addProperty(BINDING_KIND_PROPERTY, propertyList);
+ addProperty(BINDING_MODIFIER_PROPERTY, propertyList); // one flag, not a bitset
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ if(apiLevel == AST.JLS3)
+ return PROPERTY_DESCRIPTORS_3_0;
+ else
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+
+ private int bindingKind = 0; // one of KIND_CALLIN, KIND_CALLOUT, KIND_CALLOUT_OVERRIDE;
+ /**
+ * The modifier flags; exactly one of before, after, replace.
+ * No default.
+ */
+ private int bindingModifierFlag = 0;
+ private Modifier bindingModifier;
+
+ public MethodBindingOperator(AST ast) {
+ super(ast);
+ }
+
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == BINDING_MODIFIER_PROPERTY)
+ {
+ if (get) {
+ return bindingModifier();
+ } else {
+ setBindingModifier((Modifier)child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ @Override
+ int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == BINDING_KIND_PROPERTY) {
+ if (get) {
+ return getBindingKind();
+ }
+ else
+ {
+ setBindingKind(value);
+ return 0;
+ }
+ }
+
+ // default impl to signal errors
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ public int getBindingKind() {
+ return this.bindingKind;
+ }
+
+ public void setBindingKind(int bindingKind) {
+ if (bindingKind < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(BINDING_KIND_PROPERTY);
+ this.bindingKind = bindingKind;
+ postValueChange(BINDING_KIND_PROPERTY);
+ }
+
+
+ /**
+ * Returns the callin modifiers explicitly specified on this declaration.
+ *
+ * @return exactly one of before, after, replace using constants from Modifier
+ * @see Modifier
+ */
+ public int getBindingModifier()
+ {
+ if (this.bindingModifierFlag == 0 && this.bindingModifier != null)
+ {
+ this.bindingModifierFlag = this.bindingModifier.getKeyword().toFlagValue();
+ }
+ return bindingModifierFlag;
+ }
+
+ /**
+ * Sets the callin or c-t-f modifier explicitly specified on this declaration.
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @see Modifier
+ */
+ public void setBindingModifier(int modifiers)
+ {
+ setBindingModifier(this.ast.newModifier(Modifier.ModifierKeyword.fromFlagValue(modifiers)));
+ }
+
+ public void setBindingModifier(Modifier modifier) {
+ ChildPropertyDescriptor propertyDescriptor = BINDING_MODIFIER_PROPERTY;
+ Modifier oldModifier = this.bindingModifier;
+ preReplaceChild(oldModifier, modifier, propertyDescriptor);
+ this.bindingModifierFlag = 0; // clear cached flags
+ this.bindingModifier = modifier;
+ postReplaceChild(oldModifier, modifier, propertyDescriptor);
+ }
+
+ /**
+ * Returns the callin or c-t-f modifier for this mapping declaration.
+ *
+ * @see Modifier
+ * @return one of before, after, replace
+ */
+ public Modifier bindingModifier()
+ {
+ return bindingModifier;
+ }
+
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, this.bindingModifier);
+ }
+ visitor.endVisit(this);
+ }
+
+ ASTNode clone0(AST target) {
+ MethodBindingOperator result = new MethodBindingOperator(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setBindingModifier(this.bindingModifier);
+ result.setBindingKind(this.bindingKind);
+ return result;
+ }
+
+ int getNodeType0() {
+ return METHOD_BINDING_OPERATOR;
+ }
+
+ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ int memSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ if (!(other instanceof MethodBindingOperator))
+ return false;
+ MethodBindingOperator otherOp = (MethodBindingOperator) other;
+ return (otherOp.bindingKind == this.bindingKind)
+ && (otherOp.getBindingModifier() == this.getBindingModifier());
+ }
+
+ int treeSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
new file mode 100644
index 000000000..16c219571
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
@@ -0,0 +1,953 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method declaration AST node type. A method declaration
+ * is the union of a method declaration and a constructor declaration.
+ * For JLS2:
+ * <pre>
+ * MethodDeclaration:
+ * [ Javadoc ] { Modifier } ( Type | <b>void</b> ) Identifier <b>(</b>
+ * [ FormalParameter
+ * { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
+ * [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
+ * ConstructorDeclaration:
+ * [ Javadoc ] { Modifier } Identifier <b>(</b>
+ * [ FormalParameter
+ * { <b>,</b> FormalParameter } ] <b>)</b>
+ * [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
+ * </pre>
+ * For JLS3, type parameters and reified modifiers
+ * (and annotations) were added:
+ * <pre>
+ * MethodDeclaration:
+ * [ Javadoc ] { ExtendedModifier }
+ * [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ * ( Type | <b>void</b> ) Identifier <b>(</b>
+ * [ FormalParameter
+ * { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
+ * [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
+ * ConstructorDeclaration:
+ * [ Javadoc ] { ExtendedModifier }
+ * [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ * Identifier <b>(</b>
+ * [ FormalParameter
+ * { <b>,</b> FormalParameter } ] <b>)</b>
+ * [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), or the
+ * first character of the "&lt;" token (method, no modifiers, type parameters),
+ * or the first character of the return type (method, no modifiers, no type
+ * parameters), or the first character of the identifier (constructor,
+ * no modifiers). The source range extends through the last character of the
+ * ";" token (if no body), or the last character of the block (if body).
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(MethodDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(MethodDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(MethodDeclaration.class);
+
+ /**
+ * The "constructor" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY =
+ new SimplePropertyDescriptor(MethodDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MethodDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "returnType" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(MethodDeclaration.class, "returnType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "returnType2" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY =
+ new ChildPropertyDescriptor(MethodDeclaration.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(MethodDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "typeParameters" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "parameters" structural property of this node type).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodDeclaration.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thrownExceptions" structural property of this node type).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor THROWN_EXCEPTIONS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodDeclaration.class, "thrownExceptions", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+//{ObjectTeams: new element:
+ /**
+ * The "guardPredicate" structural property of this node type.
+ * @since 0.9.25
+ */
+ public static final ChildPropertyDescriptor GUARD_PROPERTY =
+ new ChildPropertyDescriptor(MethodDeclaration.class, "guardPredicate", GuardPredicateDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+// SH}
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(MethodDeclaration.class, "body", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(10);
+ createPropertyList(MethodDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+ addProperty(RETURN_TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+//{ObjectTeams:
+ addProperty(GUARD_PROPERTY, propertyList);
+// SH}
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(12);
+ createPropertyList(MethodDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+ addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+ addProperty(RETURN_TYPE2_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+//{ObjectTeams:
+ addProperty(GUARD_PROPERTY, propertyList);
+// SH}
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * <code>true</code> for a constructor, <code>false</code> for a method.
+ * Defaults to method.
+ */
+ private boolean isConstructor = false;
+
+ /**
+ * The method name; lazily initialized; defaults to an unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The parameter declarations
+ * (element type: <code>SingleVariableDeclaration</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList parameters =
+ new ASTNode.NodeList(PARAMETERS_PROPERTY);
+
+ /**
+ * The return type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * JLS3 behavior; lazily initialized; defaults to void; null allowed.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type returnType = null;
+
+ /**
+ * Indicated whether the return type has been initialized.
+ * @since 3.1
+ */
+ private boolean returnType2Initialized = false;
+
+ /**
+ * The type paramters (element type: <code>TypeParameter</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeParameters = null;
+
+ /**
+ * The number of array dimensions that appear after the parameters, rather
+ * than after the return type itself; defaults to 0.
+ *
+ * @since 2.1
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The list of thrown exception names (element type: <code>Name</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList thrownExceptions =
+ new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
+
+//{ObjectTeams: new element:
+ GuardPredicateDeclaration _optionalGuardPredicate = null;
+// SH}
+ /**
+ * The method body, or <code>null</code> if none.
+ * Defaults to none.
+ */
+ private Block optionalBody = null;
+
+ /**
+ * Creates a new AST node for a method declaration owned
+ * by the given AST. By default, the declaration is for a method of an
+ * unspecified, but legal, name; no modifiers; no javadoc; no type
+ * parameters; void return type; no parameters; no array dimensions after
+ * the parameters; no thrown exceptions; and no body (as opposed to an
+ * empty body).
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == CONSTRUCTOR_PROPERTY) {
+ if (get) {
+ return isConstructor();
+ } else {
+ setConstructor(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == RETURN_TYPE_PROPERTY) {
+ if (get) {
+ return getReturnType();
+ } else {
+ setReturnType((Type) child);
+ return null;
+ }
+ }
+ if (property == RETURN_TYPE2_PROPERTY) {
+ if (get) {
+ return getReturnType2();
+ } else {
+ setReturnType2((Type) child);
+ return null;
+ }
+ }
+//{ObjectTeams:
+ if (property == GUARD_PROPERTY) {
+ if (get) {
+ return getGuardPredicate();
+ } else {
+ setGuardPredicate((GuardPredicateDeclaration) child);
+ return null;
+ }
+ }
+// SH}
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == TYPE_PARAMETERS_PROPERTY) {
+ return typeParameters();
+ }
+ if (property == PARAMETERS_PROPERTY) {
+ return parameters();
+ }
+ if (property == THROWN_EXCEPTIONS_PROPERTY) {
+ return thrownExceptions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return METHOD_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MethodDeclaration result = new MethodDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ result.setReturnType(
+ (Type) ASTNode.copySubtree(target, getReturnType()));
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.typeParameters().addAll(
+ ASTNode.copySubtrees(target, typeParameters()));
+ result.setReturnType2(
+ (Type) ASTNode.copySubtree(target, getReturnType2()));
+ }
+ result.setConstructor(isConstructor());
+ result.setExtraDimensions(getExtraDimensions());
+ result.setName((SimpleName) getName().clone(target));
+ result.parameters().addAll(
+ ASTNode.copySubtrees(target, parameters()));
+ result.thrownExceptions().addAll(
+ ASTNode.copySubtrees(target, thrownExceptions()));
+//{ObjectTeams:
+ result.setGuardPredicate((GuardPredicateDeclaration)ASTNode.copySubtree(target, getGuardPredicate()));
+// SH}
+ result.setBody(
+ (Block) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getReturnType());
+ } else {
+ acceptChildren(visitor, this.modifiers);
+ acceptChildren(visitor, this.typeParameters);
+ acceptChild(visitor, getReturnType2());
+//{ObjectTeams:
+ acceptChild(visitor, this.getGuardPredicate());
+// SH}
+ }
+ // n.b. visit return type even for constructors
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.parameters);
+ acceptChildren(visitor, this.thrownExceptions);
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns whether this declaration declares a constructor or a method.
+ *
+ * @return <code>true</code> if this is a constructor declaration,
+ * and <code>false</code> if this is a method declaration
+ */
+ public boolean isConstructor() {
+ return this.isConstructor;
+ }
+
+ /**
+ * Sets whether this declaration declares a constructor or a method.
+ *
+ * @param isConstructor <code>true</code> for a constructor declaration,
+ * and <code>false</code> for a method declaration
+ */
+ public void setConstructor(boolean isConstructor) {
+ preValueChange(CONSTRUCTOR_PROPERTY);
+ this.isConstructor = isConstructor;
+ postValueChange(CONSTRUCTOR_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type parameters of this method
+ * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
+ *
+ * @return the live list of type parameters
+ * (element type: <code>TypeParameter</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeParameters() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeParameters == null) {
+ unsupportedIn2();
+ }
+ return this.typeParameters;
+ }
+
+ /**
+ * Returns the name of the method declared in this method declaration.
+ * For a constructor declaration, this should be the same as the name
+ * of the class.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method declared in this method declaration to the
+ * given name. For a constructor declaration, this should be the same as
+ * the name of the class.
+ *
+ * @param methodName the new method name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName methodName) {
+ if (methodName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, methodName, NAME_PROPERTY);
+ this.methodName = methodName;
+ postReplaceChild(oldChild, methodName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of method parameter declarations for this
+ * method declaration.
+ *
+ * @return the live list of method parameter declarations
+ * (element type: <code>SingleVariableDeclaration</code>)
+ */
+ public List parameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Returns whether this method declaration declares a
+ * variable arity method (added in JLS3 API). The convenience method checks
+ * whether the last parameter is so marked.
+ *
+ * @return <code>true</code> if this is a variable arity method declaration,
+ * and <code>false</code> otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @see SingleVariableDeclaration#isVarargs()
+ * @since 3.1
+ */
+ public boolean isVarargs() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ if (parameters().isEmpty()) {
+ return false;
+ } else {
+ SingleVariableDeclaration v = (SingleVariableDeclaration) parameters().get(parameters().size() - 1);
+ return v.isVarargs();
+ }
+ }
+
+ /**
+ * Returns the live ordered list of thrown exception names in this method
+ * declaration.
+ *
+ * @return the live list of exception names
+ * (element type: <code>Name</code>)
+ */
+ public List thrownExceptions() {
+ return this.thrownExceptions;
+ }
+
+ /**
+ * Returns the return type of the method declared in this method
+ * declaration, exclusive of any extra array dimensions (JLS2 API only).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available.
+ * </p>
+ *
+ * @return the return type, possibly the void primitive type
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by {@link #getReturnType2()},
+ * which may return <code>null</code>.
+ */
+ public Type getReturnType() {
+ return internalGetReturnType();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final Type internalGetReturnType() {
+ supportedOnlyIn2();
+ if (this.returnType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.returnType == null) {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method declaration
+ * to the given type, exclusive of any extra array dimensions (JLS2 API only). This is one
+ * of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * </p>
+ *
+ * @param type the new return type, possibly the void primitive type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setReturnType2(Type)}, which accepts <code>null</code>.
+ */
+ public void setReturnType(Type type) {
+ internalSetReturnType(type);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ void internalSetReturnType(Type type) {
+ supportedOnlyIn2();
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the return type of the method declared in this method
+ * declaration, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although, if present, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available. In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ * </p>
+ *
+ * @return the return type, possibly the void primitive type,
+ * or <code>null</code> if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public Type getReturnType2() {
+ unsupportedIn2();
+ if (this.returnType == null && !this.returnType2Initialized) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.returnType == null && !this.returnType2Initialized) {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ this.returnType2Initialized = true;
+ postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method declaration
+ * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ * </p>
+ *
+ * @param type the new return type, possibly the void primitive type,
+ * or <code>null</code> if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @since 3.1
+ */
+ public void setReturnType2(Type type) {
+ unsupportedIn2();
+ this.returnType2Initialized = true;
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ }
+
+ /**
+ * Returns the number of extra array dimensions over and above the
+ * explicitly-specified return type.
+ * <p>
+ * For example, <code>int foo()[][]</code> has a return type of
+ * <code>int</code> and two extra array dimensions;
+ * <code>int[][] foo()</code> has a return type of <code>int[][]</code>
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * method declaration.
+ * </p>
+ *
+ * @return the number of extra array dimensions
+ * @since 2.1
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /**
+ * Sets the number of extra array dimensions over and above the
+ * explicitly-specified return type.
+ * <p>
+ * For example, <code>int foo()[][]</code> is rendered as a return
+ * type of <code>int</code> with two extra array dimensions;
+ * <code>int[][] foo()</code> is rendered as a return type of
+ * <code>int[][]</code> with zero extra array dimensions. The two
+ * constructs have different ASTs, even though there are really syntactic
+ * variants of the same method declaration.
+ * </p>
+ *
+ * @param dimensions the number of array dimensions
+ * @exception IllegalArgumentException if the number of dimensions is
+ * negative
+ * @since 2.1
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+//{ObjectTeams: accessors for new element
+ public void setGuardPredicate(GuardPredicateDeclaration predicate) {
+ ASTNode oldChild = this._optionalGuardPredicate;
+ preReplaceChild(oldChild, predicate, GUARD_PROPERTY);
+ this._optionalGuardPredicate = predicate;
+ postReplaceChild(oldChild, predicate, GUARD_PROPERTY);
+ }
+
+ public GuardPredicateDeclaration getGuardPredicate() {
+ return _optionalGuardPredicate;
+ }
+// SH}
+ /**
+ * Returns the body of this method declaration, or <code>null</code> if
+ * this method has <b>no</b> body.
+ * <p>
+ * Note that there is a subtle difference between having no body and having
+ * an empty body ("{}").
+ * </p>
+ *
+ * @return the method body, or <code>null</code> if this method has no
+ * body
+ */
+ public Block getBody() {
+ return this.optionalBody;
+ }
+
+ /**
+ * Sets or clears the body of this method declaration.
+ * <p>
+ * Note that there is a subtle difference between having no body
+ * (as in <code>"void foo();"</code>) and having an empty body (as in
+ * "void foo() {}"). Abstract methods, and methods declared in interfaces,
+ * have no body. Non-abstract methods, and all constructors, have a body.
+ * </p>
+ *
+ * @param body the block node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Block body) {
+ // a MethodDeclaration may occur in a Block - must check cycles
+ ASTNode oldChild = this.optionalBody;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.optionalBody = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the method or constructor declared
+ * in this method or constructor declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public IMethodBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 9 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.returnType == null ? 0 : this.returnType.treeSize())
+ + this.parameters.listSize()
+ + this.thrownExceptions.listSize()
+ + (this.optionalBody == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java
new file mode 100644
index 000000000..c8e827325
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodInvocation.java
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method invocation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * MethodInvocation:
+ * [ Expression <b>.</b> ] Identifier
+ * <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * MethodInvocation:
+ * [ Expression <b>.</b> ]
+ * [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodInvocation extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(MethodInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(MethodInvocation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(5);
+ createPropertyList(MethodInvocation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal Java method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a method invocation expression owned by the
+ * given AST. By default, no expression, no type arguments,
+ * an unspecified, but legal, method name, and an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return METHOD_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MethodInvocation result = new MethodInvocation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) getName().clone(target));
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this method invocation expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Returns <code>true</code> if the resolved return type has been inferred
+ * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise.
+ * <p>
+ * This information is available only when bindings are requested when the AST is being built
+ * </p>.
+ *
+ * @return <code>true</code> if the resolved return type has been inferred
+ * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise
+ * @since 3.3
+ */
+ public boolean isResolvedTypeInferredFromExpectedType() {
+ return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+ }
+
+ /**
+ * Sets or clears the expression of this method invocation expression.
+ *
+ * @param expression the expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this method
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this method
+ * invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the method invoked by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the method binding, or <code>null</code> if the binding cannot
+ * be resolved
+ * @since 2.1
+ */
+ public IMethodBinding resolveMethodBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingBinding.java
new file mode 100644
index 000000000..d67550442
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingBinding.java
@@ -0,0 +1,290 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2005, 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: MethodMappingBinding.java 23417 2010-02-03 20:13:55Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.objectteams.otdt.core.compiler.InferenceKind;
+
+
+/**
+ * Internal implementation of callin/callout mapping bindings.
+ *
+ * @author mkr
+ */
+class MethodMappingBinding implements IMethodMappingBinding
+{
+
+ private org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding _binding;
+ private BindingResolver _resolver;
+ private String _name;
+ private ITypeBinding _declaringClass;
+ private ITypeBinding _baseClass;
+ private IMethodBinding _roleMethod;
+ private IMethodBinding[] _baseMethods;
+
+ MethodMappingBinding(
+ BindingResolver resolver,
+ org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding binding)
+ {
+ _resolver = resolver;
+ _binding = binding;
+ }
+
+ // svenk: added to hold annotations for method getAnnotations()
+ private IAnnotationBinding[] annotations;
+
+ /*
+ * @see IBinding#getName()
+ */
+ public String getName()
+ {
+ if (_name == null)
+ {
+ _name = new String(_binding.readableName());
+ }
+
+ return _name;
+ }
+
+ /*
+ * @see IMethodMappingBinding#getDeclaringRoleClass()
+ */
+ public ITypeBinding getDeclaringRoleClass()
+ {
+ if (_declaringClass == null)
+ {
+ _declaringClass = _resolver.getTypeBinding(_binding._declaringRoleClass);
+ }
+
+ return _declaringClass;
+ }
+
+ /*
+ * @see IMethodMappingBinding#getReferencedBaseClass()
+ */
+ public ITypeBinding getReferencedBaseClass()
+ {
+ if (_baseClass == null)
+ {
+ _baseClass = _resolver.getTypeBinding(_binding._declaringRoleClass.baseclass());
+ //mkr: This is a workaround because _binding.referencedBaseClass is null
+ // _baseClass = _resolver.getTypeBinding(_binding._referencedBaseClass);
+ }
+
+ return _baseClass;
+ }
+
+ /*
+ * @see IMethodMappingBinding#getRoleMethod()
+ */
+ public IMethodBinding getRoleMethod()
+ {
+ if (_roleMethod == null)
+ {
+ _roleMethod = _resolver.getMethodBinding(_binding._roleMethodBinding);
+ }
+
+ return _roleMethod;
+ }
+
+ /*
+ * @see IMethodMappingBinding#getBaseMethods()
+ */
+ public IMethodBinding[] getBaseMethods()
+ {
+ if (_baseMethods == null)
+ {
+ MethodBinding[] methodBindings = this._binding._baseMethods;
+ if (methodBindings == null)
+ return new IMethodBinding[0];
+ this._baseMethods = new IMethodBinding[methodBindings.length];
+ for (int i = 0; i < methodBindings.length; i++)
+ this._baseMethods[i] = _resolver.getMethodBinding(methodBindings[i]);
+ }
+
+ return _baseMethods;
+ }
+
+ public String[] getBaseArgumentNames() {
+ MethodBinding[] methodBindings = this._binding._baseMethods;
+ if (methodBindings != null && methodBindings.length > 0)
+ {
+ String[] result = new String[methodBindings[0].parameters.length];
+ AbstractMethodDeclaration methodDecl = methodBindings[0].sourceMethod();
+ if (methodDecl != null) {
+ Argument[] args = methodDecl.arguments;
+ if (args != null) {
+ for (int i = 0; i < args.length; i++)
+ result[i] = String.valueOf(args[i].name);
+
+ return result;
+ }
+ }
+ for (int i = 0; i < result.length; i++)
+ result[i] = "arg"+i; //$NON-NLS-1$
+ return result;
+ }
+ return new String[0];
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind()
+ {
+ return IBinding.METHOD_MAPPING;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers()
+ {
+ if (_binding.type == org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding.CALLIN)
+ {
+ switch (_binding.callinModifier)
+ {
+ case TerminalTokens.TokenNamebefore:
+ return Modifier.OT_BEFORE_CALLIN;
+ case TerminalTokens.TokenNameafter:
+ return Modifier.OT_AFTER_CALLIN;
+ case TerminalTokens.TokenNamereplace:
+ return Modifier.OT_REPLACE_CALLIN;
+ default:
+ return 0;
+ }
+ }
+// else if (_binding.type == org.eclipse.jdt.internal.compiler.lookup.CallinCalloutBinding.CALLOUT)
+// {
+// // As for now, CalloutMappings have no modifier,
+// // since get and set are properties of FieldAccessSpec.
+// }
+
+ return 0;
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated()
+ {
+ return false;
+ }
+
+ /**
+ * @see IBinding#isSynthetic()
+ */
+ public boolean isSynthetic()
+ {
+ return false;
+ }
+
+ public boolean isCallin() {
+ return _binding.isCallin();
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(this.getDeclaringRoleClass().getKey());
+ buffer.append('/');
+ buffer.append(this.getName());
+ buffer.append(')');
+
+ return buffer.toString();
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return _binding.toString();
+ }
+
+ public IJavaElement getJavaElement() {
+ // SH: could not find a path that could possibly call this method [26.2.07]
+ return null;
+ }
+
+ public boolean isEqualTo(IBinding other) {
+ if (this == other)
+ return true;
+ if (other == null)
+ return false;
+
+ if (!(other instanceof MethodMappingBinding)) {
+ // consider a callout as equal to the role method it defines.
+ if (!this.isCallin() && this.getRoleMethod().isEqualTo(other))
+ return true;
+ return false;
+ }
+ // untested below [06.02.09]
+ org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding otherBinding = ((MethodMappingBinding) other)._binding;
+ if (BindingComparator.isEqual(this._binding, otherBinding))
+ return true;
+ return false;
+ }
+
+// (svenk: implement method from IBinding
+ public IAnnotationBinding[] getAnnotations() {
+ if (this.annotations != null) {
+ return this.annotations;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] annots = this._binding.getAnnotations();
+ int length = annots == null ? 0 : annots.length;
+ if (annots == null) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ IAnnotationBinding[] domInstances = new AnnotationBinding[length];
+ for (int i = 0; i < length; i++) {
+ final IAnnotationBinding annotationInstance = this._resolver.getAnnotationInstance(annots[i]);
+ if (annotationInstance == null) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ domInstances[i] = annotationInstance;
+ }
+ return this.annotations = domInstances;
+ }
+// svenk)
+
+ public boolean isRecovered() {
+ // method mappings are not (yet) recovered (cf. e.g., DefaultBindingResolver.getVariableBinding())
+ return false;
+ }
+
+
+
+ public InferenceKind getInferenceKind() {
+ if (this._binding != null)
+ return this._binding.inferred;
+ return InferenceKind.NONE;
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingElement.java
new file mode 100644
index 000000000..fa1543bf7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodMappingElement.java
@@ -0,0 +1,162 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: MethodMappingElement.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * NEW for OTDT
+ *
+ * Abstract base class of all AST nodes that represent elements for
+ * method mapping like
+ * "void setValue(Integer i) -> set int val" .
+ *
+ * MethodSpec, e.g. "void setValue(Integer i)"
+ * FieldAccessSpec, e.g. "set int val"
+ *
+ * @author jsv
+ * @version $Id: MethodMappingElement.java 23416 2010-02-03 19:59:31Z stephan $
+ */
+public abstract class MethodMappingElement extends ASTNode {
+
+ /**
+ * Creates a new AST node for an expression owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodMappingElement(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * The signature flag.
+ * True if MethodMappingElement have a signature
+ */
+ private boolean _hasSignature = false;
+
+ /**
+ * The element name; lazily initialized; defaults to an unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName _name = null;
+
+ /**
+ * Returns structural property descriptor for the "signature" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract SimplePropertyDescriptor internalSignatureProperty();
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalNameProperty();
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "signature" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final SimplePropertyDescriptor internalSignaturePropertyFactory(Class nodeClass) {
+ return new SimplePropertyDescriptor(nodeClass, "signature", boolean.class, MANDATORY); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "name" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the signature flag
+ */
+ public boolean hasSignature()
+ {
+ return _hasSignature;
+ }
+
+ /**
+ * Sets the signature flag.
+ */
+ public void setSignatureFlag(boolean hasSignature)
+ {
+ SimplePropertyDescriptor p = internalSignatureProperty();
+ preValueChange(p);
+ this._hasSignature = hasSignature;
+ postValueChange(p);
+ }
+
+ /**
+ * Returns the name of the MethodMappingElement
+ *
+ * @return the method name node
+ */
+ public SimpleName getName()
+ {
+ if (this._name == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this._name == null)
+ {
+ preLazyInit();
+ this._name = new SimpleName(this.ast);
+ postLazyInit(this._name, internalNameProperty());
+ }
+ }
+ }
+ return this._name;
+ }
+
+ /**
+ * Sets the name of the MethodMappingElement
+ *
+ * @param newName the new element name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName newName)
+ {
+ if (newName == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this._name;
+ preReplaceChild(oldChild, newName, internalNameProperty());
+ this._name = newName;
+ postReplaceChild(oldChild, newName, internalNameProperty());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java
new file mode 100644
index 000000000..c174784ec
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRef.java
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a method or constructor reference within a doc comment
+ * ({@link Javadoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to method and constructor members.
+ * <pre>
+ * MethodRef:
+ * [ Name ] <b>#</b> Identifier
+ * <b>(</b> [ MethodRefParameter | { <b>,</b> MethodRefParameter } ] <b>)</b>
+ * </pre>
+ *
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodRef extends ASTNode implements IDocElement {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(MethodRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MethodRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "parameters" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodRef.class, "parameters", MethodRefParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(MethodRef.class, properyList);
+ addProperty(QUALIFIER_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(PARAMETERS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; <code>null</code> for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal Java method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The parameter declarations
+ * (element type: <code>MethodRefParameter</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList parameters =
+ new ASTNode.NodeList(PARAMETERS_PROPERTY);
+
+
+ /**
+ * Creates a new AST node for a method reference owned by the given
+ * AST. By default, the method reference is for a method with an
+ * unspecified, but legal, name; no qualifier; and an empty parameter
+ * list.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodRef(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == PARAMETERS_PROPERTY) {
+ return parameters();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return METHOD_REF;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MethodRef result = new MethodRef(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ result.parameters().addAll(
+ ASTNode.copySubtrees(target, parameters()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.parameters);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this method reference, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this method reference.
+ *
+ * @param name the qualifier name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the referenced method or constructor.
+ *
+ * @return the method or constructor name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the referenced method or constructor to the
+ * given name.
+ *
+ * @param name the new method or constructor name node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the name is <code>null</code></li>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of method parameter references for this
+ * method reference.
+ *
+ * @return the live list of method parameter references
+ * (element type: <code>MethodRefParameter</code>)
+ */
+ public List parameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by
+ * this method reference.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveReference(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + this.parameters.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java
new file mode 100644
index 000000000..3e8c2ee09
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodRefParameter.java
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a parameter within a method reference ({@link MethodRef}).
+ * These nodes only occur within doc comments ({@link Javadoc}).
+ * For JLS2:
+ * <pre>
+ * MethodRefParameter:
+ * Type [ Identifier ]
+ * </pre>
+ * For JLS3, the variable arity indicator was added:
+ * <pre>
+ * MethodRefParameter:
+ * Type [ <b>...</b> ] [ Identifier ]
+ * </pre>
+ * <p>
+ * Note: The 1.5 spec for the Javadoc tool does not mention the possibility
+ * of a variable arity indicator in method references. However, the 1.5
+ * Javadoc tool itself does indeed support it. Since it makes sense to have
+ * a way to explicitly refer to variable arity methods, it seems more likely
+ * that the Javadoc spec is wrong in this case.
+ * </p>
+ *
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodRefParameter extends ASTNode {
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(MethodRefParameter.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "varargs" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final SimplePropertyDescriptor VARARGS_PROPERTY =
+ new SimplePropertyDescriptor(MethodRefParameter.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MethodRefParameter.class, "name", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(MethodRefParameter.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(3);
+ createPropertyList(MethodRefParameter.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(VARARGS_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Indicates the last parameter of a variable arity method;
+ * defaults to false.
+ *
+ * @since 3.1
+ */
+ private boolean variableArity = false;
+
+ /**
+ * The parameter name, or <code>null</code> if none; none by
+ * default.
+ */
+ private SimpleName optionalParameterName = null;
+
+ /**
+ * Creates a new AST node for a method referenece parameter owned by the given
+ * AST. By default, the node has an unspecified (but legal) type,
+ * not variable arity, and no parameter name.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodRefParameter(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == VARARGS_PROPERTY) {
+ if (get) {
+ return isVarargs();
+ } else {
+ setVarargs(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return METHOD_REF_PARAMETER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MethodRefParameter result = new MethodRefParameter(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setType((Type) ASTNode.copySubtree(target, getType()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setVarargs(isVarargs());
+ }
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the paramter type.
+ *
+ * @return the parameter type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the paramter type to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the type is <code>null</code></li>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns whether this method reference parameter is for
+ * the last parameter of a variable arity method (added in JLS3 API).
+ * <p>
+ * Note that the binding for the type <code>Foo</code>in the vararg method
+ * reference <code>#fun(Foo...)</code> is always for the type as
+ * written; i.e., the type binding for <code>Foo</code>. However, if you
+ * navigate from the MethodRef to its method binding to the
+ * type binding for its last parameter, the type binding for the vararg
+ * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
+ * the way vararg methods get compiled.
+ * </p>
+ *
+ * @return <code>true</code> if this is a variable arity parameter,
+ * and <code>false</code> otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public boolean isVarargs() {
+ unsupportedIn2();
+ return this.variableArity;
+ }
+
+ /**
+ * Sets whether this method reference parameter is for the last parameter of
+ * a variable arity method (added in JLS3 API).
+ *
+ * @param variableArity <code>true</code> if this is a variable arity
+ * parameter, and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public void setVarargs(boolean variableArity) {
+ unsupportedIn2();
+ preValueChange(VARARGS_PROPERTY);
+ this.variableArity = variableArity;
+ postValueChange(VARARGS_PROPERTY);
+ }
+
+ /**
+ * Returns the parameter name, or <code>null</code> if there is none.
+ *
+ * @return the parameter name node, or <code>null</code> if there is none
+ */
+ public SimpleName getName() {
+ return this.optionalParameterName;
+ }
+
+ /**
+ * Sets or clears the parameter name.
+ *
+ * @param name the parameter name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ ASTNode oldChild = this.optionalParameterName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.optionalParameterName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 5;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.optionalParameterName == null ? 0 : getName().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodSpec.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodSpec.java
new file mode 100644
index 000000000..00131893c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodSpec.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT, built in analogy to MethodDeclaration.
+ *
+ * Represents DOM-ASTNode for callout binding to a method of the corresponding
+ * base class, which has to handle code
+ * from e.g. :
+ * baseMethod
+ * to e.g. :
+ * String roleGetString(int b, String str)
+ *
+ * This class has following properties:
+ * parameters,
+ * returnType,
+ * name,
+ * signature
+ *
+ * This AST node has no modifier.
+ *
+ * This node can be used in CalloutMethodDeclaration and
+ * CallinMappingDeclaration
+ *
+ * @author jsv
+ */
+public class MethodSpec extends MethodMappingElement
+{
+ /**
+ * The "signature" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor SIGNATURE_PROPERTY =
+ internalSignaturePropertyFactory(MethodSpec.class);
+
+ /**
+ * The "covariantReturnType" property, flagging if "+" has been specified in the source.
+ * @since OTDT 1.1.3
+ */
+ public static final SimplePropertyDescriptor COVARIANT_RETURN_PROPERTY =
+ new SimplePropertyDescriptor(MethodSpec.class, "covariantReturn", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(MethodSpec.class);
+
+ /**
+ * The "returnType" structural property of this node type (JLS2 API only).
+ */
+ // TODO (jeem) When JLS3 support is complete (post 3.0) - deprecated Replaced by {@link #RETURN_TYPE2_PROPERTY} in the JLS3 API.
+ public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(MethodSpec.class, "returnType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "returnType2" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY =
+ new ChildPropertyDescriptor(MethodSpec.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeParameters" structural property of this node type (added in JLS3 API).
+ * @since OTDT 1.1.3
+ */
+ public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodSpec.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "parameters" structural property of this node type).
+ */
+ public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(MethodSpec.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+
+ static
+ {
+ List propertyList = new ArrayList(6);
+ createPropertyList(MethodSpec.class, propertyList);
+ addProperty(RETURN_TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(COVARIANT_RETURN_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(7);
+ createPropertyList(MethodSpec.class, propertyList);
+ addProperty(RETURN_TYPE2_PROPERTY, propertyList);
+ addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(SIGNATURE_PROPERTY, propertyList);
+ addProperty(COVARIANT_RETURN_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The parameter declarations
+ * (element type: <code>SingleVariableDeclaration</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList parameters =
+ new ASTNode.NodeList(PARAMETERS_PROPERTY);
+
+ /**
+ * The return type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type returnType = null;
+
+ /**
+ * Indicated whether the return type has been initialized.
+ * @since 3.1
+ */
+ private boolean returnType2Initialized = false;
+
+ /**
+ * The type paramters (element type: <code>TypeParameter</code>).
+ * (see constructor).
+ * @since OTDT 1.1.3
+ */
+ private ASTNode.NodeList typeParameters = null;
+
+ /**
+ * Whether the return type was specified with "+" to match covariant return types, too.
+ * @since OTDT 1.1.3
+ */
+ private boolean _hasCovariantReturn;
+
+ /**
+ * Creates a new AST node for a method spec declaration owned
+ * by the given AST. By default, the declaration is for a method spec
+ * of an unspecified, but legal, name; no modifiers; no javadoc; no type
+ * parameters; void return type; no parameters; no array dimensions after
+ * the parameters; no thrown exceptions; and no body (as opposed to an
+ * empty body).
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ MethodSpec(AST ast)
+ {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3)
+ this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+ }
+
+ /**
+ * Returns the covariantReturn flag
+ * @since OTDT 1.1.3
+ */
+ public boolean hasCovariantReturn() {
+ return _hasCovariantReturn;
+ }
+
+ /**
+ * Sets the covariantReturn flag.
+ * @since OTDT 1.1.3
+ */
+ public void setCovariantReturnFlag(boolean hasCovariantReturn)
+ {
+ preValueChange(COVARIANT_RETURN_PROPERTY);
+ this._hasCovariantReturn = hasCovariantReturn;
+ postValueChange(COVARIANT_RETURN_PROPERTY);
+ }
+
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)
+ {
+ if (property == SIGNATURE_PROPERTY)
+ {
+ if (get) {
+ return hasSignature();
+ } else {
+ setSignatureFlag(value);
+ return false;
+ }
+ }
+ if (property == COVARIANT_RETURN_PROPERTY)
+ {
+ if (get) {
+ return hasCovariantReturn();
+ } else {
+ setCovariantReturnFlag(value);
+ return false;
+ }
+ }
+
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == NAME_PROPERTY)
+ {
+ if (get)
+ {
+ return getName();
+ }
+ else
+ {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == RETURN_TYPE_PROPERTY)
+ {
+ if (get)
+ {
+ return getReturnType();
+ }
+ else
+ {
+ setReturnType((Type) child);
+ return null;
+ }
+ }
+ if(property == RETURN_TYPE2_PROPERTY) {
+ if(get)
+ return getReturnType2();
+ else {
+ setReturnType2((Type) child);
+ return null;
+ }
+ }
+
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == TYPE_PARAMETERS_PROPERTY) {
+ return typeParameters();
+ }
+ if (property == PARAMETERS_PROPERTY) {
+ return parameters();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+
+ final ChildListPropertyDescriptor internalModifiers2Property()
+ {
+ return null;
+ }
+
+ SimplePropertyDescriptor internalSignatureProperty() {
+ return SIGNATURE_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ final int getNodeType0()
+ {
+ return METHOD_SPEC;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ MethodSpec result = new MethodSpec(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel == AST.JLS2)
+ {
+ result.setReturnType(
+ (Type) ASTNode.copySubtree(target, getReturnType()));
+ }
+ if (this.ast.apiLevel >= AST.JLS3)
+ {
+ result.setReturnType2(
+ (Type) ASTNode.copySubtree(target, getReturnType2()));
+ result.typeParameters().addAll(
+ ASTNode.copySubtrees(target, typeParameters()));
+ }
+ result.setName((SimpleName) getName().clone(target));
+ result.parameters().addAll(
+ ASTNode.copySubtrees(target, parameters()));
+ result.setSignatureFlag(this.hasSignature());
+ result.setCovariantReturnFlag(this.hasCovariantReturn());
+ return result;
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel == AST.JLS2)
+ {
+ acceptChild(visitor, getReturnType());
+ }
+ else
+ {
+// acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getReturnType2());
+ }
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.typeParameters);
+ acceptChildren(visitor, this.parameters);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of method parameter declarations for this
+ * method spec.
+ *
+ * @return the live list of method parameter declarations
+ * (element type: <code>SingleVariableDeclaration</code>)
+ */
+ public List parameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Returns the live ordered list of type parameters of this method
+ * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
+ *
+ * @return the live list of type parameters
+ * (element type: <code>TypeParameter</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since OTDT 1.1.3
+ */
+ public List typeParameters() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeParameters == null) {
+ unsupportedIn2();
+ }
+ return this.typeParameters;
+ }
+
+ public IMethodBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /**
+ * Returns the return type of the method declared in this method spec,
+ * exclusive of any extra array dimensions (JLS2 API only).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available.
+ * </p>
+ *
+ * @return the return type, possibly the void primitive type
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ */
+ // TODO (jeem) When JLS3 support is complete (post 3.0) - deprecated In the JLS3 API, this method is replaced by <code>getReturnType2</code>, which may return <code>null</code>.
+ public Type getReturnType()
+ {
+ supportedOnlyIn2();
+ if (this.returnType == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this.returnType == null)
+ {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method spec
+ * declaration to the given type, exclusive of any extra array dimensions
+ * (JLS2 API only). This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * </p>
+ *
+ * @param type the new return type, possibly the void primitive type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ */
+ // TODO (jeem) When JLS3 support is complete (post 3.0) - deprecated In the JLS3 API, this method is replaced by <code>setReturnType2</code>, which accepts <code>null</code>.
+ public void setReturnType(Type type)
+ {
+ supportedOnlyIn2();
+ if (type == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the return type of the method declared in this method
+ * declaration, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although, if present, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available. In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ * </p>
+ *
+ * @return the return type, possibly the void primitive type,
+ * or <code>null</code> if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public Type getReturnType2() {
+ unsupportedIn2();
+ if (this.returnType == null && !this.returnType2Initialized) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.returnType == null && !this.returnType2Initialized) {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ this.returnType2Initialized = true;
+ postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method declaration
+ * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ * <p>
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ * </p>
+ *
+ * @param type the new return type, possibly the void primitive type,
+ * or <code>null</code> if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @since 3.1
+ */
+ public void setReturnType2(Type type) {
+ unsupportedIn2();
+ this.returnType2Initialized = true;
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ }
+
+
+ int memSize()
+ {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ int treeSize()
+ {
+ return memSize()
+ + (this.getName() == null ? 0 : getName().treeSize())
+ + (this.returnType == null ? 0 : this.returnType.treeSize())
+ + this.parameters.listSize()
+ + this.typeParameters.listSize();
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
new file mode 100644
index 000000000..2d203b305
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
@@ -0,0 +1,892 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: Modifier.java 19895 2009-04-15 13:52:23Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Modifier node.
+ * <pre>
+ * Modifier:
+ * <b>public</b>
+ * <b>protected</b>
+ * <b>private</b>
+ * <b>static</b>
+ * <b>abstract</b>
+ * <b>final</b>
+ * <b>native</b>
+ * <b>synchronized</b>
+ * <b>transient</b>
+ * <b>volatile</b>
+ * <b>strictfp</b>
+ * </pre>
+ * <p>
+ * The numeric values of these flags match the ones for class
+ * files as described in the Java Virtual Machine Specification.
+ * Note that Java model class {@link org.eclipse.jdt.core.Flags} also
+ * provides the same constants as this class.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class Modifier extends ASTNode implements IExtendedModifier {
+
+ /**
+ * Modifier keywords (typesafe enumeration).
+ * @since 3.0
+ */
+ public static class ModifierKeyword {
+
+ /** "abstract" modifier with flag value {@link Modifier#ABSTRACT}. */
+ public static final ModifierKeyword ABSTRACT_KEYWORD = new ModifierKeyword("abstract", ABSTRACT);//$NON-NLS-1$
+
+ /** "final" modifier with flag value {@link Modifier#FINAL}. */
+ public static final ModifierKeyword FINAL_KEYWORD = new ModifierKeyword("final", FINAL);//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+ private static final Map KEYWORDS;
+
+ /** "native" modifier with flag value {@link Modifier#NATIVE}. */
+ public static final ModifierKeyword NATIVE_KEYWORD = new ModifierKeyword("native", NATIVE);//$NON-NLS-1$
+
+ /** "private" modifier with flag value {@link Modifier#PRIVATE}. */
+ public static final ModifierKeyword PRIVATE_KEYWORD = new ModifierKeyword("private", PRIVATE);//$NON-NLS-1$
+
+ /** "protected" modifier with flag value {@link Modifier#PROTECTED}. */
+ public static final ModifierKeyword PROTECTED_KEYWORD = new ModifierKeyword("protected", PROTECTED);//$NON-NLS-1$
+
+ /** "public" modifier with flag value {@link Modifier#PUBLIC}. */
+ public static final ModifierKeyword PUBLIC_KEYWORD = new ModifierKeyword("public", PUBLIC);//$NON-NLS-1$
+
+ /** "static" modifier with flag value {@link Modifier#STATIC}. */
+ public static final ModifierKeyword STATIC_KEYWORD = new ModifierKeyword("static", STATIC);//$NON-NLS-1$
+
+ /** "strictfp" modifier with flag value {@link Modifier#STRICTFP}. */
+ public static final ModifierKeyword STRICTFP_KEYWORD = new ModifierKeyword("strictfp", STRICTFP);//$NON-NLS-1$
+
+ /** "synchronized" modifier with flag value {@link Modifier#SYNCHRONIZED}. */
+ public static final ModifierKeyword SYNCHRONIZED_KEYWORD = new ModifierKeyword("synchronized", SYNCHRONIZED);//$NON-NLS-1$
+
+ /** "transient" modifier with flag value {@link Modifier#TRANSIENT}. */
+ public static final ModifierKeyword TRANSIENT_KEYWORD = new ModifierKeyword("transient", TRANSIENT);//$NON-NLS-1$
+
+ /** "volatile" modifier with flag value {@link Modifier#VOLATILE}. */
+ public static final ModifierKeyword VOLATILE_KEYWORD = new ModifierKeyword("volatile", VOLATILE);//$NON-NLS-1$
+
+//{ObjectTeams: OT-specific callin modifier keywords
+ public static final ModifierKeyword AFTER_KEYWORD = new ModifierKeyword("after", OT_AFTER_CALLIN);//$NON-NLS-1$
+
+ public static final ModifierKeyword BEFORE_KEYWORD = new ModifierKeyword("before", OT_BEFORE_CALLIN);//$NON-NLS-1$
+
+ public static final ModifierKeyword REPLACE_KEYWORD = new ModifierKeyword("replace", OT_REPLACE_CALLIN);//$NON-NLS-1$
+
+ /** This keyword represents a missing callin-modifier in a callin binding. */
+ public static final ModifierKeyword MISSING_KEYWORD = new ModifierKeyword("<missing modifier>", OT_MISSING_MODIFIER);//$NON-NLS-1$
+
+ /** "get" modifier with flag value {@link Modifier#OT_GET_CALLOUT}. */
+ public static final ModifierKeyword GET_KEYWORD = new ModifierKeyword("get", OT_GET_CALLOUT);//$NON-NLS-1$
+
+ /** "set" modifier with flag value {@link Modifier#OT_SET_CALLOUT}. */
+ public static final ModifierKeyword SET_KEYWORD = new ModifierKeyword("set", OT_SET_CALLOUT);//$NON-NLS-1$
+
+ /** "team" modifier with flag value {@link Modifier#OT_TEAM}. */
+ public static final ModifierKeyword TEAM_KEYWORD = new ModifierKeyword("team", OT_TEAM);//$NON-NLS-1$
+
+ /** "callin" modifier with flag value {@link Modifier#OT_CALLIN}. */
+ public static final ModifierKeyword CALLIN_KEYWORD = new ModifierKeyword("callin", OT_CALLIN);//$NON-NLS-1$
+//gbr}
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+
+ static {
+ KEYWORDS = new HashMap(20);
+ ModifierKeyword[] ops = {
+ PUBLIC_KEYWORD,
+ PROTECTED_KEYWORD,
+ PRIVATE_KEYWORD,
+ STATIC_KEYWORD,
+ ABSTRACT_KEYWORD,
+ FINAL_KEYWORD,
+ NATIVE_KEYWORD,
+ SYNCHRONIZED_KEYWORD,
+ TRANSIENT_KEYWORD,
+ VOLATILE_KEYWORD,
+ STRICTFP_KEYWORD,
+//{ObjectTeams: added OT-specific keywords to array
+ AFTER_KEYWORD,
+ BEFORE_KEYWORD,
+ REPLACE_KEYWORD,
+ MISSING_KEYWORD,
+ GET_KEYWORD,
+ SET_KEYWORD,
+ TEAM_KEYWORD,
+ CALLIN_KEYWORD
+//gbr}
+ };
+ for (int i = 0; i < ops.length; i++) {
+ KEYWORDS.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the modifier corresponding to the given single-bit flag value,
+ * or <code>null</code> if none or if more than one bit is set.
+ * <p>
+ * <code>fromFlagValue</code> is the converse of <code>toFlagValue</code>:
+ * that is, <code>ModifierKind.fromFlagValue(k.toFlagValue()) == k</code> for
+ * all modifier keywords <code>k</code>.
+ * </p>
+ *
+ * @param flagValue the single-bit flag value for the modifier
+ * @return the modifier keyword, or <code>null</code> if none
+ * @see #toFlagValue()
+ */
+ public static ModifierKeyword fromFlagValue(int flagValue) {
+ for (Iterator it = KEYWORDS.values().iterator(); it.hasNext(); ) {
+ ModifierKeyword k = (ModifierKeyword) it.next();
+ if (k.toFlagValue() == flagValue) {
+ return k;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the modifier corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toKeyword</code> is the converse of <code>toString</code>:
+ * that is, <code>ModifierKind.toKeyword(k.toString()) == k</code> for
+ * all modifier keywords <code>k</code>.
+ * </p>
+ *
+ * @param keyword the lowercase string name for the modifier
+ * @return the modifier keyword, or <code>null</code> if none
+ * @see #toString()
+ */
+ public static ModifierKeyword toKeyword(String keyword) {
+ return (ModifierKeyword) KEYWORDS.get(keyword);
+ }
+
+ /**
+ * The flag value for the modifier.
+ */
+ private int flagValue;
+
+ /**
+ * The keyword modifier string.
+ */
+ private String keyword;
+
+ /**
+ * Creates a new modifier with the given keyword.
+ * <p>
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard modifiers.
+ * </p>
+ *
+ * @param keyword the character sequence for the modifier
+ * @param flagValue flag value as described in the Java Virtual Machine Specification
+ */
+ private ModifierKeyword(String keyword, int flagValue) {
+ this.keyword = keyword;
+ this.flagValue = flagValue;
+ }
+
+ /**
+ * Returns the modifier flag value corresponding to this modifier keyword.
+ * These flag values are as described in the Java Virtual Machine Specification.
+ *
+ * @return one of the <code>Modifier</code> constants
+ * @see #fromFlagValue(int)
+ */
+ public int toFlagValue() {
+ return this.flagValue;
+ }
+
+ /**
+ * Returns the keyword for the modifier.
+ *
+ * @return the keyword for the modifier
+ * @see #toKeyword(String)
+ */
+ public String toString() {
+ return this.keyword;
+ }
+ }
+
+ /**
+ * "abstract" modifier constant (bit mask).
+ * Applicable to types and methods.
+ * @since 2.0
+ */
+ public static final int ABSTRACT = 0x0400;
+
+ /**
+ * "final" modifier constant (bit mask).
+ * Applicable to types, methods, fields, and variables.
+ * @since 2.0
+ */
+ public static final int FINAL = 0x0010;
+
+ /**
+ * The "keyword" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor KEYWORD_PROPERTY =
+ new SimplePropertyDescriptor(Modifier.class, "keyword", Modifier.ModifierKeyword.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * "native" modifier constant (bit mask).
+ * Applicable only to methods.
+ * @since 2.0
+ */
+ public static final int NATIVE = 0x0100;
+
+ /**
+ * Modifier constant (bit mask, value 0) indicating no modifiers.
+ * @since 2.0
+ */
+ public static final int NONE = 0x0000;
+
+ /**
+ * "private" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ * @since 2.0
+ */
+ public static final int PRIVATE = 0x0002;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ /**
+ * "protected" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ * @since 2.0
+ */
+ public static final int PROTECTED = 0x0004;
+
+ /**
+ * "public" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ * @since 2.0
+ */
+ public static final int PUBLIC = 0x0001;
+
+ /**
+ * "static" modifier constant (bit mask).
+ * Applicable to types, methods, fields, and initializers.
+ * @since 2.0
+ */
+ public static final int STATIC = 0x0008;
+
+ /**
+ * "strictfp" modifier constant (bit mask).
+ * Applicable to types and methods.
+ * @since 2.0
+ */
+ public static final int STRICTFP = 0x0800;
+
+ /**
+ * "synchronized" modifier constant (bit mask).
+ * Applicable only to methods.
+ * @since 2.0
+ */
+ public static final int SYNCHRONIZED = 0x0020;
+
+ /**
+ * "transient" modifier constant (bit mask).
+ * Applicable only to fields.
+ * @since 2.0
+ */
+ public static final int TRANSIENT = 0x0080;
+
+ /**
+ * "volatile" modifier constant (bit mask).
+ * Applicable only to fields.
+ * @since 2.0
+ */
+ public static final int VOLATILE = 0x0040;
+
+ /**
+ * "callin" OT-specific modifier constant (bit mask).
+ * Applicable to methods only ("callin" modifier).
+ */
+ public static final int OT_CALLIN = 0x80000000; // keep in sync with ExtraCompilerModifiers!
+
+ /**
+ * "team" OT-specific modifier constant (bit mask).
+ * Applicable to types and methods.
+ */
+ public static final int OT_TEAM = 0x8000; // bit 16
+
+//{ObjectTeams: OT-specific callin modifier constants
+ // Note(SH): please note, that these modifiers differ from all others in this list,
+ // since they cannot be applied a class, a method, nor a field.
+ // I find it misleading to place them in this file alltogether.
+
+ /**
+ * OT-specific modifier constant.
+ * Applicable only to CallinMappingDeclaration.
+ */
+ public static final int OT_REPLACE_CALLIN = 0x1000; // bit 13
+
+ /** Used when no callin modifier is present. */
+ public static final int OT_MISSING_MODIFIER = 0x2000; // bit 14
+
+ /**
+ * OT-specific modifier constant.
+ * Applicable only to CallinMappingDeclaration.
+ */
+ public static final int OT_BEFORE_CALLIN = 0x4000; // bit 15
+
+ /**
+ * OT-specific modifier constant.
+ * Applicable only to CallinMappingDeclaration.
+ */
+ public static final int OT_AFTER_CALLIN = 0x10000; // bit 17
+
+ /**
+ * OT-specific modifier constant.
+ * Applicable only to callout to field (FieldAccessSpec).
+ */
+ public static final int OT_GET_CALLOUT = 0x20000; // bit 18
+
+ /**
+ * OT-specific modifier constant.
+ * Applicable only to callout to field (FieldAccessSpec).
+ */
+ public static final int OT_SET_CALLOUT = 0x40000; // bit 19
+
+//gbr}
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(Modifier.class, properyList);
+ addProperty(KEYWORD_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns whether the given flags includes the "abstract" modifier.
+ * Applicable to types and methods.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>ABSTRACT</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isAbstract(int flags) {
+ return (flags & ABSTRACT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "final" modifier.
+ * Applicable to types, methods, fields, and variables.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>FINAL</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isFinal(int flags) {
+ return (flags & FINAL) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "native" modifier.
+ * Applicable only to methods.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>NATIVE</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isNative(int flags) {
+ return (flags & NATIVE) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "private" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>PRIVATE</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isPrivate(int flags) {
+ return (flags & PRIVATE) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "protected" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>PROTECTED</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isProtected(int flags) {
+ return (flags & PROTECTED) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "public" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>PUBLIC</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isPublic(int flags) {
+ return (flags & PUBLIC) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "static" modifier.
+ * Applicable to types, methods, fields, and initializers.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>STATIC</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isStatic(int flags) {
+ return (flags & STATIC) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "strictfp" modifier.
+ * Applicable to types and methods.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>STRICTFP</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isStrictfp(int flags) {
+ return (flags & STRICTFP) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "synchronized" modifier.
+ * Applicable only to methods.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>SYNCHRONIZED</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isSynchronized(int flags) {
+ return (flags & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "transient" modifier.
+ * Applicable only to fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>TRANSIENT</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isTransient(int flags) {
+ return (flags & TRANSIENT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "volatile" modifier.
+ * Applicable only to fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>VOLATILE</code> bit is
+ * set, and <code>false</code> otherwise
+ * @since 2.0
+ */
+ public static boolean isVolatile(int flags) {
+ return (flags & VOLATILE) != 0;
+ }
+
+//{ObjectTeams: OT-specific check methods
+ /**
+ * Returns whether the given flags contain the "replace" modifier.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>REPLACE</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isReplace(int flags)
+ {
+ return (flags & OT_REPLACE_CALLIN) != 0;
+ }
+
+ /**
+ * Returns whether the given flags contain the "before" modifier.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>BEFORE</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isBefore(int flags)
+ {
+ return (flags & OT_BEFORE_CALLIN) != 0;
+ }
+
+ /**
+ * Returns whether the given flags contain the "after" modifier.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>AFTER</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isAfter(int flags)
+ {
+ return (flags & OT_AFTER_CALLIN) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "get" modifier.
+ * Applicable base fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>GET</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isGet(int flags)
+ {
+ return (flags & OT_GET_CALLOUT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "set" modifier.
+ * Applicable base fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>SET</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isSet(int flags)
+ {
+ return (flags & OT_SET_CALLOUT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "team" modifier.
+ * Applicable base fields.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>SET</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isTeam(int flags)
+ {
+ return (flags & OT_TEAM) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "callin" modifier.
+ * Applicable to methods only.
+ *
+ * @param flags the modifier flags
+ * @return <code>true</code> if the <code>AccCallin</code> bit is
+ * set, and <code>false</code> otherwise
+ */
+ public static boolean isCallin(int flags)
+ {
+ return (flags & OT_CALLIN) != 0;
+ }
+
+//gbr}
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The modifier keyword; defaults to an unspecified modifier.
+ * @since 3.0
+ */
+ private ModifierKeyword modifierKeyword = ModifierKeyword.PUBLIC_KEYWORD;
+
+ /**
+ * Creates a new unparented modifier node owned by the given AST.
+ * By default, the node has unspecified (but legal) modifier.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ * @since 3.0
+ */
+ Modifier(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ ASTNode clone0(AST target) {
+ Modifier result = new Modifier(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setKeyword(getKeyword());
+ return result;
+ }
+
+ /**
+ * Returns the modifier keyword of this modifier node.
+ *
+ * @return the modifier keyword
+ * @since 3.0
+ */
+ public ModifierKeyword getKeyword() {
+ return this.modifierKeyword;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final int getNodeType0() {
+ return MODIFIER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == KEYWORD_PROPERTY) {
+ if (get) {
+ return getKeyword();
+ } else {
+ setKeyword((ModifierKeyword) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /**
+ * Answer true if the receiver is the abstract modifier, false otherwise.
+ *
+ * @return true if the receiver is the abstract modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isAbstract() {
+ return this.modifierKeyword == ModifierKeyword.ABSTRACT_KEYWORD;
+ }
+
+ /**
+ * @see IExtendedModifier#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ /**
+ * Answer true if the receiver is the final modifier, false otherwise.
+ *
+ * @return true if the receiver is the final modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isFinal() {
+ return this.modifierKeyword == ModifierKeyword.FINAL_KEYWORD;
+ }
+
+ /**
+ * @see IExtendedModifier#isModifier()
+ */
+ public boolean isModifier() {
+ return true;
+ }
+
+ /**
+ * Answer true if the receiver is the native modifier, false otherwise.
+ *
+ * @return true if the receiver is the native modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isNative() {
+ return this.modifierKeyword == ModifierKeyword.NATIVE_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the private modifier, false otherwise.
+ *
+ * @return true if the receiver is the private modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isPrivate() {
+ return this.modifierKeyword == ModifierKeyword.PRIVATE_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the protected modifier, false otherwise.
+ *
+ * @return true if the receiver is the protected modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isProtected() {
+ return this.modifierKeyword == ModifierKeyword.PROTECTED_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the public modifier, false otherwise.
+ *
+ * @return true if the receiver is the public modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isPublic() {
+ return this.modifierKeyword == ModifierKeyword.PUBLIC_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the static modifier, false otherwise.
+ *
+ * @return true if the receiver is the static modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isStatic() {
+ return this.modifierKeyword == ModifierKeyword.STATIC_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the strictfp modifier, false otherwise.
+ *
+ * @return true if the receiver is the strictfp modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isStrictfp() {
+ return this.modifierKeyword == ModifierKeyword.STRICTFP_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the synchronized modifier, false otherwise.
+ *
+ * @return true if the receiver is the synchronized modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isSynchronized() {
+ return this.modifierKeyword == ModifierKeyword.SYNCHRONIZED_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the transient modifier, false otherwise.
+ *
+ * @return true if the receiver is the transient modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isTransient() {
+ return this.modifierKeyword == ModifierKeyword.TRANSIENT_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the volatile modifier, false otherwise.
+ *
+ * @return true if the receiver is the volatile modifier, false otherwise
+ * @since 3.2
+ */
+ public boolean isVolatile() {
+ return this.modifierKeyword == ModifierKeyword.VOLATILE_KEYWORD;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ int memSize() {
+ // treat ModifierKeyword as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /**
+ * Sets the modifier keyword of this modifier node.
+ *
+ * @param modifierKeyord the modifier keyword
+ * @exception IllegalArgumentException if the argument is <code>null</code>
+ * @since 3.0
+ */
+ public void setKeyword(ModifierKeyword modifierKeyord) {
+ if (modifierKeyord == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(KEYWORD_PROPERTY);
+ this.modifierKeyword = modifierKeyord;
+ postValueChange(KEYWORD_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java
new file mode 100644
index 000000000..9e5de82b8
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent names.
+ * There are exactly two kinds of name: simple ones
+ * (<code>SimpleName</code>) and qualified ones (<code>QualifiedName</code>).
+ * <p>
+ * <pre>
+ * Name:
+ * SimpleName
+ * QualifiedName
+ * </pre>
+ * </p>
+ *
+ * @since 2.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class Name extends Expression implements IDocElement {
+
+ /**
+ * Approximate base size of an expression node instance in bytes,
+ * including object header and instance fields.
+ */
+ static final int BASE_NAME_NODE_SIZE = BASE_NODE_SIZE + 1 * 4;
+
+ /**
+ * This index represents the position inside a qualified name.
+ */
+ int index;
+
+ /**
+ * Creates a new AST node for a name owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Name(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this name is a simple name
+ * (<code>SimpleName</code>).
+ *
+ * @return <code>true</code> if this is a simple name, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isSimpleName() {
+ return (this instanceof SimpleName);
+ }
+
+ /**
+ * Returns whether this name is a qualified name
+ * (<code>QualifiedName</code>).
+ *
+ * @return <code>true</code> if this is a qualified name, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isQualifiedName() {
+ return (this instanceof QualifiedName);
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by this name.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveName(this);
+ }
+
+ /**
+ * Returns the standard dot-separated representation of this name.
+ * If the name is a simple name, the result is the name's identifier.
+ * If the name is a qualified name, the result is the name of the qualifier
+ * (as computed by this method) followed by "." followed by the name's
+ * identifier.
+ *
+ * @return the fully qualified name
+ * @since 3.0
+ */
+ public final String getFullyQualifiedName() {
+ if (isSimpleName()) {
+ // avoid creating garbage for common case
+ return ((SimpleName) this).getIdentifier();
+ } else {
+ StringBuffer buffer = new StringBuffer(50);
+ appendName(buffer);
+ return new String(buffer);
+ }
+ }
+
+ /**
+ * Appends the standard representation of this name to the given string
+ * buffer.
+ *
+ * @param buffer the buffer
+ * @since 3.0
+ */
+ abstract void appendName(StringBuffer buffer);
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeEventHandler.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeEventHandler.java
new file mode 100644
index 000000000..a0878837d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeEventHandler.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * A node event handler is an internal mechanism for receiving
+ * notification of changes to nodes in an AST.
+ * <p>
+ * The default implementation serves as the default event handler
+ * that does nothing. Internal subclasses do all the real work.
+ * </p>
+ *
+ * @see AST#getEventHandler()
+ */
+class NodeEventHandler {
+
+ /**
+ * Creates a node event handler.
+ */
+ NodeEventHandler() {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Reports that the given node is about to lose a child.
+ * The first half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be removed
+ * @param property the child or child list property descriptor
+ * @see #postRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("DEL1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just lose a child.
+ * The second half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the child that was removed; note that this node is unparented
+ * @param property the child or child list property descriptor
+ * @see #preRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("DEL2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to have a child replaced.
+ * The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be replaced
+ * @param newChild the replacement child; note that this node is unparented
+ * @param property the child or child list property descriptor
+ * @see #preReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("REP1 " + property);
+ }
+
+ /**
+ * Reports that the given node has had its child replaced. The second half
+ * of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the node that was replaced; note that this node is unparented
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ * @see #postReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("REP2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to gain a child.
+ * The first half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that to be modified
+ * @param child the node that is to be added as a child; note that this
+ * node is unparented; in the case of a child list property, the exact
+ * location of insertion is not supplied (but is known on the
+ * corresponding <code>postAddChildEvent</code> to
+ * follow)
+ * @param property the child or child list property descriptor
+ * @see #postAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("ADD1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just gained a child.
+ * The second half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the node that was added as a child
+ * @param property the child or child list property descriptor
+ * @see #preAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ * @since 3.0
+ */
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("ADD2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to change the value of a
+ * non-child property. The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node to be modified
+ * @param property the property descriptor
+ * @see #postValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+ * @since 3.0
+ */
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // do nothing
+ // System.out.println("MOD1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just changed the value of a
+ * non-child property. The second half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param property the property descriptor
+ * @see #preValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+ * @since 3.0
+ */
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // do nothing
+ // System.out.println("MOD2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to be cloned.
+ * The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node to be modified
+ * @see #postCloneNodeEvent(ASTNode, ASTNode)
+ * @since 3.0
+ */
+ void preCloneNodeEvent(ASTNode node) {
+ // do nothing
+ // System.out.println("CLONE1");
+ }
+
+ /**
+ * Reports that the given node has just been cloned.
+ * The second half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param clone the clone of <code>node</code>
+ * @see #preCloneNodeEvent(ASTNode)
+ * @since 3.0
+ */
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ // do nothing
+ // System.out.println("CLONE2");
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeFinder.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeFinder.java
new file mode 100644
index 000000000..2cbe00faa
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeFinder.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IBuffer;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.compiler.IScanner;
+import org.eclipse.jdt.core.compiler.ITerminalSymbols;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+
+/**
+ * For a given range, finds the covered node and the covering node.
+ *
+ * @since 3.5
+ */
+public final class NodeFinder {
+ /**
+ * This class defines the actual visitor that finds the node.
+ */
+ private static class NodeFinderVisitor extends ASTVisitor {
+ private int fStart;
+ private int fEnd;
+ private ASTNode fCoveringNode;
+ private ASTNode fCoveredNode;
+
+//{ObjectTeams: Do not descend into role files:
+ // The topmost type found during traversal
+ private TypeDeclaration topType= null;
+ public boolean visit(TypeDeclaration type) {
+ if (topType == null)
+ topType= type;
+ return super.visit(type);
+ }
+ public boolean visit(RoleTypeDeclaration roleType) {
+ if (this.topType != null && roleType.isRoleFile())
+ return false;
+ if (topType == null)
+ topType= roleType;
+ return super.visit(roleType);
+ }
+// SH}
+
+ NodeFinderVisitor(int offset, int length) {
+ super(true); // include Javadoc tags
+ this.fStart= offset;
+ this.fEnd= offset + length;
+ }
+
+ public boolean preVisit2(ASTNode node) {
+ int nodeStart= node.getStartPosition();
+ int nodeEnd= nodeStart + node.getLength();
+ if (nodeEnd < this.fStart || this.fEnd < nodeStart) {
+ return false;
+ }
+ if (nodeStart <= this.fStart && this.fEnd <= nodeEnd) {
+ this.fCoveringNode= node;
+ }
+ if (this.fStart <= nodeStart && nodeEnd <= this.fEnd) {
+ if (this.fCoveringNode == node) { // nodeStart == fStart && nodeEnd == fEnd
+ this.fCoveredNode= node;
+ return true; // look further for node with same length as parent
+ } else if (this.fCoveredNode == null) { // no better found
+ this.fCoveredNode= node;
+ }
+ return false;
+ }
+ return true;
+ }
+ /**
+ * Returns the covered node. If more than one nodes are covered by the selection, the
+ * returned node is first covered node found in a top-down traversal of the AST
+ * @return ASTNode
+ */
+ public ASTNode getCoveredNode() {
+ return this.fCoveredNode;
+ }
+
+ /**
+ * Returns the covering node. If more than one nodes are covering the selection, the
+ * returned node is last covering node found in a top-down traversal of the AST
+ * @return ASTNode
+ */
+ public ASTNode getCoveringNode() {
+ return this.fCoveringNode;
+ }
+ }
+ /**
+ * Maps a selection to a given ASTNode, where the selection is defined using a start and a length.
+ * The result node is determined as follows:
+ * <ul>
+ * <li>first the visitor tries to find a node with the exact <code>start</code> and <code>length</code></li>
+ * <li>if no such node exists then the node that encloses the range defined by
+ * <code>start</code> and <code>length</code> is returned.</li>
+ * <li>if the length is zero then also nodes are considered where the node's
+ * start or end position matches <code>start</code>.</li>
+ * <li>otherwise <code>null</code> is returned.</li>
+ * </ul>
+ *
+ * @param root the root node from which the search starts
+ * @param start the given start
+ * @param length the given length
+ *
+ * @return the found node
+ */
+ public static ASTNode perform(ASTNode root, int start, int length) {
+ NodeFinder finder = new NodeFinder(root, start, length);
+ ASTNode result= finder.getCoveredNode();
+ if (result == null || result.getStartPosition() != start || result.getLength() != length) {
+ return finder.getCoveringNode();
+ }
+ return result;
+ }
+
+ /**
+ * Maps a selection to a given ASTNode, where the selection is defined using a source range.
+ * It calls <code>perform(root, range.getOffset(), range.getLength())</code>.
+ *
+ * @return the result node
+ * @see #perform(ASTNode, int, int)
+ */
+ public static ASTNode perform(ASTNode root, ISourceRange range) {
+ return perform(root, range.getOffset(), range.getLength());
+ }
+
+ /**
+ * Maps a selection to a given ASTNode, where the selection is given by a start and a length.
+ * The result node is determined as follows:
+ * <ul>
+ * <li>first the visitor tries to find a node that is covered by <code>start</code> and
+ * <code>length</code> where either <code>start</code> and <code>length</code> exactly
+ * matches the node or where the text covered before and after the node only consists
+ * of white spaces or comments.</li>
+ * <li>if no such node exists then the node that encloses the range defined by
+ * <code>start</code> and <code>length</code> is returned.</li>
+ * <li>if the length is zero then also nodes are considered where the node's
+ * start or end position matches <code>start</code>.</li>
+ * <li>otherwise <code>null</code> is returned.</li>
+ * </ul>
+ *
+ * @param root the root node from which the search starts
+ * @param start the given start
+ * @param length the given length
+ * @param source the source of the compilation unit
+ *
+ * @return the result node
+ * @throws JavaModelException if an error occurs in the Java model
+ */
+ public static ASTNode perform(ASTNode root, int start, int length, ITypeRoot source) throws JavaModelException {
+ NodeFinder finder = new NodeFinder(root, start, length);
+ ASTNode result= finder.getCoveredNode();
+ if (result == null)
+ return null;
+ int nodeStart= result.getStartPosition();
+ if (start <= nodeStart && ((nodeStart + result.getLength()) <= (start + length))) {
+ IBuffer buffer= source.getBuffer();
+ if (buffer != null) {
+ IScanner scanner= ToolFactory.createScanner(false, false, false, false);
+ scanner.setSource(buffer.getText(start, length).toCharArray());
+ try {
+ int token= scanner.getNextToken();
+ if (token != ITerminalSymbols.TokenNameEOF) {
+ int tStart= scanner.getCurrentTokenStartPosition();
+ if (tStart == result.getStartPosition() - start) {
+ scanner.resetTo(tStart + result.getLength(), length - 1);
+ token= scanner.getNextToken();
+ if (token == ITerminalSymbols.TokenNameEOF)
+ return result;
+ }
+ }
+ } catch (InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+ return finder.getCoveringNode();
+ }
+ private ASTNode fCoveringNode;
+ private ASTNode fCoveredNode;
+
+ /**
+ * Instantiate a new node finder using the given root node, the given start and the given length.
+ *
+ * @param root the given root node
+ * @param start the given start
+ * @param length the given length
+ */
+ public NodeFinder(ASTNode root, int start, int length) {
+ NodeFinderVisitor nodeFinderVisitor = new NodeFinderVisitor(start, length);
+ root.accept(nodeFinderVisitor);
+ this.fCoveredNode = nodeFinderVisitor.getCoveredNode();
+ this.fCoveringNode = nodeFinderVisitor.getCoveringNode();
+ }
+ /**
+ * Returns the covered node. If more than one nodes are covered by the selection, the
+ * returned node is first covered node found in a top-down traversal of the AST.
+ *
+ * @return the covered node
+ */
+ public ASTNode getCoveredNode() {
+ return this.fCoveredNode;
+ }
+
+ /**
+ * Returns the covering node. If more than one nodes are covering the selection, the
+ * returned node is last covering node found in a top-down traversal of the AST.
+ *
+ * @return the covering node
+ */
+ public ASTNode getCoveringNode() {
+ return this.fCoveringNode;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java
new file mode 100644
index 000000000..1f070c411
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+class NodeSearcher extends ASTVisitor {
+ public org.eclipse.jdt.internal.compiler.ast.ASTNode found;
+ public TypeDeclaration enclosingType;
+ public int position;
+
+ NodeSearcher(int position) {
+ this.position = position;
+ }
+
+ public boolean visit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+
+ if (constructorDeclaration.declarationSourceStart <= this.position
+ && this.position <= constructorDeclaration.declarationSourceEnd) {
+ this.found = constructorDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ FieldDeclaration fieldDeclaration,
+ MethodScope scope) {
+ if (fieldDeclaration.declarationSourceStart <= this.position
+ && this.position <= fieldDeclaration.declarationSourceEnd) {
+ this.found = fieldDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ if (initializer.declarationSourceStart <= this.position
+ && this.position <= initializer.declarationSourceEnd) {
+ this.found = initializer;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ if (memberTypeDeclaration.declarationSourceStart <= this.position
+ && this.position <= memberTypeDeclaration.declarationSourceEnd) {
+ this.enclosingType = memberTypeDeclaration;
+ return true;
+
+ }
+ return false;
+ }
+
+ public boolean visit(
+ MethodDeclaration methodDeclaration,
+ ClassScope scope) {
+
+ if (methodDeclaration.declarationSourceStart <= this.position
+ && this.position <= methodDeclaration.declarationSourceEnd) {
+ this.found = methodDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ if (typeDeclaration.declarationSourceStart <= this.position
+ && this.position <= typeDeclaration.declarationSourceEnd) {
+ this.enclosingType = typeDeclaration;
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java
new file mode 100644
index 000000000..dfbc7648a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NormalAnnotation.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Normal annotation node (added in JLS3 API).
+ * <p>
+ * <pre>
+ * NormalAnnotation:
+ * <b>@</b> TypeName <b>(</b> [ MemberValuePair { <b>,</b> MemberValuePair } ] <b>)</b>
+ * </pre>
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class NormalAnnotation extends Annotation {
+
+ /**
+ * The "typeName" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY =
+ internalTypeNamePropertyFactory(NormalAnnotation.class);
+
+ /**
+ * The "values" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor VALUES_PROPERTY =
+ new ChildListPropertyDescriptor(NormalAnnotation.class, "values", MemberValuePair.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(NormalAnnotation.class, propertyList);
+ addProperty(TYPE_NAME_PROPERTY, propertyList);
+ addProperty(VALUES_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of member value pairs (element type:
+ * {@link MemberValuePair}). Defaults to an empty list.
+ */
+ private ASTNode.NodeList values =
+ new ASTNode.NodeList(VALUES_PROPERTY);
+
+ /**
+ * Creates a new unparented normal annotation node owned
+ * by the given AST. By default, the annotation has an
+ * unspecified type name and an empty list of member value
+ * pairs.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ NormalAnnotation(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_NAME_PROPERTY) {
+ if (get) {
+ return getTypeName();
+ } else {
+ setTypeName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == VALUES_PROPERTY) {
+ return values();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalTypeNameProperty() {
+ return TYPE_NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return NORMAL_ANNOTATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ NormalAnnotation result = new NormalAnnotation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+ result.values().addAll(ASTNode.copySubtrees(target, values()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getTypeName());
+ acceptChildren(visitor, this.values);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live list of member value pairs in this annotation.
+ * Adding and removing nodes from this list affects this node
+ * dynamically. All nodes in this list must be
+ * {@link MemberValuePair}s; attempts to add any other
+ * type of node will trigger an exception.
+ *
+ * @return the live list of member value pairs in this
+ * annotation (element type: <code>MemberValuePair</code>)
+ */
+ public List values() {
+ return this.values;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getTypeName().treeSize())
+ + this.values.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java
new file mode 100644
index 000000000..8bacdf3b3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullLiteral.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null literal node.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class NullLiteral extends Expression {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(1);
+ createPropertyList(NullLiteral.class, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented null literal node owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ NullLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return NULL_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ NullLiteral result = new NullLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
new file mode 100644
index 000000000..2e38b173c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Number literal nodes.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class NumberLiteral extends Expression {
+
+ /**
+ * The "token" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor TOKEN_PROPERTY =
+ new SimplePropertyDescriptor(NumberLiteral.class, "token", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(NumberLiteral.class, propertyList);
+ addProperty(TOKEN_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The token string; defaults to the integer literal "0".
+ */
+ private String tokenValue = "0";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented number literal node owned by the given AST.
+ * By default, the number literal is the token "<code>0</code>".
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ NumberLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TOKEN_PROPERTY) {
+ if (get) {
+ return getToken();
+ } else {
+ setToken((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return NUMBER_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ NumberLiteral result = new NumberLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setToken(getToken());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the token of this number literal node. The value is the sequence
+ * of characters that would appear in the source program.
+ *
+ * @return the numeric literal token
+ */
+ public String getToken() {
+ return this.tokenValue;
+ }
+
+ /**
+ * Sets the token of this number literal node. The value is the sequence
+ * of characters that would appear in the source program.
+ *
+ * @param token the numeric literal token
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setToken(String token) {
+ // update internalSetToken(String) if this is changed
+ if (token == null || token.length() == 0) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = token.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ scanner.tokenizeComments = false;
+ scanner.tokenizeWhiteSpace = false;
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameDoubleLiteral:
+ case TerminalTokens.TokenNameIntegerLiteral:
+ case TerminalTokens.TokenNameFloatingPointLiteral:
+ case TerminalTokens.TokenNameLongLiteral:
+ break;
+ case TerminalTokens.TokenNameMINUS :
+ tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameDoubleLiteral:
+ case TerminalTokens.TokenNameIntegerLiteral:
+ case TerminalTokens.TokenNameFloatingPointLiteral:
+ case TerminalTokens.TokenNameLongLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid number literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid number literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ } finally {
+ scanner.tokenizeComments = true;
+ scanner.tokenizeWhiteSpace = true;
+ }
+ preValueChange(TOKEN_PROPERTY);
+ this.tokenValue = token;
+ postValueChange(TOKEN_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setToken(String) that doesn't do any validation.
+ */
+ void internalSetToken(String token) {
+ preValueChange(TOKEN_PROPERTY);
+ this.tokenValue = token;
+ postValueChange(TOKEN_PROPERTY);
+ }
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(this.tokenValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
new file mode 100644
index 000000000..b8f65f8c0
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
+
+/**
+ * Internal implementation of package bindings.
+ */
+class PackageBinding implements IPackageBinding {
+
+ private static final String[] NO_NAME_COMPONENTS = CharOperation.NO_STRINGS;
+ private static final String UNNAMED = Util.EMPTY_STRING;
+ private static final char PACKAGE_NAME_SEPARATOR = '.';
+
+ private org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding;
+ private String name;
+ private BindingResolver resolver;
+ private String[] components;
+
+ PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
+ this.binding = binding;
+ this.resolver = resolver;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ try {
+ INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment;
+ if (!(nameEnvironment instanceof SearchableEnvironment))
+ return AnnotationBinding.NoAnnotations;
+ NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+ if (nameLookup == null)
+ return AnnotationBinding.NoAnnotations;
+ final String pkgName = getName();
+ IPackageFragment[] pkgs = nameLookup.findPackageFragments(pkgName, false/*exact match*/);
+ if (pkgs == null)
+ return AnnotationBinding.NoAnnotations;
+
+ for (int i = 0, len = pkgs.length; i < len; i++) {
+ int fragType = pkgs[i].getKind();
+ switch(fragType) {
+ case IPackageFragmentRoot.K_SOURCE:
+ String unitName = "package-info.java"; //$NON-NLS-1$
+ ICompilationUnit unit = pkgs[i].getCompilationUnit(unitName);
+ if (unit != null && unit.exists()) {
+ ASTParser p = ASTParser.newParser(AST.JLS3);
+ p.setSource(unit);
+ p.setResolveBindings(true);
+ p.setUnitName(unitName);
+ p.setFocalPosition(0);
+ p.setKind(ASTParser.K_COMPILATION_UNIT);
+ CompilationUnit domUnit = (CompilationUnit) p.createAST(null);
+ PackageDeclaration pkgDecl = domUnit.getPackage();
+ if (pkgDecl != null) {
+ List annos = pkgDecl.annotations();
+ if (annos == null || annos.isEmpty())
+ return AnnotationBinding.NoAnnotations;
+ IAnnotationBinding[] result = new IAnnotationBinding[annos.size()];
+ int index=0;
+ for (Iterator it = annos.iterator(); it.hasNext(); index++) {
+ result[index] = ((Annotation) it.next()).resolveAnnotationBinding();
+ // not resolving bindings
+ if (result[index] == null)
+ return AnnotationBinding.NoAnnotations;
+ }
+ return result;
+ }
+ }
+ break;
+ case IPackageFragmentRoot.K_BINARY:
+ NameEnvironmentAnswer answer =
+ nameEnvironment.findType(TypeConstants.PACKAGE_INFO_NAME, this.binding.compoundName);
+ if (answer != null && answer.isBinaryType()) {
+ IBinaryType type = answer.getBinaryType();
+ char[][][] missingTypeNames = type.getMissingTypeNames();
+ IBinaryAnnotation[] binaryAnnotations = type.getAnnotations();
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] binaryInstances =
+ BinaryTypeBinding.createAnnotations(binaryAnnotations, this.binding.environment, missingTypeNames);
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] allInstances =
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding.addStandardAnnotations(binaryInstances, type.getTagBits(), this.binding.environment);
+ int total = allInstances.length;
+ IAnnotationBinding[] domInstances = new AnnotationBinding[total];
+ for (int a = 0; a < total; a++) {
+ final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(allInstances[a]);
+ if (annotationInstance == null) {// not resolving binding
+ return AnnotationBinding.NoAnnotations;
+ }
+ domInstances[a] = annotationInstance;
+ }
+ return domInstances;
+ }
+ }
+ }
+ } catch(JavaModelException e) {
+ return AnnotationBinding.NoAnnotations;
+ }
+ return AnnotationBinding.NoAnnotations;
+ }
+
+ /*
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (this.name == null) {
+ computeNameAndComponents();
+ }
+ return this.name;
+ }
+
+ /*
+ * @see IPackageBinding#isUnnamed()
+ */
+ public boolean isUnnamed() {
+ return getName().equals(UNNAMED);
+ }
+
+ /*
+ * @see IPackageBinding#getNameComponents()
+ */
+ public String[] getNameComponents() {
+ if (this.components == null) {
+ computeNameAndComponents();
+ }
+ return this.components;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.PACKAGE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ /**
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /**
+ * @see IBinding#isSynthetic()
+ */
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ /*
+ * @see IBinding#getJavaElement()
+ */
+ public IJavaElement getJavaElement() {
+ INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set
+ if (!(nameEnvironment instanceof SearchableEnvironment)) return null;
+ NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+ if (nameLookup == null) return null;
+ IJavaElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/);
+ if (pkgs == null) return null;
+ return pkgs[0];
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ return new String(this.binding.computeUniqueKey());
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ * @since 3.1
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof PackageBinding)) {
+ return false;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding;
+ return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName);
+ }
+
+ private void computeNameAndComponents() {
+ char[][] compoundName = this.binding.compoundName;
+ if (compoundName == CharOperation.NO_CHAR_CHAR || compoundName == null) {
+ this.name = UNNAMED;
+ this.components = NO_NAME_COMPONENTS;
+ } else {
+ int length = compoundName.length;
+ this.components = new String[length];
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < length - 1; i++) {
+ this.components[i] = new String(compoundName[i]);
+ buffer.append(compoundName[i]).append(PACKAGE_NAME_SEPARATOR);
+ }
+ this.components[length - 1] = new String(compoundName[length - 1]);
+ buffer.append(compoundName[length - 1]);
+ this.name = buffer.toString();
+ }
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java
new file mode 100644
index 000000000..8c8d3a0a3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageDeclaration.java
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Package declaration AST node type.
+ * For JLS2:
+ * <pre>
+ * PackageDeclaration:
+ * <b>package</b> Name <b>;</b>
+ * </pre>
+ * For JLS3, annotations and doc comment
+ * were added:
+ * <pre>
+ * PackageDeclaration:
+ * [ Javadoc ] { Annotation } <b>package</b> Name <b>;</b>
+ * </pre>
+ * Note that the standard AST parser only recognizes a Javadoc comment
+ * immediately preceding the package declaration when it occurs in the
+ * special <code>package-info.java</code> compilation unit (JLS3 7.4.1.1).
+ * The Javadoc comment in that file contains the package description.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PackageDeclaration extends ASTNode {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ new ChildPropertyDescriptor(PackageDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "annotations" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY =
+ new ChildListPropertyDescriptor(PackageDeclaration.class, "annotations", Annotation.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(PackageDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(PackageDeclaration.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(PackageDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(ANNOTATIONS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The doc comment, or <code>null</code> if none.
+ * Defaults to none.
+ * @since 3.0
+ */
+ Javadoc optionalDocComment = null;
+
+ /**
+ * The annotations (element type: <code>Annotation</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList annotations = null;
+
+ /**
+ * The package name; lazily initialized; defaults to a unspecified,
+ * legal Java package identifier.
+ */
+ private Name packageName = null;
+
+ /**
+ * Creates a new AST node for a package declaration owned by the
+ * given AST. The package declaration initially has an unspecified,
+ * but legal, Java identifier; and an empty list of annotations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ PackageDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.annotations = new ASTNode.NodeList(ANNOTATIONS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ANNOTATIONS_PROPERTY) {
+ return annotations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PACKAGE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PackageDeclaration result = new PackageDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.annotations().addAll(ASTNode.copySubtrees(target, annotations()));
+ }
+ result.setName((Name) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.annotations);
+ }
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of annotations of this
+ * package declaration (added in JLS3 API).
+ *
+ * @return the live list of annotations
+ * (element type: <code>Annotation</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List annotations() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ return this.annotations;
+ }
+
+ /**
+ * Returns the doc comment node.
+ *
+ * @return the doc comment node, or <code>null</code> if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.0
+ */
+ public Javadoc getJavadoc() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ return this.optionalDocComment;
+ }
+
+ /**
+ * Sets or clears the doc comment node.
+ *
+ * @param docComment the doc comment node, or <code>null</code> if none
+ * @exception IllegalArgumentException if the doc comment string is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.0
+ */
+ public void setJavadoc(Javadoc docComment) {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ ASTNode oldChild = this.optionalDocComment;
+ preReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+ this.optionalDocComment = docComment;
+ postReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+ }
+
+ /**
+ * Returns the package name of this package declaration.
+ *
+ * @return the package name node
+ */
+ public Name getName() {
+ if (this.packageName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.packageName == null) {
+ preLazyInit();
+ this.packageName = new SimpleName(this.ast);
+ postLazyInit(this.packageName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.packageName;
+ }
+
+ /**
+ * Sets the package name of this package declaration to the given name.
+ *
+ * @param name the new package name
+ * @exception IllegalArgumentException if`:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(Name name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.packageName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.packageName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the package declared in this package
+ * declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public IPackageBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolvePackage(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.annotations == null ? 0 : this.annotations.listSize())
+ + (this.packageName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterMapping.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterMapping.java
new file mode 100644
index 000000000..4e0157798
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterMapping.java
@@ -0,0 +1,385 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ParameterMapping.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT.
+ *
+ * Represents the DOM-ASTNode for parameterMapping, which has to handle mappings for callin (OTJLD §4.4) and callout (OTJLD §3.2) bindings.
+ *
+ * Possible parameter mappings are:
+ * "integer.intValue() -> i" or "result <- new Integer(result)" for callout Bindings or
+ * "what <- uid" or "new Integer(i) -> result" for callin Bindings
+ *
+ * Contained AST elements:
+ * This class consists of one expression, one identifier, one direction and a flag, whether it is
+ * a return-parameter mapping or not. The direction is necessary for determination of callout and callin.
+ *
+ * Locations in source code:
+ * This node is used in CalloutMappingDeclartion, CallinMappingDeclaration
+ *
+ * @author ike
+ */
+public class ParameterMapping extends Expression
+{
+ /**
+ * Creates a new AST node for a ParameterMapping declaration owned
+ * by the given AST. By default, the declaration is for a ParameterMapping
+ * of an unspecified, but legal, name;
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ParameterMapping(AST ast)
+ {
+ super(ast);
+ }
+
+
+ /**
+ * The expression structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ParameterMapping.class, "expression", Expression.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The identifier structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor IDENTIFIER_PROPERTY =
+ new ChildPropertyDescriptor(ParameterMapping.class, "identifier", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The direction structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor DIRECTION_PROPERTY =
+ new SimplePropertyDescriptor(ParameterMapping.class, "direction", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The is_Result structural property of this node type.
+ */
+ private static final SimplePropertyDescriptor IS_RESULT_PROPERTY =
+ new SimplePropertyDescriptor(ParameterMapping.class, "isResult", boolean.class, MANDATORY); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ private Expression _expression = null;
+ private SimpleName _identifier = null;
+ private String _direction = null;
+ private boolean _isResult = false;
+
+ static
+ {
+ List propertyList = new ArrayList(5);
+ createPropertyList(ParameterMapping.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(IDENTIFIER_PROPERTY, propertyList);
+ addProperty(DIRECTION_PROPERTY, propertyList);
+ addProperty(IS_RESULT_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+
+ final ASTNode internalGetSetChildProperty(
+ ChildPropertyDescriptor property,
+ boolean isGet,
+ ASTNode child)
+ {
+ if (property == IDENTIFIER_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getIdentifier();
+ }
+ else
+ {
+ setIdentifier((SimpleName) child);
+ return null;
+ }
+ }
+ else if (property == EXPRESSION_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getExpression();
+ }
+ else
+ {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, isGet, child);
+ }
+
+ final boolean internalGetSetBooleanProperty(
+ SimplePropertyDescriptor property,
+ boolean isGet,
+ boolean value)
+ {
+ if (property == IS_RESULT_PROPERTY)
+ {
+ if (isGet)
+ {
+ return hasResultFlag();
+ }
+ else
+ {
+ setResultFlag(value);
+ return false;
+ }
+ }
+ return super.internalGetSetBooleanProperty(property, isGet, value);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#internalGetSetObjectProperty(org.eclipse.jdt.core.dom.SimplePropertyDescriptor, boolean, java.lang.Object)
+ */
+ final Object internalGetSetObjectProperty(
+ SimplePropertyDescriptor property,
+ boolean isGet,
+ Object value)
+ {
+
+ if (property == DIRECTION_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getDirection();
+ }
+ else
+ {
+ setDirection((String) value);
+ return null;
+ }
+ }
+ return super.internalGetSetObjectProperty(property, isGet, value);
+ }
+
+ public boolean hasResultFlag()
+ {
+ return _isResult;
+ }
+
+ public void setResultFlag(boolean resultFlag)
+ {
+ preValueChange(IS_RESULT_PROPERTY);
+ _isResult = resultFlag;
+ postValueChange(IS_RESULT_PROPERTY);
+ }
+
+ public SimpleName getIdentifier()
+ {
+ if (_identifier == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_identifier == null)
+ {
+ preLazyInit();
+ _identifier = new SimpleName(super.ast);
+ postLazyInit(_identifier, IDENTIFIER_PROPERTY);
+ }
+ }
+ } return _identifier;
+ }
+
+ public void setIdentifier(SimpleName identifier)
+ {
+ if (identifier == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = _identifier;
+ preReplaceChild(oldChild, identifier, IDENTIFIER_PROPERTY);
+ _identifier = identifier;
+ postReplaceChild(oldChild, identifier, IDENTIFIER_PROPERTY);
+ }
+
+ public String getDirection()
+ {
+ if (_direction == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_direction == null)
+ {
+ _direction = new String(""); //$NON-NLS-1$
+ }
+ }
+ }
+ return _direction;
+ }
+
+ public boolean isBindIN() {
+ return "<-".equals(getDirection());
+ }
+
+ public void setDirection(String direction)
+ {
+ if (direction == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ _direction = direction;
+ }
+
+
+ public ASTNode getExpression()
+ {
+ if (_expression == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (_expression == null)
+ {
+ preLazyInit();
+ _expression = new SimpleName(super.ast);
+ postLazyInit(_expression, EXPRESSION_PROPERTY);
+ }
+ }
+ } return _expression;
+ }
+
+ public void setExpression(Expression expression)
+ {
+ if (expression == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = _expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ _expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#getNodeType0()
+ */
+ int getNodeType0()
+ {
+ return ASTNode.PARAMETER_MAPPING;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#subtreeMatch0(org.eclipse.jdt.core.dom.ASTMatcher, java.lang.Object)
+ */
+ boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#clone0(org.eclipse.jdt.core.dom.AST)
+ */
+ ASTNode clone0(AST target)
+ {
+ ParameterMapping result = new ParameterMapping(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setExpression((Expression) ASTNode.copySubtree(target,getExpression()));
+ result.setIdentifier((SimpleName) ASTNode.copySubtree(target,getIdentifier()));
+ result.setDirection(this.getDirection());
+ result.setResultFlag(this.hasResultFlag());
+
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#accept0(org.eclipse.jdt.core.dom.ASTVisitor)
+ */
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ if (getDirection().equals("->")) { // expr -> id
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getIdentifier());
+ } else { // id <- expr
+ acceptChild(visitor, getIdentifier());
+ acceptChild(visitor, getExpression());
+ }
+ }
+ visitor.endVisit(this);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#treeSize()
+ */
+ int treeSize()
+ {
+ return memSize() + getExpression().treeSize();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTNode#memSize()
+ */
+ int memSize()
+ {
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java
new file mode 100644
index 000000000..1d108ce31
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParameterizedType.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a parameterized type (added in JLS3 API).
+ * These nodes are used for type references (as opposed to
+ * declarations of parameterized types.)
+ * <pre>
+ * ParameterizedType:
+ * Type <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b>
+ * </pre>
+ * The first type may be a simple type or a qualified type;
+ * other kinds of types are meaningless.
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ParameterizedType extends Type {
+ /**
+ * This index represents the position inside a parameterized qualified type.
+ */
+ int index;
+
+ /**
+ * The "type" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ParameterizedType.class, "type", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ParameterizedType.class, "typeArguments", Type.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(ParameterizedType.class, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type node; lazily initialized; defaults to an unspecfied, but legal,
+ * type.
+ */
+ private Type type = null;
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList typeArguments =
+ new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented node for a parameterized type owned by the
+ * given AST. By default, an unspecified, but legal, type, and no type
+ * arguments.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ParameterizedType(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PARAMETERIZED_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ParameterizedType result = new ParameterizedType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setType((Type) ((ASTNode) getType()).clone(target));
+ result.typeArguments().addAll(
+ ASTNode.copySubtrees(target, typeArguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.typeArguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type of this parameterized type.
+ *
+ * @return the type of this parameterized type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = new SimpleType(this.ast);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type of this parameterized type.
+ *
+ * @param type the new type of this parameterized type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this parameterized
+ * type. For the parameterized type to be plausible, the list should contain
+ * at least one element and not contain primitive types.
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ */
+ public List typeArguments() {
+ return this.typeArguments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.type == null ? 0 : getType().treeSize())
+ + this.typeArguments.listSize();
+ }
+
+//{ObjectTeams: value dependent type?
+ public boolean isDependentType(boolean onlyRelevant) {
+ if (this.typeArguments.listSize() == 0)
+ return false;
+ ASTNode arg0 = (ASTNode)this.typeArguments.get(0);
+ if (arg0.getNodeType() == ASTNode.TYPE_ANCHOR) {
+ Name path= ((TypeAnchor)arg0).getPath();
+ if (path.isSimpleName())
+ return ((SimpleName)path).getIdentifier().equals("tthis"); //$NON-NLS-1$
+ }
+ return false;
+ }
+ public String[] getAnchorPath() {
+ if (this.typeArguments.listSize() > 0) {
+ Type type = (Type)this.typeArguments.get(0);
+ if (type.getNodeType() == ASTNode.TYPE_ANCHOR)
+ return ((TypeAnchor)type).getPath().getFullyQualifiedName().split("."); //$NON-NLS-1$
+ }
+ return new String[0];
+ }
+// SH}
+
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java
new file mode 100644
index 000000000..8be31ffe7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ParenthesizedExpression.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parenthesized expression AST node type.
+ *
+ * <pre>
+ * ParenthesizedExpression:
+ * <b>(</b> Expression <b>)</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ParenthesizedExpression extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ParenthesizedExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ParenthesizedExpression.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented parenthesized expression node owned by the given
+ * AST. By default, the parenthesized expression has an unspecified, but
+ * legal, expression.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ParenthesizedExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PARENTHESIZED_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ParenthesizedExpression result = new ParenthesizedExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this parenthesized expression.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this parenthesized expression.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java
new file mode 100644
index 000000000..a51db30d8
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PostfixExpression.java
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Postfix expression AST node type.
+ *
+ * <pre>
+ * PostfixExpression:
+ * Expression PostfixOperator
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PostfixExpression extends Expression {
+
+ /**
+ * Postfix operators (typesafe enumeration).
+ * <pre>
+ * PostfixOperator:
+ * <b><code>++</code></b> <code>INCREMENT</code>
+ * <b><code>--</code></b> <code>DECREMENT</code>
+ * </pre>
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new postfix operator with the given token.
+ * <p>
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return this.token;
+ }
+
+ /** Postfix increment "++" operator. */
+ public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+ /** Postfix decrement "--" operator. */
+ public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ INCREMENT,
+ DECREMENT,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the postfix operator corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toOperator</code> is the converse of <code>toString</code>:
+ * that is, <code>Operator.toOperator(op.toString()) == op</code> for
+ * all operators <code>op</code>.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ * @return the postfix operator, or <code>null</code> if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+ }
+
+ /**
+ * The "operator" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(PostfixExpression.class, "operator", PostfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "operand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(PostfixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(PostfixExpression.class, propertyList);
+ addProperty(OPERAND_PROPERTY, propertyList);
+ addProperty(OPERATOR_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The operator; defaults to an unspecified postfix operator.
+ */
+ private PostfixExpression.Operator operator =
+ PostfixExpression.Operator.INCREMENT;
+
+ /**
+ * The operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression operand = null;
+
+ /**
+ * Creates a new AST node for an postfix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator and
+ * operand.
+ *
+ * @param ast the AST that is to own this node
+ */
+ PostfixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == OPERAND_PROPERTY) {
+ if (get) {
+ return getOperand();
+ } else {
+ setOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return POSTFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PostfixExpression result = new PostfixExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setOperator(getOperator());
+ result.setOperand((Expression) getOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this postfix expression.
+ *
+ * @return the operator
+ */
+ public PostfixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this postfix expression.
+ *
+ * @param operator the operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(PostfixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the operand of this postfix expression.
+ *
+ * @return the operand expression node
+ */
+ public Expression getOperand() {
+ if (this.operand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.operand == null) {
+ preLazyInit();
+ this.operand= new SimpleName(this.ast);
+ postLazyInit(this.operand, OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.operand;
+ }
+
+ /**
+ * Sets the operand of this postfix expression.
+ *
+ * @param expression the operand expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.operand;
+ preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ this.operand = expression;
+ postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.operand == null ? 0 : getOperand().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrecedenceDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrecedenceDeclaration.java
new file mode 100644
index 000000000..a5b868e71
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrecedenceDeclaration.java
@@ -0,0 +1,128 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: PrecedenceDeclaration.java 23417 2010-02-03 20:13:55Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a precedence declaration in OT/J (OTJLD §4.8).
+ * A precedence declaration contains a list of names
+ * referring either to classes or to callin bindings.
+ *
+ * @author stephan
+ */
+public class PrecedenceDeclaration extends ASTNode {
+
+ @SuppressWarnings("nls")
+ public static final ChildListPropertyDescriptor ELEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(PrecedenceDeclaration.class, "elements", Name.class, NO_CYCLE_RISK);
+
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(PrecedenceDeclaration.class, propertyList);
+ addProperty(ELEMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("JLS2 not supported"); //$NON-NLS-1$
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ ASTNode.NodeList _elements = new ASTNode.NodeList(ELEMENTS_PROPERTY);
+
+ PrecedenceDeclaration(AST ast)
+ {
+ super(ast);
+ }
+
+ List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == ELEMENTS_PROPERTY) {
+ return this._elements;
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ @Override
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ unsupportedIn2();
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this._elements);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ @Override
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ ASTNode clone0(AST target) {
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL)
+ unsupportedIn2();
+ PrecedenceDeclaration result = new PrecedenceDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.elements().addAll(ASTNode.copySubtrees(target, elements()));
+ return result;
+ }
+
+ @Override
+ int getNodeType0() {
+ return PRECEDENCE_DECLARATION;
+ }
+
+ @Override
+ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ public List elements() {
+ return this._elements;
+ }
+
+ @Override
+ int memSize() {
+ return BASE_NODE_SIZE;
+ }
+
+ @Override
+ int treeSize() {
+ return memSize() + this._elements.listSize();
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java
new file mode 100644
index 000000000..196c800ba
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrefixExpression.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Prefix expression AST node type.
+ *
+ * <pre>
+ * PrefixExpression:
+ * PrefixOperator Expression
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PrefixExpression extends Expression {
+
+ /**
+ * Prefix operators (typesafe enumeration).
+ * <pre>
+ * PrefixOperator:
+ * <b><code>++</code></b> <code>INCREMENT</code>
+ * <b><code>--</code></b> <code>DECREMENT</code>
+ * <b><code>+</code></b> <code>PLUS</code>
+ * <b><code>-</code></b> <code>MINUS</code>
+ * <b><code>~</code></b> <code>COMPLEMENT</code>
+ * <b><code>!</code></b> <code>NOT</code>
+ * </pre>
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new prefix operator with the given token.
+ * <p>
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return this.token;
+ }
+
+ /** Prefix increment "++" operator. */
+ public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+ /** Prefix decrement "--" operator. */
+ public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+ /** Unary plus "+" operator. */
+ public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+ /** Unary minus "-" operator. */
+ public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+ /** Bitwise complement "~" operator. */
+ public static final Operator COMPLEMENT = new Operator("~");//$NON-NLS-1$
+ /** Logical complement "!" operator. */
+ public static final Operator NOT = new Operator("!");//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: <code>String</code>;
+ * value type: <code>Operator</code>).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ INCREMENT,
+ DECREMENT,
+ PLUS,
+ MINUS,
+ COMPLEMENT,
+ NOT,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the prefix operator corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toOperator</code> is the converse of <code>toString</code>:
+ * that is, <code>Operator.toOperator(op.toString()) == op</code> for
+ * all operators <code>op</code>.
+ * </p>
+ *
+ * @param token the character sequence for the operator
+ * @return the prefix operator, or <code>null</code> if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+ }
+
+ /**
+ * The "operator" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(PrefixExpression.class, "operator", PrefixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "operand" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(PrefixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(PrefixExpression.class, propertyList);
+ addProperty(OPERATOR_PROPERTY, propertyList);
+ addProperty(OPERAND_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The operator; defaults to an unspecified prefix operator.
+ */
+ private PrefixExpression.Operator operator =
+ PrefixExpression.Operator.PLUS;
+
+ /**
+ * The operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression operand = null;
+
+ /**
+ * Creates a new AST node for an prefix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator and
+ * operand.
+ *
+ * @param ast the AST that is to own this node
+ */
+ PrefixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == OPERAND_PROPERTY) {
+ if (get) {
+ return getOperand();
+ } else {
+ setOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PREFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PrefixExpression result = new PrefixExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setOperator(getOperator());
+ result.setOperand((Expression) getOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this prefix expression.
+ *
+ * @return the operator
+ */
+ public PrefixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this prefix expression.
+ *
+ * @param operator the operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(PrefixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the operand of this prefix expression.
+ *
+ * @return the operand expression node
+ */
+ public Expression getOperand() {
+ if (this.operand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.operand == null) {
+ preLazyInit();
+ this.operand= new SimpleName(this.ast);
+ postLazyInit(this.operand, OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.operand;
+ }
+
+ /**
+ * Sets the operand of this prefix expression.
+ *
+ * @param expression the operand expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.operand;
+ preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ this.operand = expression;
+ postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.operand == null ? 0 : getOperand().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
new file mode 100644
index 000000000..0dcf6fff1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Primitive type nodes.
+ * <pre>
+ * PrimitiveType:
+ * <b>byte</b>
+ * <b>short</b>
+ * <b>char</b>
+ * <b>int</b>
+ * <b>long</b>
+ * <b>float</b>
+ * <b>double</b>
+ * <b>boolean</b>
+ * <b>void</b>
+ * </pre>
+ * <p>
+ * Note that due to the fact that AST nodes belong to a specific AST and
+ * have a specific parent, there needs to multiple instances of these
+ * nodes.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PrimitiveType extends Type {
+
+ /**
+ * Primitive type codes (typesafe enumeration).
+ * <pre>
+ * <b>byte</b> BYTE
+ * <b>short</b> SHORT
+ * <b>char</b> CHAR
+ * <b>int</b> INT
+ * <b>long</b> LONG
+ * <b>float</b> FLOAT
+ * <b>double</b> DOUBLE
+ * <b>boolean</b> BOOLEAN
+ * <b>void</b> VOID
+ * </pre>
+ */
+ public static class Code {
+
+ /**
+ * The name of the type.
+ */
+ private String name;
+
+ /**
+ * Creates a new primitive type code with the given name.
+ * <p>
+ * Note: this constructor is package-private. The only instances
+ * ever created are the ones for the standard primitive types.
+ * </p>
+ *
+ * @param name the standard name of the primitive type
+ */
+ Code(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the standard name of the primitive type.
+ *
+ * @return the standard name of the primitive type
+ */
+ public String toString() {
+ return this.name;
+ }
+ }
+
+ /** Type code for the primitive type "int". */
+ public static final Code INT = new Code("int");//$NON-NLS-1$
+ /** Type code for the primitive type "char". */
+ public static final Code CHAR = new Code("char");//$NON-NLS-1$
+ /** Type code for the primitive type "boolean". */
+ public static final Code BOOLEAN = new Code("boolean");//$NON-NLS-1$
+ /** Type code for the primitive type "short". */
+ public static final Code SHORT = new Code("short");//$NON-NLS-1$
+ /** Type code for the primitive type "long". */
+ public static final Code LONG = new Code("long");//$NON-NLS-1$
+ /** Type code for the primitive type "float". */
+ public static final Code FLOAT = new Code("float");//$NON-NLS-1$
+ /** Type code for the primitive type "double". */
+ public static final Code DOUBLE = new Code("double");//$NON-NLS-1$
+ /** Type code for the primitive type "byte". */
+ public static final Code BYTE = new Code("byte");//$NON-NLS-1$
+
+ /** Type code for the primitive type "void". Note that "void" is
+ * special in that its only legitimate uses are as a method return
+ * type and as a type literal.
+ */
+ public static final Code VOID = new Code("void");//$NON-NLS-1$
+
+ /**
+ * The primitive type code; one of the PrimitiveType constants; default
+ * is int.
+ */
+ private PrimitiveType.Code typeCode = INT;
+
+ /**
+ * Map from token to primitive type code (key type: <code>String</code>;
+ * value type: <code>PrimitiveType.Code</code>).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Code[] ops = {
+ INT,
+ BYTE,
+ CHAR,
+ BOOLEAN,
+ SHORT,
+ LONG,
+ FLOAT,
+ DOUBLE,
+ VOID,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the primitive type code corresponding to the given string,
+ * or <code>null</code> if none.
+ * <p>
+ * <code>toCode</code> is the converse of <code>toString</code>:
+ * that is,
+ * <code>PrimitiveType.Code.toCode(code.toString()) == code</code>
+ * for all type code <code>code</code>.
+ * </p>
+ *
+ * @param token the standard name of the primitive type
+ * @return the primitive type code, or <code>null</code> if none
+ */
+ public static PrimitiveType.Code toCode(String token) {
+ return (PrimitiveType.Code) CODES.get(token);
+ }
+
+ /**
+ * The "primitiveTypeCode" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor PRIMITIVE_TYPE_CODE_PROPERTY =
+ new SimplePropertyDescriptor(PrimitiveType.class, "primitiveTypeCode", PrimitiveType.Code.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(PrimitiveType.class, propertyList);
+ addProperty(PRIMITIVE_TYPE_CODE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented node for a primitive type owned by the given
+ * AST. By default, the node has type "int".
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ PrimitiveType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == PRIMITIVE_TYPE_CODE_PROPERTY) {
+ if (get) {
+ return getPrimitiveTypeCode();
+ } else {
+ setPrimitiveTypeCode((Code) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PRIMITIVE_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PrimitiveType result = new PrimitiveType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setPrimitiveTypeCode(getPrimitiveTypeCode());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the primitive type code.
+ *
+ * @return one of the primitive type code constants declared in this
+ * class
+ */
+ public PrimitiveType.Code getPrimitiveTypeCode() {
+ return this.typeCode;
+ }
+
+ /**
+ * Sets the primitive type code.
+ *
+ * @param typeCode one of the primitive type code constants declared in
+ * this class
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setPrimitiveTypeCode(PrimitiveType.Code typeCode) {
+ if (typeCode == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+ this.typeCode = typeCode;
+ postValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
new file mode 100644
index 000000000..002c3604e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * AST node for a qualified name. A qualified name is defined recursively
+ * as a simple name preceded by a name, which qualifies it. Expressing it this
+ * way means that the qualifier and the simple name get their own AST nodes.
+ * <pre>
+ * QualifiedName:
+ * Name <b>.</b> SimpleName
+ * </pre>
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ *
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class QualifiedName extends Name {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedName.class, "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedName.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(QualifiedName.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The identifier; lazily initialized; defaults to a unspecified, legal
+ * Java identifier.
+ */
+ private Name qualifier = null;
+
+ /**
+ * The name being qualified; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName name = null;
+
+ /**
+ * Creates a new AST node for a qualified name owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ QualifiedName(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return QUALIFIED_NAME;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ QualifiedName result = new QualifiedName(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Name) getQualifier().clone(target));
+ result.setName((SimpleName) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier part of this qualified name.
+ *
+ * @return the qualifier part of this qualified name
+ */
+ public Name getQualifier() {
+ if (this.qualifier == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.qualifier == null) {
+ preLazyInit();
+ this.qualifier = new SimpleName(this.ast);
+ postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+ }
+ }
+ }
+ return this.qualifier;
+ }
+
+ /**
+ * Sets the qualifier of this qualified name to the given name.
+ *
+ * @param qualifier the qualifier of this qualified name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setQualifier(Name qualifier) {
+ if (qualifier == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.qualifier;
+ preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+ this.qualifier = qualifier;
+ postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name part of this qualified name.
+ *
+ * @return the name being qualified
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Sets the name part of this qualified name to the given simple name.
+ *
+ * @param name the identifier of this qualified name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on Name.
+ */
+ void appendName(StringBuffer buffer) {
+ getQualifier().appendName(buffer);
+ buffer.append('.');
+ getName().appendName(buffer);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NAME_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.name == null ? 0 : getName().treeSize())
+ + (this.qualifier == null ? 0 : getQualifier().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
new file mode 100644
index 000000000..5dc5edaa7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a qualified type (added in JLS3 API).
+ * <pre>
+ * QualifiedType:
+ * Type <b>.</b> SimpleName
+ * </pre>
+ * <p>
+ * Not all node arragements will represent legal Java constructs. In particular,
+ * it is nonsense if the type is an array type or primitive type. The normal use
+ * is when the type is a simple or parameterized type.
+ * </p>
+ * <p>
+ * A type like "A.B" can be represented either of two ways:
+ * <ol>
+ * <li>
+ * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+ * </li>
+ * <li>
+ * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+ * </li>
+ * </ol>
+ * The first form is preferred when "A" is known to be a type. However, a
+ * parser cannot always determine this. Clients should be prepared to handle
+ * either rather than make assumptions. (Note also that the first form
+ * became possible as of JLS3; only the second form existed in JLS2 API.)
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class QualifiedType extends Type {
+ /**
+ * This index represents the position inside a parameterized qualified type.
+ */
+ int index;
+
+ /**
+ * The "qualifier" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedType.class, "qualifier", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedType.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(QualifiedType.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type node; lazily initialized; defaults to a type with
+ * an unspecfied, but legal, simple name.
+ */
+ private Type qualifier = null;
+
+ /**
+ * The name being qualified; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName name = null;
+
+ /**
+ * Creates a new unparented node for a qualified type owned by the
+ * given AST. By default, an unspecified, but legal, qualifier and name.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ QualifiedType(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Type) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return QUALIFIED_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ QualifiedType result = new QualifiedType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Type) ((ASTNode) getQualifier()).clone(target));
+ result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this qualified type.
+ *
+ * @return the qualifier of this qualified type
+ */
+ public Type getQualifier() {
+ if (this.qualifier == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.qualifier == null) {
+ preLazyInit();
+ this.qualifier = new SimpleType(this.ast);
+ postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+ }
+ }
+ }
+ return this.qualifier;
+ }
+
+ /**
+ * Sets the qualifier of this qualified type to the given type.
+ *
+ * @param type the new qualifier of this qualified type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.qualifier;
+ preReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+ this.qualifier = type;
+ postReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name part of this qualified type.
+ *
+ * @return the name being qualified
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Sets the name part of this qualified type to the given simple name.
+ *
+ * @param name the identifier of this qualified name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.qualifier == null ? 0 : getQualifier().treeSize())
+ + (this.name == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
new file mode 100644
index 000000000..3b40c3ed4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
@@ -0,0 +1,797 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+
+/**
+ * <h4>OTDT changes:</h4>
+ * <dl>
+ * <dt>What:<dd> new lookup functions, some from ITypeBinding plus some additional ones.
+ * </dl>
+ * <hr>
+ * This class represents the recovered binding for a type
+ */
+class RecoveredTypeBinding implements ITypeBinding {
+
+ private VariableDeclaration variableDeclaration;
+ private Type currentType;
+ private BindingResolver resolver;
+ private int dimensions;
+ private RecoveredTypeBinding innerTypeBinding;
+ private ITypeBinding[] typeArguments;
+ private org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
+
+ RecoveredTypeBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+ this.variableDeclaration = variableDeclaration;
+ this.resolver = resolver;
+ this.currentType = getType();
+ this.dimensions = variableDeclaration.getExtraDimensions();
+ if (this.currentType.isArrayType()) {
+ this.dimensions += ((ArrayType) this.currentType).getDimensions();
+ }
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding) {
+ this.resolver = resolver;
+ this.dimensions = typeBinding.dimensions();
+ this.binding = typeBinding;
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, Type type) {
+ this.currentType = type;
+ this.resolver = resolver;
+ this.dimensions = 0;
+ if (type.isArrayType()) {
+ this.dimensions += ((ArrayType) type).getDimensions();
+ }
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, RecoveredTypeBinding typeBinding, int dimensions) {
+ this.innerTypeBinding = typeBinding;
+ this.dimensions = typeBinding.getDimensions() + dimensions;
+ this.resolver = resolver;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#createArrayType(int)
+ */
+ public ITypeBinding createArrayType(int dims) {
+ return this.resolver.getTypeBinding(this, dims);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getBinaryName()
+ */
+ public String getBinaryName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+ */
+ public ITypeBinding getBound() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getGenericTypeOfWildcardType()
+ */
+ public ITypeBinding getGenericTypeOfWildcardType() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getRank()
+ */
+ public int getRank() {
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getComponentType()
+ */
+ public ITypeBinding getComponentType() {
+ if (this.dimensions == 0) return null;
+ return this.resolver.getTypeBinding(this, -1);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredFields()
+ */
+ public IVariableBinding[] getDeclaredFields() {
+ return TypeBinding.NO_VARIABLE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredMethods()
+ */
+ public IMethodBinding[] getDeclaredMethods() {
+ return TypeBinding.NO_METHOD_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredModifiers()
+ */
+ public int getDeclaredModifiers() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredTypes()
+ */
+ public ITypeBinding[] getDeclaredTypes() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaringMethod()
+ */
+ public IMethodBinding getDeclaringMethod() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getDimensions()
+ */
+ public int getDimensions() {
+ return this.dimensions;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getElementType()
+ */
+ public ITypeBinding getElementType() {
+ if (this.binding != null) {
+ if (this.binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+ return new RecoveredTypeBinding(this.resolver, arrayBinding.leafComponentType);
+ } else {
+ return new RecoveredTypeBinding(this.resolver, this.binding);
+ }
+ }
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getElementType();
+ }
+ if (this.currentType!= null && this.currentType.isArrayType()) {
+ return this.resolver.getTypeBinding(((ArrayType) this.currentType).getElementType());
+ }
+ if (this.variableDeclaration != null && this.variableDeclaration.getExtraDimensions() != 0) {
+ return this.resolver.getTypeBinding(getType());
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
+ */
+ public ITypeBinding getErasure() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getInterfaces()
+ */
+ public ITypeBinding[] getInterfaces() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getName()
+ */
+ public String getName() {
+ char[] brackets = new char[this.dimensions * 2];
+ for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ StringBuffer buffer = new StringBuffer(getInternalName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+ }
+
+ private String getInternalName() {
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getInternalName();
+ }
+ ReferenceBinding referenceBinding = getReferenceBinding();
+ if (referenceBinding != null) {
+ return new String(referenceBinding.compoundName[referenceBinding.compoundName.length - 1]);
+ }
+ return getTypeNameFrom(getType());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getPackage()
+ */
+ public IPackageBinding getPackage() {
+ if (this.binding != null) {
+ switch (this.binding.kind()) {
+ case Binding.BASE_TYPE :
+ case Binding.ARRAY_TYPE :
+ case Binding.TYPE_PARAMETER : // includes capture scenario
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE:
+ return null;
+ }
+ IPackageBinding packageBinding = this.resolver.getPackageBinding(this.binding.getPackage());
+ if (packageBinding != null) return packageBinding;
+ }
+ if (this.innerTypeBinding != null && this.dimensions > 0) {
+ return null;
+ }
+ CompilationUnitScope scope = this.resolver.scope();
+ if (scope != null) {
+ return this.resolver.getPackageBinding(scope.getCurrentPackage());
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
+ */
+ public String getQualifiedName() {
+ ReferenceBinding referenceBinding = getReferenceBinding();
+ if (referenceBinding != null) {
+ StringBuffer buffer = new StringBuffer();
+ char[] brackets = new char[this.dimensions * 2];
+ for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ buffer.append(CharOperation.toString(referenceBinding.compoundName));
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+ } else {
+ return getName();
+ }
+ }
+
+ private ReferenceBinding getReferenceBinding() {
+ if (this.binding != null) {
+ if (this.binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+ if (arrayBinding.leafComponentType instanceof ReferenceBinding) {
+ return (ReferenceBinding) arrayBinding.leafComponentType;
+ }
+ } else if (this.binding instanceof ReferenceBinding) {
+ return (ReferenceBinding) this.binding;
+ }
+ } else if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getReferenceBinding();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getSuperclass()
+ */
+ public ITypeBinding getSuperclass() {
+ if (getQualifiedName().equals("java.lang.Object")) { //$NON-NLS-1$
+ return null;
+ }
+ return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+ */
+ public ITypeBinding[] getTypeArguments() {
+ if (this.binding != null) {
+ return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+ }
+ if (this.typeArguments != null) {
+ return this.typeArguments;
+ }
+
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getTypeArguments();
+ }
+
+ if (this.currentType.isParameterizedType()) {
+ ParameterizedType parameterizedType = (ParameterizedType) this.currentType;
+ List typeArgumentsList = parameterizedType.typeArguments();
+ int size = typeArgumentsList.size();
+ ITypeBinding[] temp = new ITypeBinding[size];
+ for (int i = 0; i < size; i++) {
+ ITypeBinding currentTypeBinding = ((Type) typeArgumentsList.get(i)).resolveBinding();
+ if (currentTypeBinding == null) {
+ return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+ }
+ temp[i] = currentTypeBinding;
+ }
+ return this.typeArguments = temp;
+ }
+ return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
+ */
+ public ITypeBinding[] getTypeBounds() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
+ */
+ public ITypeBinding getTypeDeclaration() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+ */
+ public ITypeBinding[] getTypeParameters() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getWildcard()
+ */
+ public ITypeBinding getWildcard() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnonymous()
+ */
+ public boolean isAnonymous() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isArray()
+ */
+ public boolean isArray() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isAssignmentCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+ */
+ public boolean isAssignmentCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isCapture()
+ */
+ public boolean isCapture() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isCastCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+ */
+ public boolean isCastCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isClass()
+ */
+ public boolean isClass() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isEnum()
+ */
+ public boolean isEnum() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isFromSource()
+ */
+ public boolean isFromSource() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
+ */
+ public boolean isGenericType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isInterface()
+ */
+ public boolean isInterface() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isLocal()
+ */
+ public boolean isLocal() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isMember()
+ */
+ public boolean isMember() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isNested()
+ */
+ public boolean isNested() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isNullType()
+ */
+ public boolean isNullType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.isParameterizedType();
+ }
+ if (this.currentType != null) {
+ return this.currentType.isParameterizedType();
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isPrimitive()
+ */
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
+ */
+ public boolean isRawType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isSubTypeCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+ */
+ public boolean isSubTypeCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isTopLevel()
+ */
+ public boolean isTopLevel() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isTypeVariable()
+ */
+ public boolean isTypeVariable() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
+ */
+ public boolean isUpperbound() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+ */
+ public boolean isWildcardType() {
+ return false;
+ }
+
+//{ObjectTeams: implement OT method from ITypeBinding:
+ public boolean isTeam() {
+ if (this.currentType != null)
+ return Flags.isTeam(this.currentType.getFlags());
+ return false;
+ }
+ public boolean isRole() {
+ if (this.currentType != null)
+ return Flags.isRole(this.currentType.getFlags());
+ return false;
+ }
+ public boolean isClassPartOf (ITypeBinding other) {
+ return false;
+ }
+ public boolean isSynthRoleIfc() {
+ return false;
+ }
+ public ITypeBinding getIfcPart() {
+ if (isInterface())
+ return this;
+ return null;
+ }
+ public ITypeBinding getBaseClass() {
+ return null;
+ }
+ public ITypeBinding[] getSuperRoles() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+ public String getOptimalName() {
+ return this.getQualifiedName();
+ }
+// SH}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#getAnnotations()
+ */
+ public IAnnotationBinding[] getAnnotations() {
+ return AnnotationBinding.NoAnnotations;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#getJavaElement()
+ */
+ public IJavaElement getJavaElement() {
+ IPackageBinding packageBinding = getPackage();
+ if (packageBinding != null) {
+ final IJavaElement javaElement = packageBinding.getJavaElement();
+ if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+ // best effort: we don't know if the recovered binding is a binary or source binding, so go with a compilation unit
+ return ((PackageFragment) javaElement).getCompilationUnit(getInternalName() + SuffixConstants.SUFFIX_STRING_java);
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#getKey()
+ */
+ public String getKey() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Recovered#"); //$NON-NLS-1$
+ if (this.innerTypeBinding != null) {
+ buffer.append("innerTypeBinding") //$NON-NLS-1$
+ .append(this.innerTypeBinding.getKey());
+ } else if (this.currentType != null) {
+ buffer.append("currentType") //$NON-NLS-1$
+ .append(this.currentType.toString());
+ } else if (this.binding != null) {
+ buffer.append("typeBinding") //$NON-NLS-1$
+ .append(this.binding.computeUniqueKey());
+ } else if (this.variableDeclaration != null) {
+ buffer
+ .append("variableDeclaration") //$NON-NLS-1$
+ .append(this.variableDeclaration.getClass())
+ .append(this.variableDeclaration.getName().getIdentifier())
+ .append(this.variableDeclaration.getExtraDimensions());
+ }
+ buffer.append(getDimensions());
+ if (this.typeArguments != null) {
+ buffer.append('<');
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ if (i != 0) {
+ buffer.append(',');
+ }
+ buffer.append(this.typeArguments[i].getKey());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.TYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isEqualTo(org.eclipse.jdt.core.dom.IBinding)
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (!other.isRecovered() || other.getKind() != IBinding.TYPE) return false;
+ return getKey().equals(other.getKey());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isSynthetic()
+ */
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ private String getTypeNameFrom(Type type) {
+ if (type == null) return Util.EMPTY_STRING;
+ switch(type.getNodeType0()) {
+ case ASTNode.ARRAY_TYPE :
+ ArrayType arrayType = (ArrayType) type;
+ type = arrayType.getElementType();
+ return getTypeNameFrom(type);
+ case ASTNode.PARAMETERIZED_TYPE :
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ StringBuffer buffer = new StringBuffer(getTypeNameFrom(parameterizedType.getType()));
+ ITypeBinding[] tArguments = getTypeArguments();
+ final int typeArgumentsLength = tArguments.length;
+ if (typeArgumentsLength != 0) {
+ buffer.append('<');
+ for (int i = 0; i < typeArgumentsLength; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ }
+ buffer.append(tArguments[i].getName());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+ case ASTNode.PRIMITIVE_TYPE :
+ PrimitiveType primitiveType = (PrimitiveType) type;
+ return primitiveType.getPrimitiveTypeCode().toString();
+ case ASTNode.QUALIFIED_TYPE :
+ QualifiedType qualifiedType = (QualifiedType) type;
+ return qualifiedType.getName().getIdentifier();
+ case ASTNode.SIMPLE_TYPE :
+ SimpleType simpleType = (SimpleType) type;
+ Name name = simpleType.getName();
+ if (name.isQualifiedName()) {
+ QualifiedName qualifiedName = (QualifiedName) name;
+ return qualifiedName.getName().getIdentifier();
+ }
+ return ((SimpleName) name).getIdentifier();
+ }
+ return Util.EMPTY_STRING;
+ }
+
+ private Type getType() {
+ if (this.currentType != null) {
+ return this.currentType;
+ }
+ if (this.variableDeclaration == null) return null;
+ switch(this.variableDeclaration.getNodeType()) {
+ case ASTNode.SINGLE_VARIABLE_DECLARATION :
+ SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) this.variableDeclaration;
+ return singleVariableDeclaration.getType();
+ default :
+ // this is a variable declaration fragment
+ ASTNode parent = this.variableDeclaration.getParent();
+ switch(parent.getNodeType()) {
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) parent;
+ return variableDeclarationExpression.getType();
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT :
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) parent;
+ return statement.getType();
+ case ASTNode.FIELD_DECLARATION :
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) parent;
+ return fieldDeclaration.getType();
+ }
+ }
+ return null; // should not happen
+ }
+//{ObjectTeams: new lookup-functions
+ public org.eclipse.jdt.internal.compiler.lookup.TypeBinding getResolvedBinding() {
+ return this.binding;
+ }
+
+ /* implement method from ITypeBinding. */
+ public boolean isDependentType(boolean onlyRelevant) {
+ if (this.binding != null) {
+ if (onlyRelevant)
+ return RoleTypeBinding.isRoleWithExplicitAnchor(this.binding);
+ return DependentTypeBinding.isDependentType(this.binding);
+ }
+ if ( this.currentType != null
+ && this.currentType.isParameterizedType())
+ return ((ParameterizedType)this.currentType).isDependentType(onlyRelevant);
+ return false;
+ }
+
+ /* implement method from ITypeBinding. */
+ public String[] getAnchorPath() {
+ if (this.binding != null) {
+ if (DependentTypeBinding.isDependentType(this.binding))
+ return TypeBinding.getBestNamePath((DependentTypeBinding)this.binding);
+ } else if ( this.currentType != null
+ && this.currentType.isParameterizedType()
+ && ((ParameterizedType)this.currentType).isDependentType(false)) {
+ return ((ParameterizedType)this.currentType).getAnchorPath();
+ }
+ return new String[0];
+ }
+
+ public IMethodMappingBinding[] getResolvedMethodMappings() {
+ // copy of TypeBinding.getResolvedMethodMappings:
+ List<IMethodMappingBinding> mappings = new ArrayList<IMethodMappingBinding>();
+ if (this.isRole()) {
+ org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding roleBinding
+ = (org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)this.binding;
+ if (roleBinding.callinCallouts != null) {
+ for (CallinCalloutBinding mapping : roleBinding.callinCallouts) {
+ mappings.add(this.resolver.getMethodMappingBinding(mapping));
+ }
+ }
+ }
+ IMethodMappingBinding[] result = new IMethodMappingBinding[mappings.size()];
+ if (!mappings.isEmpty())
+ mappings.toArray(result);
+ return result;
+ }
+// SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredVariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredVariableBinding.java
new file mode 100644
index 000000000..ba512fc63
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredVariableBinding.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IJavaElement;
+
+/**
+ * This class represents the recovered binding for a variable
+ */
+class RecoveredVariableBinding implements IVariableBinding {
+
+ private VariableDeclaration variableDeclaration;
+ private BindingResolver resolver;
+
+ RecoveredVariableBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+ this.resolver = resolver;
+ this.variableDeclaration = variableDeclaration;
+ }
+ public Object getConstantValue() {
+ return null;
+ }
+
+ public ITypeBinding getDeclaringClass() {
+ ASTNode parent = this.variableDeclaration.getParent();
+ while (parent != null && parent.getNodeType() != ASTNode.TYPE_DECLARATION) {
+ parent = parent.getParent();
+ }
+ if (parent != null) {
+ return ((TypeDeclaration) parent).resolveBinding();
+ }
+ return null;
+ }
+
+ public IMethodBinding getDeclaringMethod() {
+ ASTNode parent = this.variableDeclaration.getParent();
+ while (parent != null && parent.getNodeType() != ASTNode.METHOD_DECLARATION) {
+ parent = parent.getParent();
+ }
+ if (parent != null) {
+ return ((MethodDeclaration) parent).resolveBinding();
+ }
+ return null;
+ }
+
+ public String getName() {
+ return this.variableDeclaration.getName().getIdentifier();
+ }
+
+ public ITypeBinding getType() {
+ return this.resolver.getTypeBinding(this.variableDeclaration);
+ }
+
+ public IVariableBinding getVariableDeclaration() {
+ return this;
+ }
+
+ public int getVariableId() {
+ return 0;
+ }
+
+ public boolean isEnumConstant() {
+ return false;
+ }
+
+ public boolean isField() {
+ return this.variableDeclaration.getParent() instanceof FieldDeclaration;
+ }
+
+ public boolean isParameter() {
+ return this.variableDeclaration instanceof SingleVariableDeclaration;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ return AnnotationBinding.NoAnnotations;
+ }
+
+ public IJavaElement getJavaElement() {
+ return null;
+ }
+
+ public String getKey() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Recovered#"); //$NON-NLS-1$
+ if (this.variableDeclaration != null) {
+ buffer
+ .append("variableDeclaration") //$NON-NLS-1$
+ .append(this.variableDeclaration.getClass())
+ .append(this.variableDeclaration.getName().getIdentifier())
+ .append(this.variableDeclaration.getExtraDimensions());
+ }
+ return String.valueOf(buffer);
+ }
+
+ public int getKind() {
+ return IBinding.VARIABLE;
+ }
+
+ public int getModifiers() {
+ return 0;
+ }
+
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ public boolean isEqualTo(IBinding binding) {
+ if (binding.isRecovered() && binding.getKind() == IBinding.VARIABLE) {
+ return getKey().equals(binding.getKey());
+ }
+ return false;
+ }
+
+ public boolean isRecovered() {
+ return true;
+ }
+
+ public boolean isSynthetic() {
+ return false;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java
new file mode 100644
index 000000000..66a01c19a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ReturnStatement.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Return statement AST node type.
+ *
+ * <pre>
+ * ReturnStatement:
+ * <b>return</b> [ Expression ] <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ReturnStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ReturnStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ReturnStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * Creates a new AST node for a return statement owned by the
+ * given AST. By default, the statement has no expression.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ReturnStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return RETURN_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ReturnStatement result = new ReturnStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this return statement, or
+ * <code>null</code> if there is none.
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets or clears the expression of this return statement.
+ *
+ * @param expression the expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RoleTypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RoleTypeDeclaration.java
new file mode 100644
index 000000000..7d574b228
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RoleTypeDeclaration.java
@@ -0,0 +1,1029 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * NEW for OTDT, built in analogy to TypeDeclaration (its superclass)
+ *
+ *
+ * Represents the DOM-ASTNode for a SubType of TypeDeclaration. This node represents a role in a
+ * compilation unit (a "role file").
+ *
+ * Contained AST elements:
+ * RoleTypeDeclaration is a Subtyp of TypeDeclaration, so it contains all properties and methods from
+ * TypeDeclaration, like e.g. TEAM-PROPERTY and getRoles()-Method. This is mandatory, because a role can also
+ * be a team see <a href="#codeexample1">CodeExample1</a>.<br>
+ * RoleTypeDeclaration contains also rolespecific properties:
+ * <dl>
+ * <dt>1. BaseProperty <dd> adapted baseclass -> TypeDeclaration
+ * <dt>2. TeamProperty <dd> Team, which includes this Role -> TypeDeclaration
+ * <dt>3. CallinProperty <dd> a list of all callins which exist inside a role -> List
+ * <dt>4. CalloutProperty <dd> a list of all callouts which exist inside a role -> List
+ * </dl>
+ *
+ *
+ * Locations in source code:
+ * This node is used in BodyDeclaration.
+ *
+ * TODO(ike): javadoc is not completed yet...
+ *
+ * <a name="codeexample1">CodeExample1</a>
+ * <pre>
+ * public team MyTeam1 {
+ * public team MyRole playedBy MyBaseClass {
+ * }
+ * }
+ * </pre>
+ * @author ike
+ */
+public class RoleTypeDeclaration extends TypeDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(RoleTypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ * @deprecated Replaced by {@link #MODIFIERS2_PROPERTY} in the JLS3 API.
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(RoleTypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(RoleTypeDeclaration.class);
+
+ /**
+ * The "interface" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor INTERFACE_PROPERTY =
+ new SimplePropertyDescriptor(RoleTypeDeclaration.class, "interface", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "team" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor TEAM_PROPERTY =
+ new SimplePropertyDescriptor(RoleTypeDeclaration.class, "team", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "role" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor ROLE_PROPERTY =
+ new SimplePropertyDescriptor(RoleTypeDeclaration.class, "role", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "rolefile" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor ROLE_FILE_PROPERTY =
+ new SimplePropertyDescriptor(RoleTypeDeclaration.class, "rolefile", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "BaseClass" structural property of this node type.
+ * @since 3.0
+ * @deprecated Replaced by {@link #BASECLASS_TYPE_PROPERTY} in the JLS3 API.
+ */
+ public static final ChildPropertyDescriptor BASECLASS_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "baseClass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "baseClassType" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BASECLASS_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "baseClassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "BaseClass" structural property of this node type.
+ * @since 3.0
+ * @deprecated Replaced by {@link #TEAMCLASS_TYPE_PROPERTY} in the JLS3 API.
+ */
+ public static final ChildPropertyDescriptor TEAMCLASS_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "teamClass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "baseClassType" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TEAMCLASS_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "teamClassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superclass" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ * @deprecated Replaced by {@link #SUPERCLASS_TYPE_PROPERTY} in the JLS3 API.
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "superclass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superInterfaces" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ * @deprecated Replaced by {@link #SUPER_INTERFACE_TYPES_PROPERTY} in the JLS3 API.
+ */
+ public static final ChildListPropertyDescriptor SUPER_INTERFACES_PROPERTY =
+ new ChildListPropertyDescriptor(RoleTypeDeclaration.class, "superInterfaces", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superclassType" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "superclassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superInterfaceTypes" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY =
+ new ChildListPropertyDescriptor(RoleTypeDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeParameters" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(RoleTypeDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "guardPredicate" structural property of this node type (added in JLS3 API).
+ * @since 0.9.25
+ */
+ public static final ChildPropertyDescriptor GUARD_PROPERTY =
+ new ChildPropertyDescriptor(RoleTypeDeclaration.class, "guardPredicate", GuardPredicateDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "bodyDeclarations" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ internalBodyDeclarationPropertyFactory(RoleTypeDeclaration.class);
+
+ /**
+ * The "precedence" structural property.
+ * @since 0.9.24
+ */
+ public static final ChildListPropertyDescriptor PRECEDENCE_PROPERTY =
+ new ChildListPropertyDescriptor(RoleTypeDeclaration.class, "precedence", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+
+
+ static {
+ List<StructuralPropertyDescriptor> propertyList = new ArrayList<StructuralPropertyDescriptor>(14);
+ createPropertyList(RoleTypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(INTERFACE_PROPERTY, propertyList);
+ addProperty(TEAM_PROPERTY, propertyList);
+ addProperty(ROLE_PROPERTY, propertyList);
+ addProperty(BASECLASS_PROPERTY, propertyList);
+ addProperty(TEAMCLASS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_PROPERTY, propertyList);
+ addProperty(SUPER_INTERFACES_PROPERTY, propertyList);
+ addProperty(GUARD_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ addProperty(PRECEDENCE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList<StructuralPropertyDescriptor>(16);
+ createPropertyList(RoleTypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(INTERFACE_PROPERTY, propertyList);
+ addProperty(TEAM_PROPERTY, propertyList);
+ addProperty(ROLE_PROPERTY, propertyList);
+ addProperty(ROLE_FILE_PROPERTY, propertyList);
+ addProperty(BASECLASS_TYPE_PROPERTY, propertyList);
+ addProperty(TEAMCLASS_TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_TYPE_PROPERTY, propertyList);
+ addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList);
+ addProperty(GUARD_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ addProperty(PRECEDENCE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ public static List propertyDescriptors(int apiLevel)
+ {
+ if (apiLevel == AST.JLS2)
+ {
+ return PROPERTY_DESCRIPTORS_2_0;
+ }
+ else
+ {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional baseClass name; <code>null</code> if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Not used in 3.0.
+ */
+ private Name optionalBaseClassName = null;
+
+ /**
+ * The optional baseClass type; <code>null</code> if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Null in JLS2. Added in JLS3.
+ * @since 3.0
+ */
+ private Type optionalBaseClassType = null;
+
+ private Name teamClassName = null;
+ private Type teamClassType = null;
+
+ /**
+ * @since 1.1.7
+ */
+ private boolean isRoleFile = false;
+
+ /**
+ * Creates a new AST node for a type declaration owned by the given
+ * AST. By default, the type declaration is for a class of an
+ * unspecified, but legal, name; no modifiers; no javadoc;
+ * no type parameters; no superclass or superinterfaces; and an empty list
+ * of body declarations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ RoleTypeDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel == AST.JLS2) {
+ this.superInterfaceNames = new ASTNode.NodeList(SUPER_INTERFACES_PROPERTY);
+ }
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+ this.superInterfaceTypes = new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value)
+ {
+ if (property == MODIFIERS_PROPERTY)
+ {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)
+ {
+ if (property == INTERFACE_PROPERTY)
+ {
+ if (get)
+ {
+ return isInterface();
+ }
+ else
+ {
+ setInterface(value);
+ return false;
+ }
+ }
+
+ if (property == TEAM_PROPERTY)
+ {
+ if (get)
+ {
+ return isTeam();
+ }
+ else
+ {
+ setTeam(value);
+ return false;
+ }
+ }
+ if (property == ROLE_PROPERTY)
+ {
+ if (get)
+ {
+ return isRole();
+ }
+ else
+ {
+ setRole(value);
+ return false;
+ }
+ }
+ if (property == ROLE_FILE_PROPERTY)
+ {
+ if (get)
+ {
+ return isRoleFile();
+ }
+ else
+ {
+ setRoleFile(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ @Override
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == JAVADOC_PROPERTY)
+ {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_PROPERTY) {
+ if (get) {
+ return getSuperclass();
+ } else {
+ setSuperclass((Name) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_TYPE_PROPERTY) {
+ if (get) {
+ return getSuperclassType();
+ } else {
+ setSuperclassType((Type) child);
+ return null;
+ }
+ }
+
+ if (property == BASECLASS_PROPERTY)
+ {
+ if (get)
+ {
+ return getBaseClass();
+ }
+ else
+ {
+ setBaseClass((Name) child);
+ return null;
+ }
+ }
+
+ if (property == BASECLASS_TYPE_PROPERTY)
+ {
+ if (get)
+ {
+ return getBaseClassType();
+ }
+ else
+ {
+ setBaseClassType((Type) child);
+ return null;
+ }
+ }
+
+ if (property == TEAMCLASS_PROPERTY)
+ {
+ if (get)
+ {
+ return getTeamClass();
+ }
+ else
+ {
+ setTeamClass((Name) child);
+ return null;
+ }
+ }
+
+ if (property == TEAMCLASS_TYPE_PROPERTY)
+ {
+ if (get)
+ {
+ return getTeamClassType();
+ }
+ else
+ {
+ setTeamClassType((Type) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ @SuppressWarnings("rawtypes")
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == MODIFIERS2_PROPERTY)
+ {
+ return modifiers();
+ }
+
+ if (property == TYPE_PARAMETERS_PROPERTY)
+ {
+ return typeParameters();
+ }
+
+ if (property == SUPER_INTERFACES_PROPERTY)
+ {
+ return superInterfaces();
+ }
+
+ if (property == SUPER_INTERFACE_TYPES_PROPERTY)
+ {
+ return superInterfaceTypes();
+ }
+
+ if (property == BODY_DECLARATIONS_PROPERTY)
+ {
+ return bodyDeclarations();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty()
+ {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property()
+ {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty()
+ {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildPropertyDescriptor internalNameProperty()
+ {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildListPropertyDescriptor internalBodyDeclarationsProperty()
+ {
+ return BODY_DECLARATIONS_PROPERTY;
+ }
+
+ ChildPropertyDescriptor internalGuardPredicateProperty() {
+ return GUARD_PROPERTY;
+ }
+
+ ChildListPropertyDescriptor internalPrecedenceProperty() {
+ return PRECEDENCE_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0()
+ {
+ return ROLE_TYPE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ RoleTypeDeclaration result = new RoleTypeDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2)
+ {
+ result.setModifiers(getModifiers());
+ result.setSuperclass(
+ (Name) ASTNode.copySubtree(target, getSuperclass()));
+ result.superInterfaces().addAll(
+ ASTNode.copySubtrees(target, superInterfaces()));
+
+ result.setBaseClass(
+ (Name) ASTNode.copySubtree(target, getBaseClass()));
+
+ result.setTeamClass(
+ (Name) ASTNode.copySubtree(target, getTeamClass()));
+ }
+ result.setTeam(isTeam());
+ result.setRole(isRole());
+ result.setRoleFile(isRoleFile());
+ result.setName((SimpleName) getName().clone(target));
+ if (this.ast.apiLevel >= AST.JLS3)
+ {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.typeParameters().addAll(
+ ASTNode.copySubtrees(target, typeParameters()));
+ result.setSuperclassType(
+ (Type) ASTNode.copySubtree(target, getSuperclassType()));
+ result.superInterfaceTypes().addAll(
+ ASTNode.copySubtrees(target, superInterfaceTypes()));
+
+ result.setBaseClassType(
+ (Type) ASTNode.copySubtree(target, getBaseClassType()));
+
+ result.setTeamClassType(
+ (Type) ASTNode.copySubtree(target, getTeamClassType()));
+ }
+ result.setGuardPredicate((GuardPredicateDeclaration)ASTNode.copySubtree(target, getGuardPredicate()));
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ result.precedences().addAll(ASTNode.copySubtrees(target, precedences()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel == AST.JLS2) {
+ acceptChild(visitor, getJavadoc());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getSuperclass());
+ acceptChild(visitor, getBaseClass());
+ acceptChildren(visitor, this.superInterfaceNames);
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.typeParameters);
+ acceptChild(visitor, getSuperclassType());
+ acceptChild(visitor, getBaseClassType());
+ acceptChildren(visitor, this.superInterfaceTypes);
+ acceptChild(visitor, this.getGuardPredicate());
+ acceptChildren(visitor, this.bodyDeclarations);
+ acceptChildren(visitor, this._precedences);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Sets wether this type declaration declares a team class or a class.
+ *
+ * @param isTeam <code>true</code> if this is a team class
+ * declaration, and <code>false</code> if this is a class declaration
+ */
+ public void setTeam(boolean isTeam)
+ {
+ preValueChange(TEAM_PROPERTY);
+ this._isTeam = isTeam;
+ postValueChange(TEAM_PROPERTY);
+ }
+
+ /**
+ * Sets whether this type declaration declares a role class or a class.
+ *
+ * @param isRole <code>true</code> if this is a role class
+ * declaration, and <code>false</code> if this is a class declaration
+ */
+ public void setRole(boolean isRole)
+ {
+ preValueChange(ROLE_PROPERTY);
+ this._isRole = isRole;
+ postValueChange(ROLE_PROPERTY);
+ }
+
+ /**
+ * Sets whether this type declaration resides in a role file.
+ */
+ public void setRoleFile(boolean isRoleFile)
+ {
+ preValueChange(ROLE_FILE_PROPERTY);
+ this.isRoleFile = isRoleFile;
+ postValueChange(ROLE_FILE_PROPERTY);
+ }
+
+ /**
+ * Answer whether this role is a role file.
+ */
+ public boolean isRoleFile() {
+ return this.isRoleFile;
+ }
+
+ /** @deprecated replaced by {@link #getBaseClassType()} in JLS3. */
+ public Name getBaseClass()
+ {
+ supportedOnlyIn2();
+ return this.optionalBaseClassName;
+ }
+
+ public Type getBaseClassType()
+ {
+ unsupportedIn2();
+ return this.optionalBaseClassType;
+ }
+
+ /** @deprecated replaced by {@link #getTeamClassType()} in JLS3. */
+ public Name getTeamClass()
+ {
+ supportedOnlyIn2();
+ return this.teamClassName;
+ }
+
+ public Type getTeamClassType()
+ {
+ unsupportedIn2();
+ return this.teamClassType;
+ }
+
+ /** @deprecated use {@link #setBaseClassType(Type)} (JLS3) */
+ public void setBaseClass(Name baseClassName)
+ {
+ supportedOnlyIn2();
+ ASTNode oldChild = this.optionalBaseClassName;
+ preReplaceChild(oldChild, baseClassName, BASECLASS_PROPERTY);
+ this.optionalBaseClassName = baseClassName;
+ postReplaceChild(oldChild, baseClassName, BASECLASS_PROPERTY);
+ }
+
+ public void setBaseClassType(Type baseClassType)
+ {
+ unsupportedIn2();
+ ASTNode oldChild = this.optionalBaseClassType;
+ preReplaceChild(oldChild, baseClassType, BASECLASS_TYPE_PROPERTY);
+ this.optionalBaseClassType = baseClassType;
+ postReplaceChild(oldChild, baseClassType, BASECLASS_TYPE_PROPERTY);
+ }
+
+ /** @deprecated use {@link #setTeamClassType(Type)} (JLS3) */
+ public void setTeamClass(Name teamClassName)
+ {
+ supportedOnlyIn2();
+ ASTNode oldChild = this.teamClassName;
+ preReplaceChild(oldChild, teamClassName, TEAMCLASS_PROPERTY);
+ this.teamClassName = teamClassName;
+ postReplaceChild(oldChild, teamClassName, TEAMCLASS_PROPERTY);
+ }
+
+ public void setTeamClassType(Type teamClassType)
+ {
+ unsupportedIn2();
+ ASTNode oldChild = this.teamClassType;
+ preReplaceChild(oldChild, teamClassType, TEAMCLASS_TYPE_PROPERTY);
+ this.teamClassType = teamClassType;
+ postReplaceChild(oldChild, teamClassType, TEAMCLASS_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the superclass declared in this type
+ * declaration, or <code>null</code> if there is none (JLS2 API only).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @return the superclass name node, or <code>null</code> if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by <code>getSuperclassType</code>, which returns a <code>Type</code> instead of a <code>Name</code>.
+ */
+ public Name getSuperclass() {
+ supportedOnlyIn2();
+ return this.optionalSuperclassName;
+ }
+
+ /**
+ * Returns the superclass declared in this type
+ * declaration, or <code>null</code> if there is none (added in JLS3 API).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @return the superclass type node, or <code>null</code> if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.0
+ */
+ public Type getSuperclassType() {
+ unsupportedIn2();
+ return this.optionalSuperclassType;
+ }
+
+ /**
+ * Sets or clears the name of the superclass declared in this type
+ * declaration (JLS2 API only).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @param superclassName the superclass name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by <code>setType</code>, which expects a <code>Type</code> instead of a <code>Name</code>.
+ */
+ public void setSuperclass(Name superclassName) {
+ supportedOnlyIn2();
+ ASTNode oldChild = this.optionalSuperclassName;
+ preReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ this.optionalSuperclassName = superclassName;
+ postReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ }
+
+ /**
+ * Sets or clears the superclass declared in this type
+ * declaration (added in JLS3 API).
+ * <p>
+ * Note that this child is not relevant for interface declarations
+ * (although it does still figure in subtree equality comparisons).
+ * </p>
+ *
+ * @param superclassType the superclass type node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.0
+ */
+ public void setSuperclassType(Type superclassType) {
+ unsupportedIn2();
+ ASTNode oldChild = this.optionalSuperclassType;
+ preReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ this.optionalSuperclassType = superclassType;
+ postReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the ordered list of callout declarations of this type
+ * declaration.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-methods filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of role type declarations
+ */
+ @SuppressWarnings("rawtypes")
+ public CalloutMappingDeclaration[] getCallOuts()
+ {
+ List bd = bodyDeclarations();
+ int callOutCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); )
+ {
+ if (it.next() instanceof CalloutMappingDeclaration)
+ {
+ callOutCount++;
+ }
+ }
+ CalloutMappingDeclaration[] callOuts = new CalloutMappingDeclaration[callOutCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); )
+ {
+ Object decl = it.next();
+ if (decl instanceof CalloutMappingDeclaration)
+ {
+ callOuts[next++] = (CalloutMappingDeclaration) decl;
+ }
+ }
+ return callOuts;
+ }
+
+ /**
+ * Returns the ordered list of CallIn declarations of this type
+ * declaration.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-methods filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of role type declarations
+ */
+ @SuppressWarnings("rawtypes")
+ public CallinMappingDeclaration[] getCallIns()
+ {
+ List bd = bodyDeclarations();
+ int callInCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); )
+ {
+ if (it.next() instanceof CallinMappingDeclaration)
+ {
+ callInCount++;
+ }
+ }
+ CallinMappingDeclaration[] callIns = new CallinMappingDeclaration[callInCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); )
+ {
+ Object decl = it.next();
+ if (decl instanceof CallinMappingDeclaration)
+ {
+ callIns[next++] = (CallinMappingDeclaration) decl;
+ }
+ }
+ return callIns;
+ }
+
+
+
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ @SuppressWarnings({ "nls", "rawtypes" })
+ void appendDebugString(StringBuffer buffer)
+ {
+ buffer.append("RoleTypeDeclaration[\n");
+ buffer.append("class ");
+ buffer.append(getName().getIdentifier());
+ buffer.append("\n");
+ if (this.optionalGuardPredicate != null) {
+ getGuardPredicate().appendDebugString(buffer);
+ buffer.append("\n");
+ }
+ for (Iterator it = bodyDeclarations().iterator(); it.hasNext();) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.appendDebugString(buffer);
+ if (it.hasNext()) {
+ buffer.append(";\n");
+ }
+ }
+ buffer.append("]");
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize()
+ {
+ return super.memSize() + 12 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize()
+ {
+ return memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
+ + (this.optionalSuperclassName == null ? 0 : getSuperclass().treeSize())
+ + (this.optionalSuperclassType == null ? 0 : getSuperclassType().treeSize())
+ + (this.superInterfaceNames == null ? 0 : this.superInterfaceNames.listSize())
+ + (this.superInterfaceTypes == null ? 0 : this.superInterfaceTypes.listSize())
+ + this.bodyDeclarations.listSize()
+ + this._precedences.listSize()
+ + (this.optionalBaseClassName == null ? 0 : this.optionalBaseClassName.treeSize())
+ + (this.optionalBaseClassType == null ? 0 : this.optionalBaseClassType.treeSize())
+ + (this.teamClassName== null ? 0 : this.teamClassName.treeSize())
+ + (this.teamClassType == null ? 0 : this.teamClassType.treeSize())
+ + (this.optionalGuardPredicate == null ? 0 : this.optionalGuardPredicate.treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
new file mode 100644
index 000000000..42cd9a155
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: SimpleName.java 19895 2009-04-15 13:52:23Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a simple name. A simple name is an identifier other than
+ * a keyword, boolean literal ("true", "false") or null literal ("null").
+ * <pre>
+ * SimpleName:
+ * Identifier
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SimpleName extends Name {
+
+ /**
+ * The "identifier" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor IDENTIFIER_PROPERTY =
+ new SimplePropertyDescriptor(SimpleName.class, "identifier", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SimpleName.class, propertyList);
+ addProperty(IDENTIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * An unspecified (but externally observable) legal Java identifier.
+ */
+ private static final String MISSING_IDENTIFIER = "MISSING";//$NON-NLS-1$
+
+ /**
+ * The identifier; defaults to a unspecified, legal Java identifier.
+ */
+ private String identifier = MISSING_IDENTIFIER;
+
+ /**
+ * Creates a new AST node for a simple name owned by the given AST.
+ * The new node has an unspecified, legal Java identifier.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SimpleName(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == IDENTIFIER_PROPERTY) {
+ if (get) {
+ return getIdentifier();
+ } else {
+ setIdentifier((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SIMPLE_NAME;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SimpleName result = new SimpleName(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setIdentifier(getIdentifier());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's identifier.
+ *
+ * @return the identifier of this node
+ */
+ public String getIdentifier() {
+ return this.identifier;
+ }
+
+ /**
+ * Sets the identifier of this node to the given value.
+ * The identifier should be legal according to the rules
+ * of the Java language. Note that keywords are not legal
+ * identifiers.
+ * <p>
+ * Note that the list of keywords may depend on the version of the
+ * language (determined when the AST object was created).
+ * </p>
+ *
+ * @param identifier the identifier of this node
+ * @exception IllegalArgumentException if the identifier is invalid
+ */
+ public void setIdentifier(String identifier) {
+ // update internalSetIdentifier if this is changed
+ if (identifier == null) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = identifier.toCharArray();
+ scanner.setSource(source);
+ final int length = source.length;
+ scanner.resetTo(0, length - 1);
+ try {
+ int tokenType = scanner.scanIdentifier();
+//{ObjectTeams: treat like an Identifier:
+ switch (tokenType) {
+ case TerminalTokens.TokenNamebase:
+ case TerminalTokens.TokenNamewhen:
+ case TerminalTokens.TokenNamethis: // like in: T.this.anchor.Type
+ tokenType = TerminalTokens.TokenNameIdentifier;
+ }
+//SH}
+ if (tokenType != TerminalTokens.TokenNameIdentifier) {
+ throw new IllegalArgumentException();
+ }
+ if (scanner.currentPosition != length) {
+ // this is the case when there is only one identifier see 87849
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(IDENTIFIER_PROPERTY);
+ this.identifier = identifier;
+ postValueChange(IDENTIFIER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setIdentifier(String) that doesn't do any validation.
+ */
+ void internalSetIdentifier(String ident) {
+ preValueChange(IDENTIFIER_PROPERTY);
+ this.identifier = ident;
+ postValueChange(IDENTIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns whether this simple name represents a name that is being defined,
+ * as opposed to one being referenced. The following positions are considered
+ * ones where a name is defined:
+ * <ul>
+ * <li>The type name in a <code>TypeDeclaration</code> node.</li>
+ * <li>The method name in a <code>MethodDeclaration</code> node
+ * providing <code>isConstructor</code> is <code>false</code>.</li>
+ * <li>The variable name in any type of <code>VariableDeclaration</code>
+ * node.</li>
+ * <li>The enum type name in a <code>EnumDeclaration</code> node.</li>
+ * <li>The enum constant name in an <code>EnumConstantDeclaration</code>
+ * node.</li>
+ * <li>The variable name in an <code>EnhancedForStatement</code>
+ * node.</li>
+ * <li>The type variable name in a <code>TypeParameter</code>
+ * node.</li>
+ * <li>The type name in an <code>AnnotationTypeDeclaration</code> node.</li>
+ * <li>The member name in an <code>AnnotationTypeMemberDeclaration</code> node.</li>
+ * </ul>
+ * <p>
+ * Note that this is a convenience method that simply checks whether
+ * this node appears in the declaration position relative to its parent.
+ * It always returns <code>false</code> if this node is unparented.
+ * </p>
+ *
+ * @return <code>true</code> if this node declares a name, and
+ * <code>false</code> otherwise
+ */
+ public boolean isDeclaration() {
+ StructuralPropertyDescriptor d = getLocationInParent();
+ if (d == null) {
+ // unparented node
+ return false;
+ }
+ ASTNode parent = getParent();
+ if (parent instanceof TypeDeclaration) {
+ return (d == TypeDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof MethodDeclaration) {
+ MethodDeclaration p = (MethodDeclaration) parent;
+ // could be the name of the method or constructor
+ return !p.isConstructor() && (d == MethodDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof SingleVariableDeclaration) {
+ return (d == SingleVariableDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof VariableDeclarationFragment) {
+ return (d == VariableDeclarationFragment.NAME_PROPERTY);
+ }
+ if (parent instanceof EnumDeclaration) {
+ return (d == EnumDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof EnumConstantDeclaration) {
+ return (d == EnumConstantDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof TypeParameter) {
+ return (d == TypeParameter.NAME_PROPERTY);
+ }
+ if (parent instanceof AnnotationTypeDeclaration) {
+ return (d == AnnotationTypeDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof AnnotationTypeMemberDeclaration) {
+ return (d == AnnotationTypeMemberDeclaration.NAME_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on Name.
+ */
+ void appendName(StringBuffer buffer) {
+ buffer.append(getIdentifier());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NAME_NODE_SIZE + 2 * 4;
+ if (this.identifier != MISSING_IDENTIFIER) {
+ // everything but our missing id costs
+ size += stringSize(this.identifier);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimplePropertyDescriptor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimplePropertyDescriptor.java
new file mode 100644
index 000000000..e30c3019e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimplePropertyDescriptor.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Descriptor for a simple property of an AST node.
+ * A simple property is one whose value is a
+ * primitive type (such as <code>int</code> or <code>boolean</code>)
+ * or some simple value type (such as <code>String</code> or
+ * <code>InfixExpression.Operator</code>).
+ *
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.jdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class SimplePropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Value type. For example, for a node type like
+ * SingleVariableDeclaration, the modifiers property is int.class
+ */
+ private final Class valueType;
+
+ /**
+ * Indicates whether a value is mandatory. A property value is allowed
+ * to be <code>null</code> only if it is not mandatory.
+ */
+ private final boolean mandatory;
+
+ /**
+ * Creates a new simple property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param valueType the value type of this property
+ * @param mandatory <code>true</code> if the property is mandatory,
+ * and <code>false</code> if it is may be <code>null</code>
+ */
+ SimplePropertyDescriptor(Class nodeClass, String propertyId, Class valueType, boolean mandatory) {
+ super(nodeClass, propertyId);
+ if (valueType == null || ASTNode.class.isAssignableFrom(valueType)) {
+ throw new IllegalArgumentException();
+ }
+ this.valueType = valueType;
+ this.mandatory = mandatory;
+ }
+
+ /**
+ * Returns the value type of this property.
+ * <p>
+ * For example, for a node type like SingleVariableDeclaration,
+ * the "modifiers" property returns <code>int.class</code>.
+ * </p>
+ *
+ * @return the value type of the property
+ */
+ public Class getValueType() {
+ return this.valueType;
+ }
+
+ /**
+ * Returns whether this property is mandatory. A property value
+ * is not allowed to be <code>null</code> if it is mandatory.
+ *
+ * @return <code>true</code> if the property is mandatory,
+ * and <code>false</code> if it is may be <code>null</code>
+ */
+ public boolean isMandatory() {
+ return this.mandatory;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
new file mode 100644
index 000000000..2050281bc
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a named class type, a named interface type, or a type variable.
+ * <p>
+ * This kind of node is used to convert a name (<code>Name</code>) into a type
+ * (<code>Type</code>) by wrapping it.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SimpleType extends Type {
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SimpleType.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SimpleType.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type name node; lazily initialized; defaults to a type with
+ * an unspecfied, but legal, name.
+ */
+ private Name typeName = null;
+
+ /**
+ * Creates a new unparented node for a simple type owned by the given AST.
+ * By default, an unspecified, but legal, name.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SimpleType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SIMPLE_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SimpleType result = new SimpleType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((Name) (getName()).clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of this simple type.
+ *
+ * @return the name of this simple type
+ */
+ public Name getName() {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of this simple type to the given name.
+ *
+ * @param typeName the new name of this simple type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(Name typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java
new file mode 100644
index 000000000..a6ed58525
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleMemberAnnotation.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Single member annotation node (added in JLS3 API). The single member annotation
+ * "@foo(bar)" is equivalent to the normal annotation "@foo(value=bar)".
+ * <p>
+ * <pre>
+ * SingleMemberAnnotation:
+ * <b>@</b> TypeName <b>(</b> Expression <b>)</b>
+ * </pre>
+ * Within annotations, only certain kinds of expressions are meaningful,
+ * including other annotations.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class SingleMemberAnnotation extends Annotation {
+
+ /**
+ * The "typeName" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY =
+ internalTypeNamePropertyFactory(SingleMemberAnnotation.class);
+
+ /**
+ * The "value" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor VALUE_PROPERTY =
+ new ChildPropertyDescriptor(SingleMemberAnnotation.class, "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SingleMemberAnnotation.class, propertyList);
+ addProperty(TYPE_NAME_PROPERTY, propertyList);
+ addProperty(VALUE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The value; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression value = null;
+
+ /**
+ * Creates a new unparented normal annotation node owned
+ * by the given AST. By default, the annotation has an
+ * unspecified type name and an unspecified value.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SingleMemberAnnotation(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_NAME_PROPERTY) {
+ if (get) {
+ return getTypeName();
+ } else {
+ setTypeName((Name) child);
+ return null;
+ }
+ }
+ if (property == VALUE_PROPERTY) {
+ if (get) {
+ return getValue();
+ } else {
+ setValue((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalTypeNameProperty() {
+ return TYPE_NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SINGLE_MEMBER_ANNOTATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SingleMemberAnnotation result = new SingleMemberAnnotation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+ result.setValue((Expression) ASTNode.copySubtree(target, getValue()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getTypeName());
+ acceptChild(visitor, getValue());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the value of this annotation.
+ *
+ * @return the value node
+ */
+ public Expression getValue() {
+ if (this.value == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.value == null) {
+ preLazyInit();
+ this.value = new SimpleName(this.ast);
+ postLazyInit(this.value, VALUE_PROPERTY);
+ }
+ }
+ }
+ return this.value;
+ }
+
+ /**
+ * Sets the value of this annotation.
+ *
+ * @param value the new value
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setValue(Expression value) {
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.value;
+ preReplaceChild(oldChild, value, VALUE_PROPERTY);
+ this.value = value;
+ postReplaceChild(oldChild, value, VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getTypeName().treeSize())
+ + (this.value == null ? 0 : getValue().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
new file mode 100644
index 000000000..3cf671763
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
@@ -0,0 +1,636 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Single variable declaration AST node type. Single variable
+ * declaration nodes are used in a limited number of places, including formal
+ * parameter lists and catch clauses. They are not used for field declarations
+ * and regular variable declaration statements.
+ * For JLS2:
+ * <pre>
+ * SingleVariableDeclaration:
+ * { Modifier } Type Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations), and the variable arity
+ * indicator was added:
+ * <pre>
+ * SingleVariableDeclaration:
+ * { ExtendedModifier } Type [ <b>...</b> ] Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SingleVariableDeclaration extends VariableDeclaration {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(SingleVariableDeclaration.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "varargs" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final SimplePropertyDescriptor VARARGS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "initializer", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(6);
+ createPropertyList(SingleVariableDeclaration.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(7);
+ createPropertyList(SingleVariableDeclaration.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(VARARGS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: <code>IExtendedModifier</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ * @since 3.1
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifiers; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The variable name; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName variableName = null;
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Indicates the last parameter of a variable arity method;
+ * defaults to false.
+ *
+ * @since 3.1
+ */
+ private boolean variableArity = false;
+
+ /**
+ * The number of extra array dimensions that appear after the variable;
+ * defaults to 0.
+ *
+ * @since 2.1
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The initializer expression, or <code>null</code> if none;
+ * defaults to none.
+ */
+ private Expression optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for a variable declaration owned by the given
+ * AST. By default, the variable declaration has: no modifiers, an
+ * unspecified (but legal) type, an unspecified (but legal) variable name,
+ * 0 dimensions after the variable; no initializer; not variable arity.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SingleVariableDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+ return EXTRA_DIMENSIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final ChildPropertyDescriptor internalInitializerProperty() {
+ return INITIALIZER_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == VARARGS_PROPERTY) {
+ if (get) {
+ return isVarargs();
+ } else {
+ setVarargs(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SINGLE_VARIABLE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SingleVariableDeclaration result = new SingleVariableDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ } else {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setVarargs(isVarargs());
+ }
+ result.setType((Type) getType().clone(target));
+ result.setExtraDimensions(getExtraDimensions());
+ result.setName((SimpleName) getName().clone(target));
+ result.setInitializer(
+ (Expression) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ * <p>
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable and formal parameter declarations.
+ * </p>
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: <code>IExtendedModifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ * <p>
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from <code>modifiers()</code>.
+ * </p>
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenient method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ * <p>
+ * The following modifiers are meaningful for fields: public, private, protected,
+ * static, final, volatile, and transient. For local variable and formal
+ * parameter declarations, the only meaningful modifier is final.
+ * </p>
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public SimpleName getName() {
+ if (this.variableName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.variableName == null) {
+ preLazyInit();
+ this.variableName = new SimpleName(this.ast);
+ postLazyInit(this.variableName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.variableName;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setName(SimpleName variableName) {
+ if (variableName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.variableName;
+ preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ this.variableName = variableName;
+ postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the type of the variable declared in this variable declaration,
+ * exclusive of any extra array dimensions.
+ *
+ * @return the type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type of the variable declared in this variable declaration to
+ * the given type, exclusive of any extra array dimensions.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns whether this declaration declares the last parameter of
+ * a variable arity method (added in JLS3 API).
+ * <p>
+ * Note that the binding for the type <code>Foo</code>in the vararg method
+ * declaration <code>void fun(Foo... args)</code> is always for the type as
+ * written; i.e., the type binding for <code>Foo</code>. However, if you
+ * navigate from the method declaration to its method binding to the
+ * type binding for its last parameter, the type binding for the vararg
+ * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
+ * the way vararg methods get compiled.
+ * </p>
+ *
+ * @return <code>true</code> if this is a variable arity parameter declaration,
+ * and <code>false</code> otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public boolean isVarargs() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.variableArity;
+ }
+
+ /**
+ * Sets whether this declaration declares the last parameter of
+ * a variable arity method (added in JLS3 API).
+ *
+ * @param variableArity <code>true</code> if this is a variable arity
+ * parameter declaration, and <code>false</code> otherwise
+ * @since 3.1
+ */
+ public void setVarargs(boolean variableArity) {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ preValueChange(VARARGS_PROPERTY);
+ this.variableArity = variableArity;
+ postValueChange(VARARGS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 2.1
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 2.1
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public Expression getInitializer() {
+ return this.optionalInitializer;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setInitializer(Expression initializer) {
+ // a SingleVariableDeclaration may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 7 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.variableName == null ? 0 : getName().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Statement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Statement.java
new file mode 100644
index 000000000..31fff4779
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Statement.java
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Abstract base class of AST nodes that represent statements.
+ * There are many kinds of statements.
+ * <p>
+ * The grammar combines both Statement and BlockStatement.
+ * For JLS2:
+ * <pre>
+ * Statement:
+ * Block
+ * IfStatement
+ * ForStatement
+ * WhileStatement
+ * DoStatement
+ * TryStatement
+ * SwitchStatement
+ * SynchronizedStatement
+ * ReturnStatement
+ * ThrowStatement
+ * BreakStatement
+ * ContinueStatement
+ * EmptyStatement
+ * ExpressionStatement
+ * LabeledStatement
+ * AssertStatement
+ * VariableDeclarationStatement
+ * TypeDeclarationStatement
+ * ConstructorInvocation
+ * SuperConstructorInvocation
+ * </pre>
+ * For JLS3, an enhanced for node type was added:
+ * <pre>
+ * Statement:
+ * Block
+ * IfStatement
+ * ForStatement
+ * EnhancedForStatement
+ * WhileStatement
+ * DoStatement
+ * TryStatement
+ * SwitchStatement
+ * SynchronizedStatement
+ * ReturnStatement
+ * ThrowStatement
+ * BreakStatement
+ * ContinueStatement
+ * EmptyStatement
+ * ExpressionStatement
+ * LabeledStatement
+ * AssertStatement
+ * VariableDeclarationStatement
+ * TypeDeclarationStatement
+ * ConstructorInvocation
+ * SuperConstructorInvocation
+ * </pre>
+ * </p>
+ *
+ * @since 2.0
+ */
+public abstract class Statement extends ASTNode {
+
+ /**
+ * The leading comment, or <code>null</code> if none.
+ * Defaults to none.
+ *
+ * @deprecated The leading comment feature was removed in 2.1.
+ */
+ private String optionalLeadingComment = null;
+
+ /**
+ * Creates a new AST node for a statement owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Statement(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns the leading comment string, including the starting
+ * and ending comment delimiters, and any embedded line breaks.
+ * <p>
+ * A leading comment is a comment that appears before the statement.
+ * It may be either a traditional comment or an end-of-line comment.
+ * Traditional comments must begin with "/&#42;, may contain line breaks,
+ * and must end with "&#42;/. End-of-line comments must begin with "//",
+ * must end with a line delimiter (as per JLS 3.7), and must not contain
+ * line breaks.
+ * </p>
+ *
+ * @return the comment string, or <code>null</code> if none
+ * @deprecated This feature was removed in the 2.1 release because it was
+ * only a partial, and inadequate, solution to the issue of associating
+ * comments with statements. Furthermore, AST.parseCompilationUnit did not
+ * associate leading comments, making this moot. Clients that need to access
+ * comments preceding a statement should either consult the compilation
+ * unit's {@linkplain CompilationUnit#getCommentList() comment table}
+ * or use a scanner to reanalyze the source text immediately preceding
+ * the statement's source range.
+ */
+ public String getLeadingComment() {
+ return this.optionalLeadingComment;
+ }
+
+ /**
+ * Sets or clears the leading comment string. The comment
+ * string must include the starting and ending comment delimiters,
+ * and any embedded linebreaks.
+ * <p>
+ * A leading comment is a comment that appears before the statement.
+ * It may be either a traditional comment or an end-of-line comment.
+ * Traditional comments must begin with "/&#42;, may contain line breaks,
+ * and must end with "&#42;/. End-of-line comments must begin with "//"
+ * (as per JLS 3.7), and must not contain line breaks.
+ * </p>
+ * <p>
+ * Examples:
+ * <code>
+ * <pre>
+ * setLeadingComment("/&#42; traditional comment &#42;/"); // correct
+ * setLeadingComment("missing comment delimiters"); // wrong
+ * setLeadingComment("/&#42; unterminated traditional comment "); // wrong
+ * setLeadingComment("/&#42; broken\n traditional comment &#42;/"); // correct
+ * setLeadingComment("// end-of-line comment\n"); // correct
+ * setLeadingComment("// end-of-line comment without line terminator"); // correct
+ * setLeadingComment("// broken\n end-of-line comment\n"); // wrong
+ * </pre>
+ * </code>
+ * </p>
+ *
+ * @param comment the comment string, or <code>null</code> if none
+ * @exception IllegalArgumentException if the comment string is invalid
+ * @deprecated This feature was removed in the 2.1 release because it was
+ * only a partial, and inadequate, solution to the issue of associating
+ * comments with statements.
+ */
+ public void setLeadingComment(String comment) {
+ if (comment != null) {
+ char[] source = comment.toCharArray();
+ Scanner scanner = this.ast.scanner;
+ scanner.resetTo(0, source.length);
+ scanner.setSource(source);
+ try {
+ int token;
+ boolean onlyOneComment = false;
+ while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ if (onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ onlyOneComment = true;
+ break;
+ default:
+ onlyOneComment = false;
+ }
+ }
+ if (!onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ }
+ // we do not consider the obsolete comment as a structureal property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.optionalLeadingComment = comment;
+ }
+
+ /**
+ * Copies the leading comment from the given statement.
+ *
+ * @param source the statement that supplies the leading comment
+ * @since 2.1
+ */
+ void copyLeadingComment(Statement source) {
+ setLeadingComment(source.getLeadingComment());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(getLeadingComment());
+ return size;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
new file mode 100644
index 000000000..26f55872e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * String literal nodes.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class StringLiteral extends Expression {
+
+ /**
+ * The "escapedValue" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(StringLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(StringLiteral.class, propertyList);
+ addProperty(ESCAPED_VALUE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The literal string, including quotes and escapes; defaults to the
+ * literal for the empty string.
+ */
+ private String escapedValue = "\"\"";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented string literal node owned by the given AST.
+ * By default, the string literal denotes the empty string.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ StringLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == ESCAPED_VALUE_PROPERTY) {
+ if (get) {
+ return getEscapedValue();
+ } else {
+ setEscapedValue((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return STRING_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ StringLiteral result = new StringLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setEscapedValue(getEscapedValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the string value of this literal node to the given string
+ * literal token. The token is the sequence of characters that would appear
+ * in the source program, including enclosing double quotes and embedded
+ * escapes.
+ *
+ * @return the string literal token, including enclosing double
+ * quotes and embedded escapes
+ */
+ public String getEscapedValue() {
+ return this.escapedValue;
+ }
+
+ /**
+ * Sets the string value of this literal node to the given string literal
+ * token. The token is the sequence of characters that would appear in the
+ * source program, including enclosing double quotes and embedded escapes.
+ * For example,
+ * <ul>
+ * <li><code>""</code> <code>setLiteral("\"\"")</code></li>
+ * <li><code>"hello world"</code> <code>setLiteral("\"hello world\"")</code></li>
+ * <li><code>"boo\nhoo"</code> <code>setLiteral("\"boo\\nhoo\"")</code></li>
+ * </ul>
+ *
+ * @param token the string literal token, including enclosing double
+ * quotes and embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setEscapedValue(String token) {
+ // update internalSetEscapedValue(String) if this is changed
+ if (token == null) {
+ throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = token.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameStringLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+ }
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = token;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+ */
+ void internalSetEscapedValue(String token) {
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = token;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /**
+ * Returns the value of this literal node.
+ * <p>
+ * For example,
+ * <pre>
+ * StringLiteral s;
+ * s.setEscapedValue("\"hello\\nworld\"");
+ * assert s.getLiteralValue().equals("hello\nworld");
+ * </pre>
+ * </p>
+ * <p>
+ * Note that this is a convenience method that converts from the stored
+ * string literal token returned by <code>getEscapedLiteral</code>.
+ * </p>
+ *
+ * @return the string value without enclosing double quotes and embedded
+ * escapes
+ * @exception IllegalArgumentException if the literal value cannot be converted
+ */
+ public String getLiteralValue() {
+ String s = getEscapedValue();
+ int len = s.length();
+ if (len < 2 || s.charAt(0) != '\"' || s.charAt(len-1) != '\"' ) {
+ throw new IllegalArgumentException();
+ }
+
+ Scanner scanner = this.ast.scanner;
+ char[] source = s.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameStringLiteral:
+ return scanner.getCurrentStringLiteral();
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Sets the value of this literal node.
+ * <p>
+ * For example,
+ * <pre>
+ * StringLiteral s;
+ * s.setLiteralValue("hello\nworld");
+ * assert s.getEscapedValue().equals("\"hello\\nworld\"");
+ * assert s.getLiteralValue().equals("hello\nworld");
+ * </pre>
+ * </p>
+ * <p>
+ * Note that this is a convenience method that converts to the stored
+ * string literal token acceptable to <code>setEscapedLiteral</code>.
+ * </p>
+ *
+ * @param value the string value without enclosing double quotes and
+ * embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setLiteralValue(String value) {
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ int len = value.length();
+ StringBuffer b = new StringBuffer(len + 2);
+
+ b.append("\""); // opening delimiter //$NON-NLS-1$
+ for (int i = 0; i < len; i++) {
+ char c = value.charAt(i);
+ switch(c) {
+ case '\b' :
+ b.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ b.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ b.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ b.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ b.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"':
+ b.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ b.append("\\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ b.append("\\\\"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ b.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ b.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ b.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ b.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ b.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ b.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ b.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ b.append("\\7"); //$NON-NLS-1$
+ break;
+ default:
+ b.append(c);
+ }
+ }
+ b.append("\""); // closing delimiter //$NON-NLS-1$
+ setEscapedValue(b.toString());
+ }
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(this.escapedValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StructuralPropertyDescriptor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StructuralPropertyDescriptor.java
new file mode 100644
index 000000000..ddd178af3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StructuralPropertyDescriptor.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class for property descriptors of AST nodes.
+ * There are three kinds of properties:
+ * <ul>
+ * <li>simple properties ({@link SimplePropertyDescriptor})
+ * - properties where the value is a primitive (int, boolean)
+ * or simple (String, InfixExprsssion.Operator) type other than an
+ * AST node; for example, the identifier of a {@link SimpleName}</li>
+ * <li>child properties ({@link ChildPropertyDescriptor})
+ * - properties whose value is another AST node;
+ * for example, the name of a {@link MethodDeclaration}</li>
+ * <li>child list properties ({@link ChildListPropertyDescriptor})
+ * - properties where the value is a list of AST nodes;
+ * for example, the statements of a {@link Block}</li>
+ * </ul>
+ *
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class StructuralPropertyDescriptor {
+
+ /**
+ * Property id.
+ */
+ private final String propertyId;
+
+ /**
+ * The concrete AST node type that owns this property.
+ */
+ private final Class nodeClass;
+
+ /**
+ * Creates a new property descriptor for the given node type
+ * with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ */
+ StructuralPropertyDescriptor(Class nodeClass, String propertyId) {
+ if (nodeClass == null || propertyId == null) {
+ throw new IllegalArgumentException();
+ }
+ this.propertyId = propertyId;
+ this.nodeClass = nodeClass;
+ }
+
+ /**
+ * Returns the id of this property.
+ *
+ * @return the property id
+ */
+ public final String getId() {
+ return this.propertyId;
+ }
+
+ /**
+ * Returns the AST node type that owns this property.
+ * <p>
+ * For example, for all properties of the node type
+ * TypeDeclaration, this method returns <code>TypeDeclaration.class</code>.
+ * </p>
+ *
+ * @return the node type that owns this property
+ */
+ public final Class getNodeClass() {
+ return this.nodeClass;
+ }
+
+ /**
+ * Returns whether this property is a simple property
+ * (instance of {@link SimplePropertyDescriptor}.
+ *
+ * @return <code>true</code> if this is a simple property, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isSimpleProperty(){
+ return (this instanceof SimplePropertyDescriptor);
+ }
+
+ /**
+ * Returns whether this property is a child property
+ * (instance of {@link ChildPropertyDescriptor}.
+ *
+ * @return <code>true</code> if this is a child property, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isChildProperty() {
+ return (this instanceof ChildPropertyDescriptor);
+ }
+
+ /**
+ * Returns whether this property is a child list property
+ * (instance of {@link ChildListPropertyDescriptor}.
+ *
+ * @return <code>true</code> if this is a child list property, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isChildListProperty() {
+ return (this instanceof ChildListPropertyDescriptor);
+ }
+
+ /**
+ * Returns a string suitable for debug purposes.
+ * @return {@inheritDoc}
+ */
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ if (isChildListProperty()) {
+ b.append("ChildList"); //$NON-NLS-1$
+ }
+ if (isChildProperty()) {
+ b.append("Child"); //$NON-NLS-1$
+ }
+ if (isSimpleProperty()) {
+ b.append("Simple"); //$NON-NLS-1$
+ }
+ b.append("Property["); //$NON-NLS-1$
+ if (this.nodeClass != null) {
+ b.append(this.nodeClass.getName());
+ }
+ b.append(","); //$NON-NLS-1$
+ if (this.propertyId != null) {
+ b.append(this.propertyId);
+ }
+ b.append("]"); //$NON-NLS-1$
+ return b.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java
new file mode 100644
index 000000000..415798dff
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperConstructorInvocation.java
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Super constructor invocation statement AST node type.
+ * For JLS2: * <pre>
+ * SuperConstructorInvocation:
+ * [ Expression <b>.</b> ] <b>super</b>
+ * <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * SuperConstructorInvocation:
+ * [ Expression <b>.</b> ]
+ * [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * <b>super</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperConstructorInvocation extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SuperConstructorInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SuperConstructorInvocation.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(SuperConstructorInvocation.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The expression; <code>null</code> for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an super constructor invocation statement
+ * owned by the given AST. By default, no type arguments, and an empty list
+ * of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperConstructorInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_CONSTRUCTOR_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperConstructorInvocation result = new SuperConstructorInvocation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this super constructor invocation statement,
+ * or <code>null</code> if there is none.
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets or clears the expression of this super constructor invocation
+ * statement.
+ *
+ * @param expression the expression node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this constructor
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this super
+ * constructor invocation statement.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the constructor binding, or <code>null</code> if the binding
+ * cannot be resolved
+ */
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
new file mode 100644
index 000000000..a20c01fab
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" field access expression AST node type.
+ *
+ * <pre>
+ * SuperFieldAccess:
+ * [ ClassName <b>.</b> ] <b>super</b> <b>.</b> Identifier
+ * </pre>
+ *
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ *
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperFieldAccess extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(SuperFieldAccess.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SuperFieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SuperFieldAccess.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; <code>null</code> for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The field; lazily initialized; defaults to an unspecified,
+ * but legal, simple field name.
+ */
+ private SimpleName fieldName = null;
+
+ /**
+ * Creates a new unparented node for a super field access expression owned
+ * by the given AST. By default, field name is an unspecified, but legal,
+ * name, and there is no qualifier.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperFieldAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_FIELD_ACCESS;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperFieldAccess result = new SuperFieldAccess(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "super" field access expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this "super" field access expression.
+ *
+ * @param name the qualifier name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the field accessed in this "super" field access
+ * expression.
+ *
+ * @return the field name
+ */
+ public SimpleName getName() {
+ if (this.fieldName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.fieldName == null) {
+ preLazyInit();
+ this.fieldName = new SimpleName(this.ast);
+ postLazyInit(this.fieldName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.fieldName;
+ }
+
+ /**
+ * Resolves and returns the binding for the field accessed by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the variable binding, or <code>null</code> if the binding cannot
+ * be resolved
+ * @since 3.0
+ */
+ public IVariableBinding resolveFieldBinding() {
+ return this.ast.getBindingResolver().resolveField(this);
+ }
+
+ /**
+ * Sets the name of the field accessed in this "super" field access
+ * expression.
+ *
+ * @param fieldName the field name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName fieldName) {
+ if (fieldName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.fieldName;
+ preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ this.fieldName = fieldName;
+ postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.fieldName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java
new file mode 100644
index 000000000..bd61dbfb9
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodInvocation.java
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" method invocation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * SuperMethodInvocation:
+ * [ ClassName <b>.</b> ] <b>super</b> <b>.</b> Identifier
+ * <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * SuperMethodInvocation:
+ * [ ClassName <b>.</b> ] <b>super</b> <b>.</b>
+ * [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ * Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperMethodInvocation extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(SuperMethodInvocation.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperMethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SuperMethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperMethodInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(SuperMethodInvocation.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(5);
+ createPropertyList(SuperMethodInvocation.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional qualifier; <code>null</code> for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The type arguments (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal Java method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a "super" method invocation expression owned
+ * by the given AST. By default, no qualifier, no type arguments,
+ * an unspecified, but legal, method name, and an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperMethodInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_METHOD_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperMethodInvocation result = new SuperMethodInvocation(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) getName().clone(target));
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "super" method invocation expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Returns true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise.
+ * <p>
+ * This information is available only when bindings are requested when the AST is being built
+ * </p>.
+ *
+ * @return true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise
+ * @since 3.3
+ */
+ public boolean isResolvedTypeInferredFromExpectedType() {
+ return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+ }
+
+
+ /**
+ * Sets or clears the qualifier of this "super" method invocation expression.
+ *
+ * @param name the qualifier name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this method
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this
+ * "super" method invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the method invoked by this
+ * expression.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the method binding, or <code>null</code> if the binding cannot
+ * be resolved
+ * @since 2.1
+ */
+ public IMethodBinding resolveMethodBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java
new file mode 100644
index 000000000..b28fbe85c
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchCase.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch case AST node type. A switch case is a special kind of node used only
+ * in switch statements. It is a <code>Statement</code> in name only.
+ * <p>
+ * <pre>
+ * SwitchCase:
+ * <b>case</b> Expression <b>:</b>
+ * <b>default</b> <b>:</b>
+ * </pre>
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SwitchCase extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SwitchCase.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SwitchCase.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; <code>null</code> for none; lazily initialized (but
+ * does <b>not</b> default to none).
+ * @see #expressionInitialized
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * Indicates whether <code>optionalExpression</code> has been initialized.
+ */
+ private boolean expressionInitialized = false;
+
+ /**
+ * Creates a new AST node for a switch case pseudo-statement owned by the
+ * given AST. By default, there is an unspecified, but legal, expression.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SwitchCase(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SWITCH_CASE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SwitchCase result = new SwitchCase(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this switch case, or
+ * <code>null</code> if there is none (the "default:" case).
+ *
+ * @return the expression node, or <code>null</code> if there is none
+ */
+ public Expression getExpression() {
+ if (!this.expressionInitialized) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (!this.expressionInitialized) {
+ preLazyInit();
+ this.optionalExpression = new SimpleName(this.ast);
+ this.expressionInitialized = true;
+ postLazyInit(this.optionalExpression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets the expression of this switch case, or clears it (turns it into
+ * the "default:" case).
+ *
+ * @param expression the expression node, or <code>null</code> to
+ * turn it into the "default:" case
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ this.expressionInitialized = true;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns whether this switch case represents the "default:" case.
+ * <p>
+ * This convenience method is equivalent to
+ * <code>getExpression() == null</code>.
+ * </p>
+ *
+ * @return <code>true</code> if this is the default switch case, and
+ * <code>false</code> if this is a non-default switch case
+ */
+ public boolean isDefault() {
+ return getExpression() == null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : this.optionalExpression.treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java
new file mode 100644
index 000000000..f8c51a596
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SwitchStatement.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch statement AST node type.
+ * <p>
+ * <pre>
+ * SwitchStatement:
+ * <b>switch</b> <b>(</b> Expression <b>)</b>
+ * <b>{</b> { SwitchCase | Statement } } <b>}</b>
+ * SwitchCase:
+ * <b>case</b> Expression <b>:</b>
+ * <b>default</b> <b>:</b>
+ * </pre>
+ * <code>SwitchCase</code> nodes are treated as a kind of
+ * <code>Statement</code>.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SwitchStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SwitchStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "statements" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SwitchStatement.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SwitchStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(STATEMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The statements and SwitchCase nodes
+ * (element type: <code>Statement</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList statements =
+ new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented switch statement node owned by the given
+ * AST. By default, the swicth statement has an unspecified, but legal,
+ * expression, and an empty list of switch groups.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SwitchStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == STATEMENTS_PROPERTY) {
+ return statements();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SWITCH_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SwitchStatement result = new SwitchStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.statements().addAll(ASTNode.copySubtrees(target, statements()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChildren(visitor, this.statements);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this switch statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this switch statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of statements for this switch statement.
+ * Within this list, <code>SwitchCase</code> nodes mark the start of
+ * the switch groups.
+ *
+ * @return the live list of statement nodes
+ * (element type: <code>Statement</code>)
+ */
+ public List statements() {
+ return this.statements;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + this.statements.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java
new file mode 100644
index 000000000..4fbf63f40
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SynchronizedStatement.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Synchronized statement AST node type.
+ *
+ * <pre>
+ * SynchronizedStatement:
+ * <b>synchronized</b> <b>(</b> Expression <b>)</b> Block
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SynchronizedStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SynchronizedStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(SynchronizedStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SynchronizedStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * Creates a new unparented synchronized statement node owned by the given
+ * AST. By default, the expression is unspecified, but legal, and the
+ * blody is an empty block.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ SynchronizedStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SYNCHRONIZED_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SynchronizedStatement result = new SynchronizedStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Block) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this synchronized statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this synchronized statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this synchronized statement.
+ *
+ * @return the body block node
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this synchronized statement.
+ *
+ * @param block the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Block block) {
+ if (block == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, block, BODY_PROPERTY);
+ this.body = block;
+ postReplaceChild(oldChild, block, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java
new file mode 100644
index 000000000..50e877b84
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java
@@ -0,0 +1,185 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: TSuperConstructorInvocation.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT.
+ *
+ * TSuperConstructorInvocation represents a 'tsuper call' to a constructor
+ * of the role's implicit super role-class (OTJLD §2.4.2),
+ * e.g. <code>tsuper();</code> or <code>tsuper(arg0, arg1);</code>.
+ *
+ * Contained AST elements:
+ * a list of argument expressions (<code>Expression</code>).
+ *
+ * Locations in source code:
+ * This node can only be used inside bodies of a role constructor,
+ * it appears in <code>Block</code>s only.
+ *
+ * @author mkr
+ */
+public class TSuperConstructorInvocation extends Statement
+{
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(TSuperConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS;
+
+
+ static {
+ ArrayList<StructuralPropertyDescriptor> propertyList = new ArrayList<StructuralPropertyDescriptor>(2);
+ createPropertyList(TSuperConstructorInvocation.class, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ @SuppressWarnings("rawtypes")
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an tsuper constructor invocation statement
+ * owned by the given AST. By default, no type arguments, and an empty list
+ * of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ TSuperConstructorInvocation(AST ast)
+ {
+ super(ast);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this
+ * base constructor invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ @SuppressWarnings("rawtypes")
+ public List getArguments()
+ {
+ return this.arguments;
+ }
+
+ @SuppressWarnings("rawtypes")
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ @SuppressWarnings("rawtypes")
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == ARGUMENTS_PROPERTY)
+ {
+ return getArguments();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ final int getNodeType0()
+ {
+ return TSUPER_CONSTRUCTOR_INVOCATION;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ TSuperConstructorInvocation result = new TSuperConstructorInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.getArguments().addAll(ASTNode.copySubtrees(target, getArguments()));
+
+ return result;
+ }
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ int memSize()
+ {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ int treeSize()
+ {
+ return memSize() + (this.arguments == null
+ ? 0
+ : this.arguments.listSize());
+ }
+
+ public IMethodBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java
new file mode 100644
index 000000000..1546865e4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java
@@ -0,0 +1,335 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: TSuperMessageSend.java 23416 2010-02-03 19:59:31Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT.
+ *
+ * TSuperMessageSend represents a super call along the implicit
+ * inheritance of roles (OTJLD §1.3.1(f)),
+ * e.g. <code>tsuper.m(arg1, arg2)</code> (only inside method <code>m</code> of a role method)
+ * or <code>tsuper(arg1, arg2)</code> (only in a constructor of a role class).
+ *
+ * Contained AST elements:
+ * a selector name (<code>SimpleName</code>), e.g. <code>myRoleMethod</code>.
+ * a List of argument expressions (<code>Expression</code>).
+ *
+ * Locations in source code:
+ * This node can only be used within role methods.
+ *
+ * @author mkr
+ */
+public class TSuperMessageSend extends Expression
+{
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(TSuperMessageSend.class,
+ "name",//$NON-NLS-1$
+ SimpleName.class,
+ MANDATORY,
+ NO_CYCLE_RISK);
+
+ /**
+ * The "arguments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(TSuperMessageSend.class,
+ "arguments",//$NON-NLS-1$
+ Expression.class,
+ CYCLE_RISK);
+
+ /**
+ * The "qualifier" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(TSuperMessageSend.class,
+ "qualifier", //$NON-NLS-1$
+ Name.class,
+ OPTIONAL, NO_CYCLE_RISK);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ ArrayList<StructuralPropertyDescriptor> propertyList = new ArrayList<StructuralPropertyDescriptor>(4);
+ createPropertyList(TSuperMessageSend.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ @SuppressWarnings("rawtypes")
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The method name; lazily initialized;
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * <code>Expression</code>). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * The tsuper-qualification; lazily initialized;
+ */
+ private Name optionalQualification = null;
+
+ /**
+ * Creates a new AST node for a tsuper expression owned by the given AST.
+ * By default, there is no qualifier.
+ *
+ * @param ast the AST that is to own this node
+ */
+ TSuperMessageSend(AST ast)
+ {
+ super(ast);
+ }
+
+ @SuppressWarnings("rawtypes")
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property,
+ boolean get,
+ ASTNode child)
+ {
+ if (property == NAME_PROPERTY)
+ {
+ if (get) {
+ return getName();
+ }
+ else
+ {
+ setName((SimpleName) child);
+ return null;
+ }
+ } else
+ if (property == QUALIFIER_PROPERTY)
+ {
+ if (get) {
+ return getQualifier();
+ }
+ else
+ {
+ setQualification((SimpleName) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ @SuppressWarnings("rawtypes")
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property)
+ {
+ if (property == ARGUMENTS_PROPERTY)
+ {
+ return getArguments();
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ final int getNodeType0()
+ {
+ return TSUPER_MESSAGE_SEND;
+ }
+
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target)
+ {
+ TSuperMessageSend result = new TSuperMessageSend(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((SimpleName)this.methodName.clone(target));
+ result.getArguments().addAll(ASTNode.copySubtrees(target, this.arguments));
+ result.setQualification((Name)this.optionalQualification.clone(target));
+ return result;
+ }
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName()
+ {
+ if (this.methodName == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this.methodName == null)
+ {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name)
+ {
+ if (name == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the ordered list of argument expressions in this
+ * base call method send expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: <code>Expression</code>)
+ */
+ @SuppressWarnings("rawtypes")
+ public List getArguments()
+ {
+ return this.arguments;
+ }
+
+ /**
+ * Returns the qualifier of this qualified creation expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier()
+ {
+ return this.optionalQualification;
+ }
+
+
+ /**
+ * Sets the tsuper qualification
+ *
+ * @param qualification the new qualification
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualification(Name qualification)
+ {
+ if (qualification == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.optionalQualification;
+ preReplaceChild(oldChild, qualification, QUALIFIER_PROPERTY);
+ this.optionalQualification = qualification;
+ postReplaceChild(oldChild, qualification, QUALIFIER_PROPERTY);
+ }
+
+
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, this.optionalQualification);
+ acceptChild(visitor, this.methodName);
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ int memSize()
+ {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize()
+ {
+ return
+ memSize()
+ + (this.methodName == null ? 0 : this.methodName.treeSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+
+ public IMethodBinding resolveMethodBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
new file mode 100644
index 000000000..2261a2ad5
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
@@ -0,0 +1,400 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a tag within a doc comment.
+ * Tag elements nested within another tag element are called
+ * inline doc tags.
+ * <pre>
+ * TagElement:
+ * [ <b>@</b> Identifier ] { DocElement }
+ * DocElement:
+ * TextElement
+ * Name
+ * MethodRef
+ * MemberRef
+ * <b>{</b> TagElement <b>}</b>
+ * </pre>
+ *
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class TagElement extends ASTNode implements IDocElement {
+
+ /**
+ * The "tagName" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor TAG_NAME_PROPERTY =
+ new SimplePropertyDescriptor(TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(TagElement.class, "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(TagElement.class, propertyList);
+ addProperty(TAG_NAME_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_AUTHOR = "@author"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ * <p>
+ * Note that this tag first appeared in J2SE 5.
+ * </p>
+ * @since 3.1
+ */
+ public static final String TAG_CODE = "@code"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_DOCROOT = "@docRoot"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_EXCEPTION = "@exception"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_INHERITDOC = "@inheritDoc"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_LINK = "@link"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ * <p>
+ * Note that this tag first appeared in J2SE 5.
+ * </p>
+ * @since 3.1
+ */
+ public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_RETURN = "@return"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SEE = "@see"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIAL = "@serial"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIALDATA= "@serialData"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIALFIELD= "@serialField"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SINCE = "@since"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_THROWS = "@throws"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_VALUE= "@value"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_VERSION = "@version"; //$NON-NLS-1$
+
+ /**
+ * The tag name, or null if none; defaults to null.
+ */
+ private String optionalTagName = null;
+
+ /**
+ * The list of doc elements (element type: <code>IDocElement</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList fragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a tag element owned by the given AST.
+ * The new node has no name and an empty list of fragments.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TagElement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TAG_NAME_PROPERTY) {
+ if (get) {
+ return getTagName();
+ } else {
+ setTagName((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TAG_ELEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TagElement result = new TagElement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setTagName(getTagName());
+ result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.fragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's tag name, or <code>null</code> if none.
+ * For top level doc tags such as parameter tags, the tag name
+ * includes the "@" character ("@param").
+ * For inline doc tags such as link tags, the tag name
+ * includes the "@" character ("@link").
+ * The tag name may also be <code>null</code>; this is used to
+ * represent the material at the start of a doc comment preceding
+ * the first explicit tag.
+ *
+ * @return the tag name, or <code>null</code> if none
+ */
+ public String getTagName() {
+ return this.optionalTagName;
+ }
+
+ /**
+ * Sets the tag name of this node to the given value.
+ * For top level doc tags such as parameter tags, the tag name
+ * includes the "@" character ("@param").
+ * For inline doc tags such as link tags, the tag name
+ * includes the "@" character ("@link").
+ * The tag name may also be <code>null</code>; this is used to
+ * represent the material at the start of a doc comment preceding
+ * the first explicit tag.
+ *
+ * @param tagName the tag name, or <code>null</code> if none
+ */
+ public void setTagName(String tagName) {
+ preValueChange(TAG_NAME_PROPERTY);
+ this.optionalTagName = tagName;
+ postValueChange(TAG_NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of fragments in this tag element.
+ * <p>
+ * The fragments cover everything following the tag name
+ * (or everything if there is no tag name), and generally omit
+ * embedded line breaks (and leading whitespace on new lines,
+ * including any leading "*"). {@link org.eclipse.jdt.core.dom.TagElement}
+ * nodes are used to represent tag elements (e.g., "@link")
+ * nested within this tag element.
+ * </p>
+ * <p>
+ * Here are some typical examples:
+ * <ul>
+ * <li>"@see Foo#bar()" - TagElement with tag name "@see";
+ * fragments() contains a single MethodRef node</li>
+ * <li>"@param args the program arguments" -
+ * TagElement with tag name "@param";
+ * 2 fragments: SimpleName ("args"), TextElement
+ * (" the program arguments")</li>
+ * <li>"@return See {&#64;link #foo foo} instead." -
+ * TagElement with tag name "@return";
+ * 3 fragments: TextElement ("See "),
+ * TagElement (for "&#64;link #foo foo"),
+ * TextElement (" instead.")</li>
+ * </ul>
+ * The use of Name, MethodRef, and MemberRef nodes within
+ * tag elements allows these fragments to be queried for
+ * binding information.
+ * </p>
+ * <p>
+ * Adding and removing nodes from this list affects this node
+ * dynamically. The nodes in this list may be of various
+ * types, including {@link TextElement},
+ * {@link org.eclipse.jdt.core.dom.TagElement}, {@link Name},
+ * {@link MemberRef}, and {@link MethodRef}.
+ * Clients should assume that the list of types may grow in
+ * the future, and write their code to deal with unexpected
+ * nodes types. However, attempts to add a non-proscribed type
+ * of node will trigger an exception.
+ *
+ * @return the live list of doc elements in this tag element
+ * (element type: <code>ASTNode</code>)
+ */
+ public List fragments() {
+ return this.fragments;
+ }
+
+ /**
+ * Returns whether this tag element is nested within another
+ * tag element. Nested tag elements appears enclosed in
+ * "{" and "}"; certain doc tags, including "@link" and
+ * "@linkplain" are only meaningful as nested tags.
+ * Top-level (i.e., non-nested) doc tags begin on a new line;
+ * certain doc tags, including "@param" and
+ * "@see" are only meaningful as top-level tags.
+ * <p>
+ * This convenience methods checks to see whether the parent
+ * of this node is of type {@link org.eclipse.jdt.core.dom.TagElement}.
+ * </p>
+ *
+ * @return <code>true</code> if this node is a nested tag element,
+ * and false if this node is either parented by a doc comment node
+ * ({@link Javadoc}), or is unparented
+ */
+ public boolean isNested() {
+ return (getParent() instanceof TagElement);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 2 * 4 + stringSize(this.optionalTagName);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.fragments.listSize();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java
new file mode 100644
index 000000000..4bae86903
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextElement.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * AST node for a text element within a doc comment.
+ * <pre>
+ * TextElement:
+ * Sequence of characters not including a close comment delimiter <b>*</b><b>/</b>
+ * </pre>
+ *
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class TextElement extends ASTNode implements IDocElement {
+
+ /**
+ * The "text" structural property of this node type.
+ *
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor TEXT_PROPERTY =
+ new SimplePropertyDescriptor(TextElement.class, "text", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TextElement.class, propertyList);
+ addProperty(TEXT_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The text element; defaults to the empty string.
+ */
+ private String text = Util.EMPTY_STRING;
+
+ /**
+ * Creates a new AST node for a text element owned by the given AST.
+ * The new node has an empty text string.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TextElement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TEXT_PROPERTY) {
+ if (get) {
+ return getText();
+ } else {
+ setText((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TEXT_ELEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TextElement result = new TextElement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setText(getText());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's text.
+ *
+ * @return the text of this node
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * Sets the text of this node to the given value.
+ * <p>
+ * The text element typically includes leading and trailing
+ * whitespace that separates it from the immediately preceding
+ * or following elements. The text element must not include
+ * a block comment closing delimiter "*"+"/".
+ * </p>
+ *
+ * @param text the text of this node
+ * @exception IllegalArgumentException if the text is null
+ * or contains a block comment closing delimiter
+ */
+ public void setText(String text) {
+ if (text == null) {
+ throw new IllegalArgumentException();
+ }
+ if (text.indexOf("*/") > 0) { //$NON-NLS-1$
+ throw new IllegalArgumentException();
+ }
+ preValueChange(TEXT_PROPERTY);
+ this.text = text;
+ postValueChange(TEXT_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4;
+ if (this.text != Util.EMPTY_STRING) {
+ // everything but our empty string costs
+ size += stringSize(this.text);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java
new file mode 100644
index 000000000..aa5d8ab38
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThisExpression.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "this" AST node type.
+ *
+ * <pre>
+ * ThisExpression:
+ * [ ClassName <b>.</b> ] <b>this</b>
+ * </pre>
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ *
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ThisExpression extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(ThisExpression.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ThisExpression.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; <code>null</code> for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * Creates a new AST node for a "this" expression owned by the
+ * given AST. By default, there is no qualifier.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ThisExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return THIS_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ThisExpression result = new ThisExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getQualifier());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "this" expression, or
+ * <code>null</code> if there is none.
+ *
+ * @return the qualifier name node, or <code>null</code> if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this "this" expression.
+ *
+ * @param name the qualifier name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java
new file mode 100644
index 000000000..9b3cf78d5
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ThrowStatement.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Throw statement AST node type.
+ *
+ * <pre>
+ * ThrowStatement:
+ * <b>throw</b> Expression <b>;</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ThrowStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ThrowStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ThrowStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented throw statement node owned by the given
+ * AST. By default, the throw statement has an unspecified, but legal,
+ * expression.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ ThrowStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return THROW_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ThrowStatement result = new ThrowStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this throw statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this throw statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
new file mode 100644
index 000000000..1afbee8b1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Try statement AST node type.
+ *
+ * <pre>
+ * TryStatement:
+ * <b>try</b> Block
+ * { CatchClause }
+ * [ <b>finally</b> Block ]
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TryStatement extends Statement {
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(TryStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "catchClauses" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor CATCH_CLAUSES_PROPERTY =
+ new ChildListPropertyDescriptor(TryStatement.class, "catchClauses", CatchClause.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "finally" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor FINALLY_PROPERTY =
+ new ChildPropertyDescriptor(TryStatement.class, "finally", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(TryStatement.class, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
+ addProperty(FINALLY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * The catch clauses (element type: <code>CatchClause</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList catchClauses =
+ new ASTNode.NodeList(CATCH_CLAUSES_PROPERTY);
+
+ /**
+ * The finally block, or <code>null</code> if none.
+ * Defaults to none.
+ */
+ private Block optionalFinallyBody = null;
+
+
+ /**
+ * Creates a new AST node for a try statement owned by the given
+ * AST. By default, the try statement has an empty block, no catch
+ * clauses, and no finally block.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TryStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ if (property == FINALLY_PROPERTY) {
+ if (get) {
+ return getFinally();
+ } else {
+ setFinally((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == CATCH_CLAUSES_PROPERTY) {
+ return catchClauses();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TRY_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TryStatement result = new TryStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setBody((Block) getBody().clone(target));
+ result.catchClauses().addAll(
+ ASTNode.copySubtrees(target, catchClauses()));
+ result.setFinally(
+ (Block) ASTNode.copySubtree(target, getFinally()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getBody());
+ acceptChildren(visitor, this.catchClauses);
+ acceptChild(visitor, getFinally());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the body of this try statement.
+ *
+ * @return the try body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this try statement.
+ *
+ * @param body the block node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of catch clauses for this try statement.
+ *
+ * @return the live list of catch clauses
+ * (element type: <code>CatchClause</code>)
+ */
+ public List catchClauses() {
+ return this.catchClauses;
+ }
+
+ /**
+ * Returns the finally block of this try statement, or <code>null</code> if
+ * this try statement has <b>no</b> finally block.
+ *
+ * @return the finally block, or <code>null</code> if this try statement
+ * has none
+ */
+ public Block getFinally() {
+ return this.optionalFinallyBody;
+ }
+
+ /**
+ * Sets or clears the finally block of this try statement.
+ *
+ * @param block the finally block node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setFinally(Block block) {
+ ASTNode oldChild = this.optionalFinallyBody;
+ preReplaceChild(oldChild, block, FINALLY_PROPERTY);
+ this.optionalFinallyBody = block;
+ postReplaceChild(oldChild, block, FINALLY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.body == null ? 0 : getBody().treeSize())
+ + this.catchClauses.listSize()
+ + (this.optionalFinallyBody == null ? 0 : getFinally().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java
new file mode 100644
index 000000000..6504333d8
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class of all type AST node types. A type node represents a
+ * reference to a primitive type (including void), to an array type, or to a
+ * simple named type (or type variable), to a qualified type, to a
+ * parameterized type, or to a wildcard type. Note that not all of these
+ * are meaningful in all contexts; for example, a wildcard type is only
+ * meaningful in the type argument position of a parameterized type.
+ * <p>
+ * <pre>
+ * Type:
+ * PrimitiveType
+ * ArrayType
+ * SimpleType
+ * QualifiedType
+ * ParameterizedType
+ * WildcardType
+ * PrimitiveType:
+ * <b>byte</b>
+ * <b>short</b>
+ * <b>char</b>
+ * <b>int</b>
+ * <b>long</b>
+ * <b>float</b>
+ * <b>double</b>
+ * <b>boolean</b>
+ * <b>void</b>
+ * ArrayType:
+ * Type <b>[</b> <b>]</b>
+ * SimpleType:
+ * TypeName
+ * ParameterizedType:
+ * Type <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b>
+ * QualifiedType:
+ * Type <b>.</b> SimpleName
+ * WildcardType:
+ * <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ]
+ * </pre>
+ * </p>
+ *
+ * @since 2.0
+ */
+public abstract class Type extends ASTNode {
+
+ /**
+ * Creates a new AST node for a type owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ Type(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this type is a primitive type
+ * (<code>PrimitiveType</code>).
+ *
+ * @return <code>true</code> if this is a primitive type, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isPrimitiveType() {
+ return (this instanceof PrimitiveType);
+ }
+
+ /**
+ * Returns whether this type is a simple type
+ * (<code>SimpleType</code>).
+ *
+ * @return <code>true</code> if this is a simple type, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isSimpleType() {
+ return (this instanceof SimpleType);
+ }
+
+ /**
+ * Returns whether this type is an array type
+ * (<code>ArrayType</code>).
+ *
+ * @return <code>true</code> if this is an array type, and
+ * <code>false</code> otherwise
+ */
+ public final boolean isArrayType() {
+ return (this instanceof ArrayType);
+ }
+
+ /**
+ * Returns whether this type is a parameterized type
+ * (<code>ParameterizedType</code>).
+ *
+ * @return <code>true</code> if this is a parameterized type, and
+ * <code>false</code> otherwise
+ * @since 3.1
+ */
+ public final boolean isParameterizedType() {
+ return (this instanceof ParameterizedType);
+ }
+
+ /**
+ * Returns whether this type is a qualified type
+ * (<code>QualifiedType</code>).
+ * <p>
+ * Note that a type like "A.B" can be represented either of two ways:
+ * <ol>
+ * <li>
+ * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+ * </li>
+ * <li>
+ * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+ * </li>
+ * </ol>
+ * The first form is preferred when "A" is known to be a type. However, a
+ * parser cannot always determine this. Clients should be prepared to handle
+ * either rather than make assumptions. (Note also that the first form
+ * became possible as of JLS3; only the second form existed in the
+ * JLS2 API.)
+ * </p>
+ *
+ * @return <code>true</code> if this is a qualified type, and
+ * <code>false</code> otherwise
+ * @since 3.1
+ */
+ public final boolean isQualifiedType() {
+ return (this instanceof QualifiedType);
+ }
+
+ /**
+ * Returns whether this type is a wildcard type
+ * (<code>WildcardType</code>).
+ * <p>
+ * Note that a wildcard type is only meaningful as a
+ * type argument of a <code>ParameterizedType</code> node.
+ * </p>
+ *
+ * @return <code>true</code> if this is a wildcard type, and
+ * <code>false</code> otherwise
+ * @since 3.1
+ */
+ public final boolean isWildcardType() {
+ return (this instanceof WildcardType);
+ }
+
+ /**
+ * Resolves and returns the binding for this type.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the type binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public final ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeAnchor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeAnchor.java
new file mode 100644
index 000000000..c80e18746
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeAnchor.java
@@ -0,0 +1,199 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: LiftingType.java 14417 2006-09-23 11:18:42Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * NEW for OTDT
+ *
+ * This class represents the anchor "@anchor" of a dependent type T<@anchor>.
+ * For the compiler this is a value reference but syntactically we treat it
+ * as a type reference so the whole type can mimic as a regular generic type.
+ *
+ * @author stephan
+ * @version $Id: LiftingType.java 14417 2006-09-23 11:18:42Z stephan $
+ */
+public class TypeAnchor extends Type {
+
+ /**
+ * The "path" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor PATH_PROPERTY =
+ new ChildPropertyDescriptor(TypeAnchor.class, "path", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ List<StructuralPropertyDescriptor> propertyList = new ArrayList<StructuralPropertyDescriptor>(2);
+ createPropertyList(TypeAnchor.class, propertyList);
+ addProperty(PATH_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ @SuppressWarnings("rawtypes")
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The path node; lazily initialized; defaults to a unspecified, but legal, path.
+ */
+ private Name path = null;
+
+
+ /**
+ * Creates a new unparented node for a type anchor owned by the given AST.
+ * By default, an unspecified, but legal, expression.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeAnchor(AST ast)
+ {
+ super(ast);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ final List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ @Override
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)
+ {
+ if (property == PATH_PROPERTY)
+ {
+ if (get)
+ {
+ return getPath();
+ }
+ else
+ {
+ setPath((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /**
+ * Returns the path of this type anchor.
+ *
+ * @return the path node
+ */
+ public Name getPath() {
+ if (this.path == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.path == null) {
+ preLazyInit();
+ this.path = new SimpleName(this.ast);
+ postLazyInit(this.path, PATH_PROPERTY);
+ }
+ }
+ }
+ return this.path;
+ }
+
+ /**
+ * Sets the path of this type anchor.
+ *
+ * @param path the new path node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setPath(Name path) {
+ if (path == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.path;
+ preReplaceChild(oldChild, path, PATH_PROPERTY);
+ this.path = path;
+ postReplaceChild(oldChild, path, PATH_PROPERTY);
+ }
+
+ @Override
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getPath());
+ }
+ visitor.endVisit(this);
+ }
+
+ @Override
+ ASTNode clone0(AST target) {
+ TypeAnchor result = new TypeAnchor(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setPath((Name) getPath().clone(target));
+ return result;
+ }
+
+ @Override
+ int getNodeType0() {
+ return TYPE_ANCHOR;
+ }
+
+ @Override
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ @Override
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ @Override
+ int treeSize() {
+ return memSize()
+ + (this.path == null ? 0 : getPath().treeSize());
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
new file mode 100644
index 000000000..c75ae1bc1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -0,0 +1,1463 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: TypeBinding.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
+
+/**
+ * MIGRATION_STATE: 3.4
+ *
+ * <h4>OTDT changes:</h4>
+ * <dl>
+ * <dt>What:<dd> implement methods from ITypeBinding
+ *
+ * <dt>What:<dd> Check for role files.
+ * </dl>
+ * <hr>
+ * Internal implementation of type bindings.
+ */
+class TypeBinding implements ITypeBinding {
+ protected static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
+
+ private static final String NO_NAME = ""; //$NON-NLS-1$
+ protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+ protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
+
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
+ private String key;
+ private BindingResolver resolver;
+ private IVariableBinding[] fields;
+ private IAnnotationBinding[] annotations;
+ private IMethodBinding[] methods;
+ private ITypeBinding[] members;
+ private ITypeBinding[] interfaces;
+ private ITypeBinding[] typeArguments;
+ private ITypeBinding[] bounds;
+ private ITypeBinding[] typeParameters;
+
+ public TypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding) {
+ this.binding = binding;
+ this.resolver = resolver;
+ }
+
+ public ITypeBinding createArrayType(int dimension) {
+ int realDimensions = dimension;
+ realDimensions += getDimensions();
+ if (realDimensions < 1 || realDimensions > 255) {
+ throw new IllegalArgumentException();
+ }
+ return this.resolver.resolveArrayType(this, dimension);
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ if (this.annotations != null) {
+ return this.annotations;
+ }
+ if (this.binding.isAnnotationType() || this.binding.isClass() || this.binding.isEnum() || this.binding.isInterface()) {
+ org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding refType =
+ (org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) this.binding;
+//{ObjectTeams: calling getAnnotations() requires Dependencies control:
+/* orig:
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = refType.getAnnotations();
+ :giro */
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = null;
+ Dependencies.setup(this, null, this.resolver.lookupEnvironment(), true, true); // TODO(SH): parser, flags?
+ try {
+ internalAnnotations = refType.getAnnotations();
+ } finally {
+ Dependencies.release(this);
+ }
+// SH}
+ int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+ if (length != 0) {
+ IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+ int convertedAnnotationCount = 0;
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+ IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+ if (annotationInstance == null) {
+ continue;
+ }
+ tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+ }
+ if (convertedAnnotationCount != length) {
+ if (convertedAnnotationCount == 0) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+ }
+ return this.annotations = tempAnnotations;
+ }
+ }
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+
+ /*
+ * @see ITypeBinding#getBinaryName()
+ * @since 3.0
+ */
+ public String getBinaryName() {
+ if (this.binding.isCapture()) {
+ return null; // no binary name for capture binding
+ } else if (this.binding.isTypeVariable()) {
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ org.eclipse.jdt.internal.compiler.lookup.Binding declaring = typeVariableBinding.declaringElement;
+ StringBuffer binaryName = new StringBuffer();
+ switch(declaring.kind()) {
+ case org.eclipse.jdt.internal.compiler.lookup.Binding.METHOD :
+ MethodBinding methodBinding = (MethodBinding) declaring;
+ char[] constantPoolName = methodBinding.declaringClass.constantPoolName();
+ if (constantPoolName == null) return null;
+ binaryName
+ .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
+ .append('$')
+ .append(methodBinding.signature())
+ .append('$')
+ .append(typeVariableBinding.sourceName);
+ break;
+ default :
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaring;
+ constantPoolName = typeBinding.constantPoolName();
+ if (constantPoolName == null) return null;
+ binaryName
+ .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
+ .append('$')
+ .append(typeVariableBinding.sourceName);
+ }
+ return String.valueOf(binaryName);
+ }
+ char[] constantPoolName = this.binding.constantPoolName();
+ if (constantPoolName == null) return null;
+ char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
+ return new String(dotSeparated);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+ */
+ public ITypeBinding getBound() {
+ switch (this.binding.kind()) {
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE :
+ WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+ if (wildcardBinding.bound != null) {
+ return this.resolver.getTypeBinding(wildcardBinding.bound);
+ }
+ break;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getGenericTypeOfWildcardType()
+ */
+ public ITypeBinding getGenericTypeOfWildcardType() {
+ switch (this.binding.kind()) {
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE :
+ WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+ if (wildcardBinding.genericType != null) {
+ return this.resolver.getTypeBinding(wildcardBinding.genericType);
+ }
+ break;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getRank()
+ */
+ public int getRank() {
+ switch (this.binding.kind()) {
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE :
+ WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+ return wildcardBinding.rank;
+ default:
+ return -1;
+ }
+ }
+
+ /*
+ * @see ITypeBinding#getComponentType()
+ */
+ public ITypeBinding getComponentType() {
+ if (!isArray()) {
+ return null;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+ return this.resolver.getTypeBinding(arrayBinding.elementsType());
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredFields()
+ */
+ public synchronized IVariableBinding[] getDeclaredFields() {
+ if (this.fields != null) {
+ return this.fields;
+ }
+//{ObjectTeams: may need Dependencies:
+ boolean usesDependencies = false;
+// SH}
+ try {
+ if (isClass() || isInterface() || isEnum()) {
+//{ObjectTeams: calling methods() requires Dependencies control:
+ Dependencies.setup(this, null, this.resolver.lookupEnvironment(), true, true); // TODO(SH): parser, flags?
+ usesDependencies = true;
+// SH}
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
+ int length = fieldBindings.length;
+ if (length != 0) {
+ int convertedFieldCount = 0;
+ IVariableBinding[] newFields = new IVariableBinding[length];
+ for (int i = 0; i < length; i++) {
+ FieldBinding fieldBinding = fieldBindings[i];
+ IVariableBinding variableBinding = this.resolver.getVariableBinding(fieldBinding);
+ if (variableBinding != null) {
+ newFields[convertedFieldCount++] = variableBinding;
+ }
+ }
+
+ if (convertedFieldCount != length) {
+ if (convertedFieldCount == 0) {
+ return this.fields = NO_VARIABLE_BINDINGS;
+ }
+ System.arraycopy(newFields, 0, (newFields = new IVariableBinding[convertedFieldCount]), 0, convertedFieldCount);
+ }
+ return this.fields = newFields;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
+ }
+//{ObjectTeams: cleanup:
+ finally {
+ if (usesDependencies)
+ Dependencies.release(this);
+ }
+// SH}
+ return this.fields = NO_VARIABLE_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredMethods()
+ */
+ public synchronized IMethodBinding[] getDeclaredMethods() {
+ if (this.methods != null) {
+ return this.methods;
+ }
+//{ObjectTeams: may need Dependencies:
+ boolean usesDependencies = false;
+// SH}
+ try {
+ if (isClass() || isInterface() || isEnum()) {
+//{ObjectTeams: calling methods() requires Dependencies control:
+ Dependencies.setup(this, null, this.resolver.lookupEnvironment(), true, true); // TODO(SH): parser, flags?
+ usesDependencies = true;
+// SH}
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
+ int length = internalMethods.length;
+ if (length != 0) {
+ int convertedMethodCount = 0;
+ IMethodBinding[] newMethods = new IMethodBinding[length];
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i];
+ if (methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface())) {
+ continue;
+ }
+ if ( methodBinding.copyInheritanceSrc != null
+ || CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, methodBinding.selector()))
+ continue;
+ IMethodBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding);
+ if (methodBinding2 != null) {
+ newMethods[convertedMethodCount++] = methodBinding2;
+ }
+ }
+ if (convertedMethodCount != length) {
+ if (convertedMethodCount == 0) {
+ return this.methods = NO_METHOD_BINDINGS;
+ }
+ System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[convertedMethodCount]), 0, convertedMethodCount);
+ }
+ return this.methods = newMethods;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+ }
+//{ObjectTeams: cleanup:
+ finally {
+ if (usesDependencies)
+ Dependencies.release(this);
+ }
+// SH}
+ return this.methods = NO_METHOD_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredModifiers()
+ */
+ public int getDeclaredModifiers() {
+ return getModifiers();
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredTypes()
+ */
+ public synchronized ITypeBinding[] getDeclaredTypes() {
+ if (this.members != null) {
+ return this.members;
+ }
+ try {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ ReferenceBinding[] internalMembers = referenceBinding.memberTypes();
+ int length = internalMembers.length;
+ if (length != 0) {
+ ITypeBinding[] newMembers = new ITypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(internalMembers[i]);
+ if (typeBinding == null) {
+ return this.members = NO_TYPE_BINDINGS;
+ }
+ newMembers[i] = typeBinding;
+ }
+ return this.members = newMembers;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+ }
+ return this.members = NO_TYPE_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringMethod()
+ */
+ public synchronized IMethodBinding getDeclaringMethod() {
+ if (this.binding instanceof LocalTypeBinding) {
+ LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.binding;
+ MethodBinding methodBinding = localTypeBinding.enclosingMethod;
+ if (methodBinding != null) {
+ try {
+ return this.resolver.getMethodBinding(localTypeBinding.enclosingMethod);
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
+ }
+ }
+ } else if (this.binding.isTypeVariable()) {
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ Binding declaringElement = typeVariableBinding.declaringElement;
+ if (declaringElement instanceof MethodBinding) {
+ try {
+ return this.resolver.getMethodBinding((MethodBinding)declaringElement);
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringClass()
+ */
+ public synchronized ITypeBinding getDeclaringClass() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ if (referenceBinding.isNestedType()) {
+ try {
+ return this.resolver.getTypeBinding(referenceBinding.enclosingType());
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
+ }
+ }
+ } else if (this.binding.isTypeVariable()) {
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ Binding declaringElement = typeVariableBinding.isCapture() ? ((CaptureBinding) typeVariableBinding).sourceType : typeVariableBinding.declaringElement;
+ if (declaringElement instanceof ReferenceBinding) {
+ try {
+ return this.resolver.getTypeBinding((ReferenceBinding)declaringElement);
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDimensions()
+ */
+ public int getDimensions() {
+ if (!isArray()) {
+ return 0;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+ return arrayBinding.dimensions;
+ }
+
+ /*
+ * @see ITypeBinding#getElementType()
+ */
+ public ITypeBinding getElementType() {
+ if (!isArray()) {
+ return null;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+ return this.resolver.getTypeBinding(arrayBinding.leafComponentType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
+ */
+ public ITypeBinding getTypeDeclaration() {
+ if (this.binding instanceof ParameterizedTypeBinding)
+ return this.resolver.getTypeBinding(((ParameterizedTypeBinding)this.binding).genericType());
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
+ */
+ public ITypeBinding getErasure() {
+ return this.resolver.getTypeBinding(this.binding.erasure());
+ }
+
+ public synchronized ITypeBinding[] getInterfaces() {
+ if (this.interfaces != null) {
+ return this.interfaces;
+ }
+ if (this.binding == null)
+ return this.interfaces = NO_TYPE_BINDINGS;
+ switch (this.binding.kind()) {
+ case Binding.ARRAY_TYPE :
+ case Binding.BASE_TYPE :
+ return this.interfaces = NO_TYPE_BINDINGS;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ ReferenceBinding[] internalInterfaces = null;
+ try {
+ internalInterfaces = referenceBinding.superInterfaces();
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve interfaces"); //$NON-NLS-1$
+ }
+ int length = internalInterfaces == null ? 0 : internalInterfaces.length;
+ if (length != 0) {
+ ITypeBinding[] newInterfaces = new ITypeBinding[length];
+ int interfacesCounter = 0;
+ for (int i = 0; i < length; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(internalInterfaces[i]);
+ if (typeBinding == null) {
+ continue;
+ }
+ newInterfaces[interfacesCounter++] = typeBinding;
+ }
+ if (length != interfacesCounter) {
+ System.arraycopy(newInterfaces, 0, (newInterfaces = new ITypeBinding[interfacesCounter]), 0, interfacesCounter);
+ }
+ return this.interfaces = newInterfaces;
+ }
+ return this.interfaces = NO_TYPE_BINDINGS;
+ }
+
+ public IJavaElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element != null)
+ return element.resolved(this.binding);
+ if (isRecovered()) {
+ IPackageBinding packageBinding = getPackage();
+ if (packageBinding != null) {
+ final IJavaElement javaElement = packageBinding.getJavaElement();
+ if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+ // best effort: we don't know if the recovered binding is a binary or source binding, so go with a compilation unit
+ return ((PackageFragment) javaElement).getCompilationUnit(new String(this.binding.sourceName()) + SuffixConstants.SUFFIX_STRING_java);
+ }
+ }
+ return null;
+ }
+ return null;
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ return getUnresolvedJavaElement(this.binding);
+ }
+ private JavaElement getUnresolvedJavaElement(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding ) {
+ if (this.resolver instanceof DefaultBindingResolver) {
+ DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+ return org.eclipse.jdt.internal.core.util.Util.getUnresolvedJavaElement(
+ typeBinding,
+ defaultBindingResolver.workingCopyOwner,
+ defaultBindingResolver.getBindingsToNodesMap());
+ } else {
+ return org.eclipse.jdt.internal.core.util.Util.getUnresolvedJavaElement(typeBinding, null, null);
+ }
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.TYPE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ if (referenceBinding.isAnonymousType()) {
+ return accessFlags & ~Modifier.FINAL;
+ }
+ return accessFlags;
+ } else if (isAnnotation()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ // clear the AccAbstract, AccAnnotation and the AccInterface bits
+ return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation);
+ } else if (isInterface()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ // clear the AccAbstract and the AccInterface bits
+ return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface);
+ } else if (isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ // clear the AccEnum bits
+ return accessFlags & ~ClassFileConstants.AccEnum;
+ } else {
+ return Modifier.NONE;
+ }
+ }
+
+ public String getName() {
+ StringBuffer buffer;
+ switch (this.binding.kind()) {
+
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE:
+ WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+ buffer = new StringBuffer();
+ buffer.append(TypeConstants.WILDCARD_NAME);
+ if (wildcardBinding.bound != null) {
+ switch(wildcardBinding.boundKind) {
+ case Wildcard.SUPER :
+ buffer.append(TypeConstants.WILDCARD_SUPER);
+ break;
+ case Wildcard.EXTENDS :
+ buffer.append(TypeConstants.WILDCARD_EXTENDS);
+ }
+ buffer.append(getBound().getName());
+ }
+ return String.valueOf(buffer);
+
+ case Binding.TYPE_PARAMETER :
+ if (isCapture()) {
+ return NO_NAME;
+ }
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ return new String(typeVariableBinding.sourceName);
+
+ case Binding.PARAMETERIZED_TYPE :
+ ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+ buffer = new StringBuffer();
+ buffer.append(parameterizedTypeBinding.sourceName());
+ ITypeBinding[] tArguments = getTypeArguments();
+ final int typeArgumentsLength = tArguments.length;
+ if (typeArgumentsLength != 0) {
+ buffer.append('<');
+ for (int i = 0; i < typeArgumentsLength; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ }
+ buffer.append(tArguments[i].getName());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+
+ case Binding.RAW_TYPE :
+ return getTypeDeclaration().getName();
+
+ case Binding.ARRAY_TYPE :
+ ITypeBinding elementType = getElementType();
+ if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
+ return NO_NAME;
+ }
+ int dimensions = getDimensions();
+ char[] brackets = new char[dimensions * 2];
+ for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ buffer = new StringBuffer(elementType.getName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+
+ default :
+ if (isPrimitive() || isNullType()) {
+ BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+ return new String(baseTypeBinding.simpleName);
+ }
+ if (isAnonymous()) {
+ return NO_NAME;
+ }
+ return new String(this.binding.sourceName());
+ }
+ }
+
+ /*
+ * @see ITypeBinding#getPackage()
+ */
+ public IPackageBinding getPackage() {
+ switch (this.binding.kind()) {
+ case Binding.BASE_TYPE :
+ case Binding.ARRAY_TYPE :
+ case Binding.TYPE_PARAMETER : // includes capture scenario
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE:
+ return null;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return this.resolver.getPackageBinding(referenceBinding.getPackage());
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
+ */
+ public String getQualifiedName() {
+ StringBuffer buffer;
+ switch (this.binding.kind()) {
+
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE:
+ WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+ buffer = new StringBuffer();
+ buffer.append(TypeConstants.WILDCARD_NAME);
+ final ITypeBinding bound = getBound();
+ if (bound != null) {
+ switch(wildcardBinding.boundKind) {
+ case Wildcard.SUPER :
+ buffer.append(TypeConstants.WILDCARD_SUPER);
+ break;
+ case Wildcard.EXTENDS :
+ buffer.append(TypeConstants.WILDCARD_EXTENDS);
+ }
+ buffer.append(bound.getQualifiedName());
+ }
+ return String.valueOf(buffer);
+
+ case Binding.RAW_TYPE :
+ return getTypeDeclaration().getQualifiedName();
+
+ case Binding.ARRAY_TYPE :
+ ITypeBinding elementType = getElementType();
+ if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
+ return elementType.getQualifiedName();
+ }
+ final int dimensions = getDimensions();
+ char[] brackets = new char[dimensions * 2];
+ for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ buffer = new StringBuffer(elementType.getQualifiedName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+
+ case Binding.TYPE_PARAMETER :
+ if (isCapture()) {
+ return NO_NAME;
+ }
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ return new String(typeVariableBinding.sourceName);
+
+ case Binding.PARAMETERIZED_TYPE :
+ if (this.binding.isLocalType()) {
+ return NO_NAME;
+ }
+ buffer = new StringBuffer();
+ if (isMember()) {
+ buffer
+ .append(getDeclaringClass().getQualifiedName())
+ .append('.');
+ ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+ buffer.append(parameterizedTypeBinding.sourceName());
+ ITypeBinding[] tArguments = getTypeArguments();
+ final int typeArgumentsLength = tArguments.length;
+ if (typeArgumentsLength != 0) {
+ buffer.append('<');
+ for (int i = 0; i < typeArgumentsLength; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ }
+ buffer.append(tArguments[i].getQualifiedName());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+ }
+ buffer.append(getTypeDeclaration().getQualifiedName());
+ ITypeBinding[] tArguments = getTypeArguments();
+ final int typeArgumentsLength = tArguments.length;
+ if (typeArgumentsLength != 0) {
+ buffer.append('<');
+ for (int i = 0; i < typeArgumentsLength; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ }
+ buffer.append(tArguments[i].getQualifiedName());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+ default :
+ if (isAnonymous() || this.binding.isLocalType()) {
+ return NO_NAME;
+ }
+ if (isPrimitive() || isNullType()) {
+ BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+ return new String(baseTypeBinding.simpleName);
+ }
+ if (isMember()) {
+ buffer = new StringBuffer();
+ buffer
+ .append(getDeclaringClass().getQualifiedName())
+ .append('.');
+ buffer.append(getName());
+ return String.valueOf(buffer);
+ }
+ PackageBinding packageBinding = this.binding.getPackage();
+ buffer = new StringBuffer();
+ if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
+ buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
+ }
+ buffer.append(getName());
+ return String.valueOf(buffer);
+ }
+ }
+
+
+//{ObjectTeams: uniform handling of regular types names and anchored role type names:
+ public String getOptimalName() {
+ if (binding instanceof ReferenceBinding)
+ return new String(((ReferenceBinding)binding).optimalName());
+ return getQualifiedName();
+ }
+// SH}
+
+//{ObjectTeams: tsuper types for roles via role model:
+ public ITypeBinding[] getSuperRoles()
+ {
+ if (this.binding == null || !this.isRole())
+ {
+ return null;
+ }
+ if (binding instanceof ReferenceBinding)
+ {
+ RoleModel roleModel = ((ReferenceBinding)binding).roleModel;
+ ReferenceBinding[] tsuperRefs = roleModel.getTSuperRoleBindings();
+ int length = tsuperRefs.length;
+ ITypeBinding[] superRoles = new ITypeBinding[length];
+ for (int i = 0; i < length; i++)
+ {
+ superRoles[i] = this.resolver.getTypeBinding(tsuperRefs[i]);
+ }
+ return superRoles;
+ }
+ return null;
+ }
+// mkr}
+
+ /*
+ * @see ITypeBinding#getSuperclass()
+ */
+ public synchronized ITypeBinding getSuperclass() {
+ if (this.binding == null)
+ return null;
+ switch (this.binding.kind()) {
+ case Binding.ARRAY_TYPE :
+ case Binding.BASE_TYPE :
+ return null;
+ default:
+ // no superclass for interface types (interface | annotation type)
+ if (this.binding.isInterface())
+ return null;
+ }
+ ReferenceBinding superclass = null;
+ try {
+ superclass = ((ReferenceBinding)this.binding).superclass();
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the classpath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve superclass"); //$NON-NLS-1$
+ return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+ }
+ if (superclass == null) {
+ return null;
+ }
+ return this.resolver.getTypeBinding(superclass);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+ */
+ public ITypeBinding[] getTypeArguments() {
+ if (this.typeArguments != null) {
+ return this.typeArguments;
+ }
+ if (this.binding.isParameterizedTypeWithActualArguments()) {
+ ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+ final org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] arguments = parameterizedTypeBinding.arguments;
+ int argumentsLength = arguments.length;
+ ITypeBinding[] newTypeArguments = new ITypeBinding[argumentsLength];
+ for (int i = 0; i < argumentsLength; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(arguments[i]);
+ if (typeBinding == null) {
+ return this.typeArguments = NO_TYPE_BINDINGS;
+ }
+ newTypeArguments[i] = typeBinding;
+ }
+ return this.typeArguments = newTypeArguments;
+ }
+ return this.typeArguments = NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
+ */
+ public ITypeBinding[] getTypeBounds() {
+ if (this.bounds != null) {
+ return this.bounds;
+ }
+ if (this.binding instanceof TypeVariableBinding) {
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ ReferenceBinding varSuperclass = typeVariableBinding.superclass();
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding firstClassOrArrayBound = typeVariableBinding.firstBound;
+ int boundsLength = 0;
+ if (firstClassOrArrayBound != null) {
+ if (firstClassOrArrayBound == varSuperclass) {
+ boundsLength++;
+ } else if (firstClassOrArrayBound.isArrayType()) { // capture of ? extends/super arrayType
+ boundsLength++;
+ } else {
+ firstClassOrArrayBound = null;
+ }
+ }
+ ReferenceBinding[] superinterfaces = typeVariableBinding.superInterfaces();
+ int superinterfacesLength = 0;
+ if (superinterfaces != null) {
+ superinterfacesLength = superinterfaces.length;
+ boundsLength += superinterfacesLength;
+ }
+ if (boundsLength != 0) {
+ ITypeBinding[] typeBounds = new ITypeBinding[boundsLength];
+ int boundsIndex = 0;
+ if (firstClassOrArrayBound != null) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(firstClassOrArrayBound);
+ if (typeBinding == null) {
+ return this.bounds = NO_TYPE_BINDINGS;
+ }
+ typeBounds[boundsIndex++] = typeBinding;
+ }
+ if (superinterfaces != null) {
+ for (int i = 0; i < superinterfacesLength; i++, boundsIndex++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(superinterfaces[i]);
+ if (typeBinding == null) {
+ return this.bounds = NO_TYPE_BINDINGS;
+ }
+ typeBounds[boundsIndex] = typeBinding;
+ }
+ }
+ return this.bounds = typeBounds;
+ }
+ }
+ return this.bounds = NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+ */
+ public ITypeBinding[] getTypeParameters() {
+ if (this.typeParameters != null) {
+ return this.typeParameters;
+ }
+ switch(this.binding.kind()) {
+ case Binding.RAW_TYPE :
+ case Binding.PARAMETERIZED_TYPE :
+ return this.typeParameters = NO_TYPE_BINDINGS;
+ }
+ TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+ int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
+ if (typeVariableBindingsLength != 0) {
+ ITypeBinding[] newTypeParameters = new ITypeBinding[typeVariableBindingsLength];
+ for (int i = 0; i < typeVariableBindingsLength; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
+ if (typeBinding == null) {
+ return this.typeParameters = NO_TYPE_BINDINGS;
+ }
+ newTypeParameters[i] = typeBinding;
+ }
+ return this.typeParameters = newTypeParameters;
+ }
+ return this.typeParameters = NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getWildcard()
+ * @since 3.1
+ */
+ public ITypeBinding getWildcard() {
+ if (this.binding instanceof CaptureBinding) {
+ CaptureBinding captureBinding = (CaptureBinding) this.binding;
+ return this.resolver.getTypeBinding(captureBinding.wildcard);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
+ * @since 3.1
+ */
+ public boolean isGenericType() {
+ // equivalent to return getTypeParameters().length > 0;
+ if (isRawType()) {
+ return false;
+ }
+ TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+ return (typeVariableBindings != null && typeVariableBindings.length > 0);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return this.binding.isAnnotationType();
+ }
+
+ /*
+ * @see ITypeBinding#isAnonymous()
+ */
+ public boolean isAnonymous() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isAnonymousType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isArray()
+ */
+ public boolean isArray() {
+ return this.binding.isArrayType();
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
+ */
+ public boolean isAssignmentCompatible(ITypeBinding type) {
+ try {
+ if (this == type) return true;
+ if (!(type instanceof TypeBinding)) return false;
+ TypeBinding other = (TypeBinding) type;
+ Scope scope = this.resolver.scope();
+ if (scope == null) return false;
+ return this.binding.isCompatibleWith(other.binding) || scope.isBoxingCompatibleWith(this.binding, other.binding);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isCapture()
+ */
+ public boolean isCapture() {
+ return this.binding.isCapture();
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isCastCompatible(ITypeBinding)
+ */
+ public boolean isCastCompatible(ITypeBinding type) {
+ try {
+ Expression expression = new Expression() {
+ public StringBuffer printExpression(int indent,StringBuffer output) {
+ return null;
+ }
+ };
+ Scope scope = this.resolver.scope();
+ if (scope == null) return false;
+ if (!(type instanceof TypeBinding)) return false;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding expressionType = ((TypeBinding) type).binding;
+ // simulate capture in case checked binding did not properly get extracted from a reference
+ expressionType = expressionType.capture(scope, 0);
+ return expression.checkCastTypesCompatibility(scope, this.binding, expressionType, null);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /*
+ * @see ITypeBinding#isClass()
+ */
+ public boolean isClass() {
+ switch (this.binding.kind()) {
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE :
+ return false;
+ }
+ return this.binding.isClass();
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isDeprecated();
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isEnum()
+ */
+ public boolean isEnum() {
+ return this.binding.isEnum();
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ * @since 3.1
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof TypeBinding)) {
+ return false;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
+ // check return type
+ return BindingComparator.isEqual(this.binding, otherBinding);
+ }
+
+ /*
+ * @see ITypeBinding#isFromSource()
+ */
+ public boolean isFromSource() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ if (referenceBinding.isRawType()) {
+ return !((RawTypeBinding) referenceBinding).genericType().isBinaryBinding();
+ } else if (referenceBinding.isParameterizedType()) {
+ ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) referenceBinding;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding erasure = parameterizedTypeBinding.erasure();
+ if (erasure instanceof ReferenceBinding) {
+ return !((ReferenceBinding) erasure).isBinaryBinding();
+ }
+ return false;
+ } else {
+ return !referenceBinding.isBinaryBinding();
+ }
+ } else if (isTypeVariable()) {
+ final TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+ final Binding declaringElement = typeVariableBinding.declaringElement;
+ if (declaringElement instanceof MethodBinding) {
+ MethodBinding methodBinding = (MethodBinding) declaringElement;
+ return !methodBinding.declaringClass.isBinaryBinding();
+ } else {
+ final org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaringElement;
+ if (typeBinding instanceof ReferenceBinding) {
+ return !((ReferenceBinding) typeBinding).isBinaryBinding();
+ } else if (typeBinding instanceof ArrayBinding) {
+ final ArrayBinding arrayBinding = (ArrayBinding) typeBinding;
+ final org.eclipse.jdt.internal.compiler.lookup.TypeBinding leafComponentType = arrayBinding.leafComponentType;
+ if (leafComponentType instanceof ReferenceBinding) {
+ return !((ReferenceBinding) leafComponentType).isBinaryBinding();
+ }
+ }
+ }
+
+ } else if (isCapture()) {
+ CaptureBinding captureBinding = (CaptureBinding) this.binding;
+ return !captureBinding.sourceType.isBinaryBinding();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isInterface()
+ */
+ public boolean isInterface() {
+ switch (this.binding.kind()) {
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ case Binding.INTERSECTION_TYPE :
+ return false;
+ }
+ return this.binding.isInterface();
+ }
+
+//{ObjectTeams: ira
+ /*
+ * @see ITypeBinding#isTeam()
+ */
+ public boolean isTeam() {
+ return this.binding.isTeam();
+ }
+
+ /*
+ * @see ITypeBinding#isRole()
+ */
+ public boolean isRole() {
+ return this.binding.isRole();
+ }
+
+ /*
+ * @see ITypeBinding#isClassPartOf()
+ */
+ public boolean isClassPartOf (ITypeBinding other) {
+ if (this.binding == null || !this.binding.isRole())
+ return false;
+ RoleModel roleModel = ((ReferenceBinding)this.binding).roleModel;
+ if (roleModel == null)
+ return false;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding otherBinding = (other instanceof RecoveredTypeBinding)
+ ? ((RecoveredTypeBinding)other).getResolvedBinding()
+ : ((TypeBinding)other).binding;
+ return roleModel.getInterfacePartBinding() == otherBinding;
+ }
+ public boolean isSynthRoleIfc() {
+ if (this.binding == null || !this.binding.isRole())
+ return false;
+ return ((ReferenceBinding)this.binding).isSynthInterface();
+ }
+ /*
+ * @see ITypeBinding#getIfcPart()
+ */
+ public ITypeBinding getIfcPart() {
+ if (isInterface())
+ return this;
+ if (!isRole())
+ return null;
+ ReferenceBinding roleBinding = (ReferenceBinding) this.binding;
+ ReferenceBinding ifcPart = roleBinding.getRealType();
+ if (ifcPart == null)
+ return null;
+ return this.resolver.getTypeBinding(ifcPart);
+ }
+ /*
+ * @see ITypeBinding#getBaseClass()
+ */
+ public ITypeBinding getBaseClass() {
+ if (! this.binding.isRole())
+ return null;
+ MemberTypeBinding roleBinding = (MemberTypeBinding) this.binding;
+ ReferenceBinding baseclass = roleBinding.baseclass();
+ if (baseclass == null) {
+ return null;
+ }
+ return this.resolver.getTypeBinding(baseclass);
+ }
+// ira+SH}
+
+ /*
+ * @see ITypeBinding#isLocal()
+ */
+ public boolean isLocal() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isMember()
+ */
+ public boolean isMember() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isMemberType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isNested()
+ */
+ public boolean isNested() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isNestedType();
+ }
+ return false;
+ }
+
+ /**
+ * @see ITypeBinding#isNullType()
+ */
+ public boolean isNullType() {
+ return this.binding == org.eclipse.jdt.internal.compiler.lookup.TypeBinding.NULL;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ return this.binding.isParameterizedTypeWithActualArguments();
+ }
+
+//{ObjectTeams:
+ public boolean isDependentType(boolean onlyRelevant) {
+ if (onlyRelevant)
+ return RoleTypeBinding.isRoleWithExplicitAnchor(this.binding);
+ return DependentTypeBinding.isDependentType(this.binding);
+ }
+
+ public String[] getAnchorPath() {
+ if (!DependentTypeBinding.isDependentType(this.binding))
+ return new String[0];
+
+ return getBestNamePath((DependentTypeBinding)this.binding);
+ }
+
+ static String[] getBestNamePath(DependentTypeBinding dType) {
+ ITeamAnchor[] path = dType.getAnchor().getBestNamePath();
+ String[] segments = new String[path.length];
+ for (int i = 0; i < path.length; i++) {
+ segments[i] = new String(path[i].internalName());
+ }
+ return segments;
+ }
+// SH}
+ /*
+ * @see ITypeBinding#isPrimitive()
+ */
+ public boolean isPrimitive() {
+ return !isNullType() && this.binding.isBaseType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
+ */
+ public boolean isRawType() {
+ return this.binding.isRawType();
+ }
+
+ /* (non-Javadoc)
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return (this.binding.tagBits & TagBits.HasMissingType) != 0;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
+ */
+ public boolean isSubTypeCompatible(ITypeBinding type) {
+ try {
+ if (this == type) return true;
+ if (this.binding.isBaseType()) return false;
+ if (!(type instanceof TypeBinding)) return false;
+ TypeBinding other = (TypeBinding) type;
+ if (other.binding.isBaseType()) return false;
+ return this.binding.isCompatibleWith(other.binding);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /**
+ * @see IBinding#isSynthetic()
+ */
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isTopLevel()
+ */
+ public boolean isTopLevel() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return !referenceBinding.isNestedType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isTypeVariable()
+ */
+ public boolean isTypeVariable() {
+ return this.binding.isTypeVariable() && !this.binding.isCapture();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
+ */
+ public boolean isUpperbound() {
+ switch (this.binding.kind()) {
+ case Binding.WILDCARD_TYPE :
+ return ((WildcardBinding) this.binding).boundKind == Wildcard.EXTENDS;
+ case Binding.INTERSECTION_TYPE :
+ return true;
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+ */
+ public boolean isWildcardType() {
+ return this.binding.isWildcard();
+ }
+
+//{ObjectTeams: additional queries based on this.binding:
+ public IMethodMappingBinding[] getResolvedMethodMappings() {
+ List<IMethodMappingBinding> mappings = new ArrayList<IMethodMappingBinding>();
+ if (this.isRole()) {
+ org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding roleBinding
+ = (org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)this.binding;
+ if (roleBinding.callinCallouts != null) {
+ for (CallinCalloutBinding mapping : roleBinding.callinCallouts) {
+ mappings.add(this.resolver.getMethodMappingBinding(mapping));
+ }
+ }
+ }
+ IMethodMappingBinding[] result = new IMethodMappingBinding[mappings.size()];
+ if (!mappings.isEmpty())
+ mappings.toArray(result);
+ return result;
+ }
+// SH}
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
new file mode 100644
index 000000000..b72a70ff6
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
@@ -0,0 +1,1106 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: TypeDeclaration.java 23123 2009-12-01 23:57:01Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Type declaration AST node type. A type declaration
+ * is the union of a class declaration and an interface declaration.
+ * For JLS2:
+ * <pre>
+ * TypeDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * ClassDeclaration:
+ * [ Javadoc ] { Modifier } <b>class</b> Identifier
+ * [ <b>extends</b> Type]
+ * [ <b>implements</b> Type { <b>,</b> Type } ]
+ * <b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b>
+ * InterfaceDeclaration:
+ * [ Javadoc ] { Modifier } <b>interface</b> Identifier
+ * [ <b>extends</b> Type { <b>,</b> Type } ]
+ * <b>{</b> { InterfaceBodyDeclaration | <b>;</b> } <b>}</b>
+ * </pre>
+ * For JLS3, type parameters and reified modifiers
+ * (and annotations) were added, and the superclass type name and superinterface
+ * types names are generalized to type so that parameterized types can be
+ * referenced:
+ * <pre>
+ * TypeDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * ClassDeclaration:
+ * [ Javadoc ] { ExtendedModifier } <b>class</b> Identifier
+ * [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ * [ <b>extends</b> Type ]
+ * [ <b>implements</b> Type { <b>,</b> Type } ]
+ * <b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b>
+ * InterfaceDeclaration:
+ * [ Javadoc ] { ExtendedModifier } <b>interface</b> Identifier
+ * [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ * [ <b>extends</b> Type { <b>,</b> Type } ]
+ * <b>{</b> { InterfaceBodyDeclaration | <b>;</b> } <b>}</b>
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier or annotation (if any), or the
+ * first character of the "class" or "interface" keyword (if no
+ * modifiers or annotations). The source range extends through the last character of the "}"
+ * token following the body declarations.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeDeclaration extends AbstractTypeDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "interface" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor INTERFACE_PROPERTY =
+ new SimplePropertyDescriptor(TypeDeclaration.class, "interface", boolean.class, MANDATORY); //$NON-NLS-1$
+
+//{ObjectTeams: OT-specific properties
+ /**
+ * The "team" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor TEAM_PROPERTY =
+ new SimplePropertyDescriptor(TypeDeclaration.class, "team", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "role" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor ROLE_PROPERTY =
+ new SimplePropertyDescriptor(TypeDeclaration.class, "role", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "precedence" structural property.
+ */
+ public static final ChildListPropertyDescriptor PRECEDENCE_PROPERTY =
+ new ChildListPropertyDescriptor(TypeDeclaration.class, "precedence", PrecedenceDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "guardPredicate" structural property of this node type.
+ * @since 0.9.25
+ */
+ public static final ChildPropertyDescriptor GUARD_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclaration.class, "guardPredicate", GuardPredicateDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+//gbr+SH}
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "superclass" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclaration.class, "superclass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superInterfaces" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor SUPER_INTERFACES_PROPERTY =
+ new ChildListPropertyDescriptor(TypeDeclaration.class, "superInterfaces", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superclassType" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclaration.class, "superclassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superInterfaceTypes" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY =
+ new ChildListPropertyDescriptor(TypeDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeParameters" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(TypeDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "bodyDeclarations" structural property of this node type (added in JLS3 API).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ internalBodyDeclarationPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(12);
+ createPropertyList(TypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(INTERFACE_PROPERTY, propertyList);
+//{ObjectTeams: OT-specific properties added
+ addProperty(TEAM_PROPERTY, propertyList);
+ addProperty(ROLE_PROPERTY, propertyList);
+ addProperty(PRECEDENCE_PROPERTY, propertyList);
+ addProperty(GUARD_PROPERTY, propertyList);
+//gbr+SH}
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_PROPERTY, propertyList);
+ addProperty(SUPER_INTERFACES_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(13);
+ createPropertyList(TypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(INTERFACE_PROPERTY, propertyList);
+//{ObjectTeams: OT-specific properties added
+ addProperty(TEAM_PROPERTY, propertyList);
+ addProperty(ROLE_PROPERTY, propertyList);
+ addProperty(PRECEDENCE_PROPERTY, propertyList);
+ addProperty(GUARD_PROPERTY, propertyList);
+//gbr+SH}
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_TYPE_PROPERTY, propertyList);
+ addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * <code>true</code> for an interface, <code>false</code> for a class.
+ * Defaults to class.
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private boolean isInterface = false;
+ :giro */
+ boolean isInterface = false;
+// SH}
+
+//{ObjectTeams: OT-specific fields added
+ /**
+ * <code>true</code> for a team, <code>false</code> for a class.
+ * Defaults to class.
+ */
+ boolean _isTeam = false;
+
+ /**
+ * <code>true</code> for a role, <code>false</code> for a class.
+ * Defaults to class.
+ */
+ boolean _isRole = false;
+
+ ASTNode.NodeList _precedences = new ASTNode.NodeList(PRECEDENCE_PROPERTY);
+
+ GuardPredicateDeclaration optionalGuardPredicate = null;
+//gbr}
+
+ /**
+ * The type paramters (element type: <code>TypeParameter</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private ASTNode.NodeList typeParameters = null;
+ :giro */
+ ASTNode.NodeList typeParameters = null;
+// SH}
+ /**
+ * The optional superclass name; <code>null</code> if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Not used in 3.0.
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private Name optionalSuperclassName = null;
+ :giro */
+ Name optionalSuperclassName = null;
+// SH}
+ /**
+ * The superinterface names (element type: <code>Name</code>).
+ * JLS2 only; defaults to an empty list. Not used in JLS3.
+ * (see constructor).
+ *
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private ASTNode.NodeList superInterfaceNames = null;
+ :giro */
+ ASTNode.NodeList superInterfaceNames = null;
+// SH}
+ /**
+ * The optional superclass type; <code>null</code> if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Null in JLS2. Added in JLS3.
+ * @since 3.1
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private Type optionalSuperclassType = null;
+ :giro */
+ Type optionalSuperclassType = null;
+// SH}
+ /**
+ * The superinterface types (element type: <code>Type</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+//{ObjectTeams: avoid private to allow access from RoleTypeDeclaration without duplicating this field
+/* orig:
+ private ASTNode.NodeList superInterfaceTypes = null;
+ :giro */
+ ASTNode.NodeList superInterfaceTypes = null;
+// SH}
+ /**
+ * Creates a new AST node for a type declaration owned by the given
+ * AST. By default, the type declaration is for a class of an
+ * unspecified, but legal, name; no modifiers; no javadoc;
+ * no type parameters; no superclass or superinterfaces; and an empty list
+ * of body declarations.
+ * <p>
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel == AST.JLS2_INTERNAL) {
+ this.superInterfaceNames = new ASTNode.NodeList(SUPER_INTERFACES_PROPERTY);
+ }
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+ this.superInterfaceTypes = new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+//ike}
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// {ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+// ike}
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// {ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+// ike}
+ if (property == INTERFACE_PROPERTY) {
+ if (get) {
+ return isInterface();
+ } else {
+ setInterface(value);
+ return false;
+ }
+ }
+//{ObjectTeams: cases for OT-specific properties added
+ if (property == TEAM_PROPERTY)
+ {
+ if (get)
+ {
+ return isTeam();
+ }
+ else
+ {
+ setTeam(value);
+ return false;
+ }
+ }
+ if (property == ROLE_PROPERTY)
+ {
+ if (get)
+ {
+ return isRole();
+ }
+ else
+ {
+ setRole(value);
+ return false;
+ }
+ }
+//gbr}
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// {ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+// ike}
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((Javadoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_PROPERTY) {
+ if (get) {
+ return getSuperclass();
+ } else {
+ setSuperclass((Name) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_TYPE_PROPERTY) {
+ if (get) {
+ return getSuperclassType();
+ } else {
+ setSuperclassType((Type) child);
+ return null;
+ }
+ }
+//{ObjectTeams:
+ if (property == internalGuardPredicateProperty())
+ {
+ if (get) {
+ return getGuardPredicate();
+ } else {
+ setGuardPredicate((GuardPredicateDeclaration) child);
+ return null;
+ }
+ }
+// SH}
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// {ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ List internalGetChildListProperty(ChildListPropertyDescriptor property)
+// ike}
+ {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == TYPE_PARAMETERS_PROPERTY) {
+ return typeParameters();
+ }
+ if (property == SUPER_INTERFACES_PROPERTY) {
+ return superInterfaces();
+ }
+ if (property == SUPER_INTERFACE_TYPES_PROPERTY) {
+ return superInterfaceTypes();
+ }
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+//{ObjectTeams: precedence:
+ if (property == internalPrecedenceProperty()) {
+ return precedences();
+ }
+// SH}
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ ChildPropertyDescriptor internalJavadocProperty()
+ {
+//ike}
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ ChildListPropertyDescriptor internalModifiers2Property()
+ {
+//ike}
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ SimplePropertyDescriptor internalModifiersProperty()
+ {
+//ike}
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ ChildPropertyDescriptor internalNameProperty()
+ {
+//ike}
+ return NAME_PROPERTY;
+ }
+
+//{ObjectTeams: new elements
+ ChildPropertyDescriptor internalGuardPredicateProperty() {
+ return GUARD_PROPERTY;
+ }
+ ChildListPropertyDescriptor internalPrecedenceProperty() {
+ return PRECEDENCE_PROPERTY;
+ }
+// SH}
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ ChildListPropertyDescriptor internalBodyDeclarationsProperty()
+ {
+//ike}
+ return BODY_DECLARATIONS_PROPERTY;
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+//{ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ int getNodeType0()
+ {
+//ike}
+ return TYPE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ @SuppressWarnings("unchecked")
+ ASTNode clone0(AST target) {
+ TypeDeclaration result = new TypeDeclaration(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setJavadoc(
+ (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ result.setSuperclass(
+ (Name) ASTNode.copySubtree(target, getSuperclass()));
+ result.superInterfaces().addAll(
+ ASTNode.copySubtrees(target, superInterfaces()));
+ }
+ result.setInterface(isInterface());
+//{ObjectTeams: set OT-specific features (team, role) if true
+ result.setTeam(isTeam());
+ result.setRole(isRole());
+ result.precedences().addAll(ASTNode.copySubtrees(target, precedences()));
+ result.setGuardPredicate((GuardPredicateDeclaration)ASTNode.copySubtree(target, getGuardPredicate()));
+//gbr}
+ result.setName((SimpleName) getName().clone(target));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.typeParameters().addAll(
+ ASTNode.copySubtrees(target, typeParameters()));
+ result.setSuperclassType(
+ (Type) ASTNode.copySubtree(target, getSuperclassType()));
+ result.superInterfaceTypes().addAll(
+ ASTNode.copySubtrees(target, superInterfaceTypes()));
+ }
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// {ObjectTeams: RoleTypeDeclaration can not inherit all methods, so final modifier removed
+ /*final*/ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+//ike}
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getJavadoc());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getSuperclass());
+ acceptChildren(visitor, this.superInterfaceNames);
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.typeParameters);
+ acceptChild(visitor, getSuperclassType());
+ acceptChildren(visitor, this.superInterfaceTypes);
+ acceptChildren(visitor, this.bodyDeclarations);
+//{ObjectTeams:
+ acceptChild(visitor, this.getGuardPredicate());
+ acceptChildren(visitor, this._precedences);
+// SH}
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+//{ObjectTeams: convenience methods for dealing with OT-specific types, i.e. teams/roles
+ /**
+ * Returns whether this type declaration declares a team class or a class.
+ *
+ * @return <code>true</code> if this is a team class declaration,
+ * and <code>false</code> if this is a class declaration
+ */
+ @Override
+ public boolean isTeam()
+ {
+ return _isTeam;
+ }
+
+ /**
+ * Sets wether this type declaration declares a team class or a class.
+ *
+ * @param isTeam <code>true</code> if this is a team class
+ * declaration, and <code>false</code> if this is a class declaration
+ */
+ public void setTeam(boolean isTeam)
+ {
+ preValueChange(TEAM_PROPERTY);
+ _isTeam = isTeam;
+ postValueChange(TEAM_PROPERTY);
+ }
+
+ /**
+ * Returns whether this type declaration declares a role class or a class.
+ *
+ * @return <code>true</code> if this is a role class declaration,
+ * and <code>false</code> if this is a class declaration
+ */
+ @Override
+ public boolean isRole()
+ {
+ return _isRole;
+ }
+
+ /**
+ * Sets whether this type declaration declares a role class or a class.
+ *
+ * @param isRole <code>true</code> if this is a role class
+ * declaration, and <code>false</code> if this is a class declaration
+ */
+ public void setRole(boolean isRole)
+ {
+ preValueChange(ROLE_PROPERTY);
+ _isRole = isRole;
+ postValueChange(ROLE_PROPERTY);
+ }
+
+ public List precedences() {
+ return _precedences;
+ }
+//gbr}
+
+ /**
+ * Returns whether this type declaration declares a class or an
+ * interface.
+ *
+ * @return <code>true</code> if this is an interface declaration,
+ * and <code>false</code> if this is a class declaration
+ */
+ public boolean isInterface() {
+ return this.isInterface;
+ }
+
+ /**
+ * Sets whether this type declaration declares a class or an
+ * interface.
+ *
+ * @param isInterface <code>true</code> if this is an interface
+ * declaration, and <code>false</code> if this is a class
+ * declaration
+ */
+ public void setInterface(boolean isInterface) {
+ preValueChange(INTERFACE_PROPERTY);
+ this.isInterface = isInterface;
+ postValueChange(INTERFACE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type parameters of this type
+ * declaration (added in JLS3 API). This list is non-empty for parameterized types.
+ *
+ * @return the live list of type parameters
+ * (element type: <code>TypeParameter</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List typeParameters() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeParameters == null) {
+ unsupportedIn2();
+ }
+ return this.typeParameters;
+ }
+
+ /**
+ * Returns the name of the superclass declared in this type
+ * declaration, or <code>null</code> if there is none (JLS2 API only).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @return the superclass name node, or <code>null</code> if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getSuperclassType()}, which returns a <code>Type</code>
+ * instead of a <code>Name</code>.
+ */
+ public Name getSuperclass() {
+ return internalGetSuperclass();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final Name internalGetSuperclass() {
+ supportedOnlyIn2();
+ return this.optionalSuperclassName;
+ }
+
+ /**
+ * Returns the superclass declared in this type
+ * declaration, or <code>null</code> if there is none (added in JLS3 API).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @return the superclass type node, or <code>null</code> if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public Type getSuperclassType() {
+ unsupportedIn2();
+ return this.optionalSuperclassType;
+ }
+
+ /**
+ * Sets or clears the name of the superclass declared in this type
+ * declaration (JLS2 API only).
+ * <p>
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ * </p>
+ *
+ * @param superclassName the superclass name node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setSuperclassType(Type)}, which expects a
+ * <code>Type</code> instead of a <code>Name</code>.
+ */
+ public void setSuperclass(Name superclassName) {
+ internalSetSuperclass(superclassName);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetSuperclass(Name superclassName) {
+ supportedOnlyIn2();
+ ASTNode oldChild = this.optionalSuperclassName;
+ preReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ this.optionalSuperclassName = superclassName;
+ postReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ }
+
+ /**
+ * Sets or clears the superclass declared in this type
+ * declaration (added in JLS3 API).
+ * <p>
+ * Note that this child is not relevant for interface declarations
+ * (although it does still figure in subtree equality comparisons).
+ * </p>
+ *
+ * @param superclassType the superclass type node, or <code>null</code> if
+ * there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public void setSuperclassType(Type superclassType) {
+ unsupportedIn2();
+ ASTNode oldChild = this.optionalSuperclassType;
+ preReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ this.optionalSuperclassType = superclassType;
+ postReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of names of superinterfaces of this type
+ * declaration (JLS2 API only). For a class declaration, these are the names
+ * of the interfaces that this class implements; for an interface
+ * declaration, these are the names of the interfaces that this interface
+ * extends.
+ *
+ * @return the live list of interface names
+ * (element type: <code>Name</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #superInterfaceTypes()}.
+ */
+ public List superInterfaces() {
+ return internalSuperInterfaces();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final List internalSuperInterfaces() {
+ // more efficient than just calling supportedOnlyIn2() to check
+ if (this.superInterfaceNames == null) {
+ supportedOnlyIn2();
+ }
+ return this.superInterfaceNames;
+ }
+
+ /**
+ * Returns the live ordered list of superinterfaces of this type
+ * declaration (added in JLS3 API). For a class declaration, these are the interfaces
+ * that this class implements; for an interface declaration,
+ * these are the interfaces that this interface extends.
+ *
+ * @return the live list of interface types
+ * (element type: <code>Type</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List superInterfaceTypes() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.superInterfaceTypes == null) {
+ unsupportedIn2();
+ }
+ return this.superInterfaceTypes;
+ }
+
+ /**
+ * Returns the ordered list of field declarations of this type
+ * declaration. For a class declaration, these are the
+ * field declarations; for an interface declaration, these are
+ * the constant declarations.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-fields filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of field declarations
+ */
+ public FieldDeclaration[] getFields() {
+ List bd = bodyDeclarations();
+ int fieldCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof FieldDeclaration) {
+ fieldCount++;
+ }
+ }
+ FieldDeclaration[] fields = new FieldDeclaration[fieldCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof FieldDeclaration) {
+ fields[next++] = (FieldDeclaration) decl;
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * Returns the ordered list of method declarations of this type
+ * declaration.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-methods filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of method (and constructor)
+ * declarations
+ */
+ public MethodDeclaration[] getMethods() {
+ List bd = bodyDeclarations();
+ int methodCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof MethodDeclaration) {
+ methodCount++;
+ }
+ }
+ MethodDeclaration[] methods = new MethodDeclaration[methodCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof MethodDeclaration) {
+ methods[next++] = (MethodDeclaration) decl;
+ }
+ }
+ return methods;
+ }
+
+//{ObjectTeams: method getRoles()
+ /**
+ * Returns the ordered list of role type declarations of this type
+ * declaration.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-roles filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of role type declarations
+ */
+ public RoleTypeDeclaration[] getRoles() {
+ List bd = bodyDeclarations();
+ int roleCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof RoleTypeDeclaration) {
+ roleCount++;
+ }
+ }
+ RoleTypeDeclaration[] roles = new RoleTypeDeclaration[roleCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof RoleTypeDeclaration) {
+ roles[next++] = (RoleTypeDeclaration) decl;
+ }
+ }
+ return roles;
+ }
+
+ public void setGuardPredicate(GuardPredicateDeclaration predicate) {
+ ASTNode oldChild = this.optionalGuardPredicate;
+ preReplaceChild(oldChild, predicate, internalGuardPredicateProperty());
+ this.optionalGuardPredicate = predicate;
+ postReplaceChild(oldChild, predicate, internalGuardPredicateProperty());
+ }
+
+ public GuardPredicateDeclaration getGuardPredicate() {
+ return optionalGuardPredicate;
+ }
+
+//jsv}
+
+ /**
+ * Returns the ordered list of member type declarations of this type
+ * declaration.
+ * <p>
+ * This convenience method returns this node's body declarations
+ * with non-types filtered out. Unlike <code>bodyDeclarations</code>,
+ * this method does not return a live result.
+ * </p>
+ *
+ * @return the (possibly empty) list of member type declarations
+ */
+ public TypeDeclaration[] getTypes() {
+ List bd = bodyDeclarations();
+ int typeCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof TypeDeclaration) {
+ typeCount++;
+ }
+ }
+ TypeDeclaration[] memberTypes = new TypeDeclaration[typeCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof TypeDeclaration) {
+ memberTypes[next++] = (TypeDeclaration) decl;
+ }
+ }
+ return memberTypes;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AsbtractTypeDeclaration.
+ */
+ ITypeBinding internalResolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 6 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
+ + (this.optionalSuperclassName == null ? 0 : getSuperclass().treeSize())
+ + (this.optionalSuperclassType == null ? 0 : getSuperclassType().treeSize())
+ + (this.superInterfaceNames == null ? 0 : this.superInterfaceNames.listSize())
+ + (this.superInterfaceTypes == null ? 0 : this.superInterfaceTypes.listSize())
+//{ObjectTeams:
+ + (this.optionalGuardPredicate == null ? 0 : this.optionalGuardPredicate.treeSize())
+ + this._precedences.listSize()
+// SH}
+ + this.bodyDeclarations.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java
new file mode 100644
index 000000000..107800c0a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclarationStatement.java
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Local type declaration statement AST node type.
+ * <p>
+ * This kind of node is used to convert a type declaration
+ * node into a statement node by wrapping it.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * TypeDeclarationStatement:
+ * TypeDeclaration
+ * </pre>
+ * For JLS3, the kinds of type declarations grew to include enum declarations:
+ * <pre>
+ * TypeDeclarationStatement:
+ * TypeDeclaration
+ * EnumDeclaration
+ * </pre>
+ * Although allowed at the AST, not all arrangements of AST nodes are meaningful;
+ * in particular, only class and enum declarations are meaningful in the context of
+ * a block.
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeDeclarationStatement extends Statement {
+
+ /**
+ * The "typeDeclaration" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclarationStatement.class, "typeDeclaration", TypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "declaration" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildPropertyDescriptor DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclarationStatement.class, "declaration", AbstractTypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TypeDeclarationStatement.class, propertyList);
+ addProperty(TYPE_DECLARATION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(2);
+ createPropertyList(TypeDeclarationStatement.class, propertyList);
+ addProperty(DECLARATION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type declaration; lazily initialized; defaults to a unspecified,
+ * but legal, type declaration. In JLS2, corresponds to TYPE_DECLARATION_PROPERTY.
+ * After JLS2, corresponds to DECLARATION_PROPERTY.
+ * @see #typeDeclProperty
+ */
+ private AbstractTypeDeclaration typeDecl = null;
+
+ /**
+ * The child property stored on the <code>typeDecl</code> instance variable.
+ * In JLS2, corresponds to TYPE_DECLARATION_PROPERTY. After JLS2, corresponds to
+ * DECLARATION_PROPERTY.
+ *
+ * @return the property corresponding to the <code>typeDecl</code> instance variable;
+ * never <code>null</code>
+ */
+ private ChildPropertyDescriptor typeDeclProperty () {
+ if (getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ return TYPE_DECLARATION_PROPERTY;
+ } else {
+ return DECLARATION_PROPERTY;
+ }
+ }
+
+
+ /**
+ * Creates a new unparented local type declaration statement node owned
+ * by the given AST. By default, the local type declaration is an
+ * unspecified, but legal, type declaration.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeDeclarationStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ * @since 3.0
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_DECLARATION_PROPERTY) {
+ if (get) {
+ return getTypeDeclaration();
+ } else {
+ setTypeDeclaration((TypeDeclaration) child);
+ return null;
+ }
+ }
+ if (property == DECLARATION_PROPERTY) {
+ if (get) {
+ return getDeclaration();
+ } else {
+ setDeclaration((AbstractTypeDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_DECLARATION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeDeclarationStatement result =
+ new TypeDeclarationStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setDeclaration(
+ (AbstractTypeDeclaration) getDeclaration().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getDeclaration());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the abstract type declaration of this local type declaration
+ * statement (added in JLS3 API).
+ *
+ * @return the type declaration node
+ * @since 3.1
+ */
+ public AbstractTypeDeclaration getDeclaration() {
+ if (this.typeDecl == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeDecl == null) {
+ preLazyInit();
+ this.typeDecl = new TypeDeclaration(this.ast);
+ postLazyInit(this.typeDecl, typeDeclProperty());
+ }
+ }
+ }
+ return this.typeDecl;
+ }
+
+ /**
+ * Sets the abstract type declaration of this local type declaration
+ * statement (added in JLS3 API).
+ *
+ * @param decl the type declaration node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ * @since 3.1
+ */
+ public void setDeclaration(AbstractTypeDeclaration decl) {
+ if (decl == null) {
+ throw new IllegalArgumentException();
+ }
+ // a TypeDeclarationStatement may occur inside an
+ // TypeDeclaration - must check cycles
+ ASTNode oldChild = this.typeDecl;
+ ChildPropertyDescriptor typeDeclProperty = typeDeclProperty();
+ preReplaceChild(oldChild, decl, typeDeclProperty);
+ this.typeDecl= decl;
+ postReplaceChild(oldChild, decl, typeDeclProperty);
+ }
+
+ /**
+ * Returns the type declaration of this local type declaration
+ * statement (JLS2 API only).
+ *
+ * @return the type declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getDeclaration()}, which returns <code>AbstractTypeDeclaration</code>
+ * instead of <code>TypeDeclaration</code>.
+ */
+ public TypeDeclaration getTypeDeclaration() {
+ return internalGetTypeDeclaration();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final TypeDeclaration internalGetTypeDeclaration() {
+ supportedOnlyIn2();
+ return (TypeDeclaration) getDeclaration();
+ }
+
+ /**
+ * Sets the type declaration of this local type declaration
+ * statement (JLS2 API only).
+ *
+ * @param decl the type declaration node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setDeclaration(AbstractTypeDeclaration)} which takes
+ * <code>AbstractTypeDeclaration</code> instead of
+ * <code>TypeDeclaration</code>.
+ */
+ public void setTypeDeclaration(TypeDeclaration decl) {
+ internalSetTypeDeclaration(decl);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetTypeDeclaration(TypeDeclaration decl) {
+ supportedOnlyIn2();
+ // forward to non-deprecated replacement method
+ setDeclaration(decl);
+ }
+
+ /**
+ * Resolves and returns the binding for the class or interface declared in
+ * this type declaration statement.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public ITypeBinding resolveBinding() {
+ // forward request to the wrapped type declaration
+ AbstractTypeDeclaration d = getDeclaration();
+ if (d instanceof TypeDeclaration) {
+ return ((TypeDeclaration) d).resolveBinding();
+ } else if (d instanceof AnnotationTypeDeclaration) {
+ return ((AnnotationTypeDeclaration) d).resolveBinding();
+ } else {
+ // shouldn't happen
+ return null;
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeDecl == null ? 0 : getDeclaration().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
new file mode 100644
index 000000000..fca75acb7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type literal AST node type.
+ *
+ * <pre>
+ * TypeLiteral:
+ * ( Type | <b>void</b> ) <b>.</b> <b>class</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeLiteral extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(TypeLiteral.class, "type", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TypeLiteral.class, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Creates a new AST node for a type literal owned by the given
+ * AST. By default, the expression has an unspecified (but legal) type.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeLiteral result = new TypeLiteral(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setType((Type) getType().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getType());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type in this type literal expression.
+ *
+ * @return the type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type in this type literal expression to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.type == null ? 0 : getType().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
new file mode 100644
index 000000000..940302dd1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type parameter node (added in JLS3 API).
+ * <pre>
+ * TypeParameter:
+ * TypeVariable [ <b>extends</b> Type { <b>&</b> Type } ]
+ * </pre>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeParameter extends ASTNode {
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(TypeParameter.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeBounds" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor TYPE_BOUNDS_PROPERTY =
+ new ChildListPropertyDescriptor(TypeParameter.class, "typeBounds", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+//{ObjectTeams: distinguish value parameters and <B base R>:
+ public static final SimplePropertyDescriptor VALUE_PARAMETER_PROPERTY =
+ new SimplePropertyDescriptor(TypeParameter.class, "valueParameter", boolean.class, MANDATORY); //$NON-NLS-1$
+ public static final SimplePropertyDescriptor BASE_BOUND_PROPERTY =
+ new SimplePropertyDescriptor(TypeParameter.class, "baseBound", boolean.class, MANDATORY); //$NON-NLS-1$
+// SH}
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(TypeParameter.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(TYPE_BOUNDS_PROPERTY, propertyList);
+//{ObjectTeams: value parameter:
+ addProperty(VALUE_PARAMETER_PROPERTY, propertyList);
+// SH}
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+//{ObjectTeams: value parameter, <B base R>:
+ private boolean isValueParameter= false;
+ private boolean hasBaseBound= false;
+//SH}
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type variable node; lazily initialized; defaults to an unspecfied,
+ * but legal, name.
+ */
+ private SimpleName typeVariableName = null;
+
+ /**
+ * The type bounds (element type: <code>Type</code>).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList typeBounds =
+ new ASTNode.NodeList(TYPE_BOUNDS_PROPERTY);
+
+ /**
+ * Creates a new unparented node for a parameterized type owned by the
+ * given AST. By default, an unspecified, but legal, type variable name,
+ * and no type bounds.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeParameter(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+//{ObjectTeams: value parameter?
+ boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == VALUE_PARAMETER_PROPERTY) {
+ if (get) {
+ return isValueParameter();
+ } else {
+ setIsValueParameter(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+// SH}
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == TYPE_BOUNDS_PROPERTY) {
+ return typeBounds();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_PARAMETER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeParameter result = new TypeParameter(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+//{ObjectTeams: value parameter?
+ result.setIsValueParameter(this.isValueParameter());
+// SH}
+ result.typeBounds().addAll(
+ ASTNode.copySubtrees(target, typeBounds()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.typeBounds);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of the type variable declared in this type parameter.
+ *
+ * @return the name of the type variable
+ */
+ public SimpleName getName() {
+ if (this.typeVariableName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeVariableName == null) {
+ preLazyInit();
+ this.typeVariableName = new SimpleName(this.ast);
+ postLazyInit(this.typeVariableName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.typeVariableName;
+ }
+
+ /**
+ * Resolves and returns the binding for this type parameter.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public final ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveTypeParameter(this);
+ }
+
+ /**
+ * Sets the name of the type variable of this type parameter to the given
+ * name.
+ *
+ * @param typeName the new name of this type parameter
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeVariableName;
+ preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ this.typeVariableName = typeName;
+ postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type bounds of this type parameter.
+ * For the type parameter to be plausible, there can be at most one
+ * class in the list, and it must be first, and the remaining ones must be
+ * interfaces; the list should not contain primitive types (but array types
+ * and parameterized types are allowed).
+ *
+ * @return the live list of type bounds
+ * (element type: <code>Type</code>)
+ */
+ public List typeBounds() {
+ return this.typeBounds;
+ }
+
+//{ObjectTeams: value parameters & <B base R>:
+ /**
+ * Returns whether this type parameter is a value parameter.
+ */
+ public boolean isValueParameter() {
+ return this.isValueParameter;
+ }
+
+ /**
+ * Sets whether this type parameter is a value parameter.
+ */
+ public void setIsValueParameter(boolean isValueParameter) {
+ preValueChange(VALUE_PARAMETER_PROPERTY);
+ this.isValueParameter= isValueParameter;
+ postValueChange(VALUE_PARAMETER_PROPERTY);
+ }
+
+ /**
+ * Returns whether this type parameter has a "base" bound.
+ */
+ public boolean hasBaseBound() {
+ return this.hasBaseBound;
+ }
+
+ /**
+ * Sets whether this type parameter has a "base" bound.
+ */
+ public void setHasBaseBound(boolean hasBaseBound) {
+ preValueChange(BASE_BOUND_PROPERTY);
+ this.hasBaseBound = hasBaseBound;
+ postValueChange(BASE_BOUND_PROPERTY);
+ }
+// SH}
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeVariableName == null ? 0 : getName().treeSize())
+ + this.typeBounds.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
new file mode 100644
index 000000000..510fa0e9e
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.util.IModifierConstants;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.LocalVariable;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * Internal implementation of variable bindings.
+ */
+class VariableBinding implements IVariableBinding {
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
+
+ private org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding;
+ private ITypeBinding declaringClass;
+ private String key;
+ private String name;
+ private BindingResolver resolver;
+ private ITypeBinding type;
+ private IAnnotationBinding[] annotations;
+
+ VariableBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
+ this.resolver = resolver;
+ this.binding = binding;
+ }
+
+ public IAnnotationBinding[] getAnnotations() {
+ if (this.annotations != null) {
+ return this.annotations;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
+ int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+ if (length != 0) {
+ IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+ int convertedAnnotationCount = 0;
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+ final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+ if (annotationInstance == null) {
+ continue;
+ }
+ tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+ }
+ if (convertedAnnotationCount != length) {
+ if (convertedAnnotationCount == 0) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+ }
+ return this.annotations = tempAnnotations;
+ }
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+
+ /* (non-Javadoc)
+ * @see IVariableBinding#getConstantValue()
+ * @since 3.0
+ */
+ public Object getConstantValue() {
+ Constant c = this.binding.constant();
+ if (c == null || c == Constant.NotAConstant) return null;
+ switch (c.typeID()) {
+ case TypeIds.T_boolean:
+ return Boolean.valueOf(c.booleanValue());
+ case TypeIds.T_byte:
+ return new Byte(c.byteValue());
+ case TypeIds.T_char:
+ return new Character(c.charValue());
+ case TypeIds.T_double:
+ return new Double(c.doubleValue());
+ case TypeIds.T_float:
+ return new Float(c.floatValue());
+ case TypeIds.T_int:
+ return new Integer(c.intValue());
+ case TypeIds.T_long:
+ return new Long(c.longValue());
+ case TypeIds.T_short:
+ return new Short(c.shortValue());
+ case TypeIds.T_JavaLangString:
+ return c.stringValue();
+ }
+ return null;
+ }
+
+ /*
+ * @see IVariableBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ if (isField()) {
+ if (this.declaringClass == null) {
+ FieldBinding fieldBinding = (FieldBinding) this.binding;
+ this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
+ }
+ return this.declaringClass;
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * @see IVariableBinding#getDeclaringMethod()
+ */
+ public IMethodBinding getDeclaringMethod() {
+ if (!isField()) {
+ ASTNode node = this.resolver.findDeclaringNode(this);
+ while (true) {
+ if (node == null) break;
+ switch(node.getNodeType()) {
+ case ASTNode.INITIALIZER :
+ return null;
+ case ASTNode.METHOD_DECLARATION :
+ MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+ return methodDeclaration.resolveBinding();
+ default:
+ node = node.getParent();
+ }
+ }
+ }
+ return null;
+ }
+//{ObjectTeams: similar to #getDeclaringMethod()
+ public MethodMappingElement getDeclaringMethodSpec() {
+ if (!isField()) {
+ ASTNode node = this.resolver.findDeclaringNode(this);
+ while (true) {
+ if (node == null) break;
+ switch(node.getNodeType()) {
+ case ASTNode.METHOD_SPEC:
+ return (MethodSpec) node;
+ default:
+ node = node.getParent();
+ }
+ }
+ }
+ return null;
+ }
+// SH}
+
+ /*
+ * @see IBinding#getJavaElement()
+ */
+ public IJavaElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.VARIABLE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ if (isField()) {
+ return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
+ }
+ if (this.binding.isFinal()) {
+ return IModifierConstants.ACC_FINAL;
+ }
+ return Modifier.NONE;
+ }
+
+ /*
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (this.name == null) {
+ this.name = new String(this.binding.name);
+ }
+ return this.name;
+ }
+
+ /*
+ * @see IVariableBinding#getType()
+ */
+ public ITypeBinding getType() {
+ if (this.type == null) {
+ this.type = this.resolver.getTypeBinding(this.binding.type);
+ }
+ return this.type;
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ if (isField()) {
+ if (this.resolver instanceof DefaultBindingResolver) {
+ DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+ return Util.getUnresolvedJavaElement(
+ (FieldBinding) this.binding,
+ defaultBindingResolver.workingCopyOwner,
+ defaultBindingResolver.getBindingsToNodesMap());
+ } else {
+ return Util.getUnresolvedJavaElement((FieldBinding) this.binding, null, null);
+ }
+ }
+ // local variable
+ if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+ VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+ if (localVar == null) return null;
+ int nameStart;
+ int nameLength;
+ int sourceStart;
+ int sourceLength;
+ if (localVar instanceof SingleVariableDeclaration) {
+ sourceStart = localVar.getStartPosition();
+ sourceLength = localVar.getLength();
+ SimpleName simpleName = ((SingleVariableDeclaration) localVar).getName();
+ nameStart = simpleName.getStartPosition();
+ nameLength = simpleName.getLength();
+ } else {
+ nameStart = localVar.getStartPosition();
+ nameLength = localVar.getLength();
+ ASTNode node = localVar.getParent();
+ sourceStart = node.getStartPosition();
+ sourceLength = node.getLength();
+ }
+ int sourceEnd = sourceStart+sourceLength-1;
+ char[] typeSig = this.binding.type.genericTypeSignature();
+ JavaElement parent = null;
+ IMethodBinding declaringMethod = getDeclaringMethod();
+ if (declaringMethod == null) {
+ ReferenceContext referenceContext = ((LocalVariableBinding) this.binding).declaringScope.referenceContext();
+ if (referenceContext instanceof TypeDeclaration){
+ // Local variable is declared inside an initializer
+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
+ JavaElement typeHandle = null;
+ if (this.resolver instanceof DefaultBindingResolver) {
+ DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+ typeHandle = Util.getUnresolvedJavaElement(
+ typeDeclaration.binding,
+ defaultBindingResolver.workingCopyOwner,
+ defaultBindingResolver.getBindingsToNodesMap());
+ } else {
+ typeHandle = Util.getUnresolvedJavaElement(typeDeclaration.binding, null, null);
+ }
+ parent = Util.getUnresolvedJavaElement(sourceStart, sourceEnd, typeHandle);
+ } else {
+ return null;
+ }
+ } else {
+ parent = (JavaElement) declaringMethod.getJavaElement();
+ }
+ if (parent == null) return null;
+ return new LocalVariable(parent, localVar.getName().getIdentifier(), sourceStart, sourceEnd, nameStart, nameStart+nameLength-1, new String(typeSig), ((LocalVariableBinding) this.binding).declaration.annotations);
+ }
+
+ /*
+ * @see IVariableBinding#getVariableDeclaration()
+ * @since 3.1
+ */
+ public IVariableBinding getVariableDeclaration() {
+ if (isField()) {
+ FieldBinding fieldBinding = (FieldBinding) this.binding;
+ return this.resolver.getVariableBinding(fieldBinding.original());
+ }
+ return this;
+ }
+
+ /*
+ * @see IVariableBinding#getVariableId()
+ */
+ public int getVariableId() {
+ return this.binding.id;
+ }
+
+ /*
+ * @see IVariableBinding#isParameter()
+ */
+ public boolean isParameter() {
+ return (this.binding.tagBits & TagBits.IsArgument) != 0;
+ }
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ if (isField()) {
+ return ((FieldBinding) this.binding).isDeprecated();
+ }
+ return false;
+ }
+
+ /*
+ * @see IVariableBinding#isEnumConstant()
+ * @since 3.1
+ */
+ public boolean isEnumConstant() {
+ return (this.binding.modifiers & ClassFileConstants.AccEnum) != 0;
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ * @since 3.1
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof VariableBinding)) {
+ return false;
+ }
+ org.eclipse.jdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
+ if (this.binding instanceof FieldBinding) {
+ if (otherBinding instanceof FieldBinding) {
+ return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBinding) otherBinding);
+ } else {
+ return false;
+ }
+ } else {
+ if (BindingComparator.isEqual(this.binding, otherBinding)) {
+ IMethodBinding declaringMethod = getDeclaringMethod();
+ IMethodBinding otherDeclaringMethod = ((VariableBinding) other).getDeclaringMethod();
+ if (declaringMethod == null) {
+ if (otherDeclaringMethod != null) {
+ return false;
+ }
+//{ObjectTeams: no declaring method perhaps declared in a method spec?
+ MethodMappingElement otherDeclaringSpec = ((VariableBinding)other).getDeclaringMethodSpec();
+ if (otherDeclaringSpec != null) {
+ MethodMappingElement declaringSpec = getDeclaringMethodSpec();
+ if (declaringSpec == null)
+ return false;
+ return declaringSpec.equals(otherDeclaringSpec);
+ }
+// SH}
+ return true;
+ }
+ return declaringMethod.isEqualTo(otherDeclaringMethod);
+ }
+ return false;
+ }
+ }
+
+ /*
+ * @see IVariableBinding#isField()
+ */
+ public boolean isField() {
+ return this.binding instanceof FieldBinding;
+ }
+
+ /*
+ * @see IBinding#isSynthetic()
+ */
+ public boolean isSynthetic() {
+ if (isField()) {
+ return ((FieldBinding) this.binding).isSynthetic();
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
new file mode 100644
index 000000000..9abc14ad7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class of all AST node types that declare a single local
+ * variable.
+ * <p>
+ * <pre>
+ * VariableDeclaration:
+ * SingleVariableDeclaration
+ * VariableDeclarationFragment
+ * </pre>
+ * </p>
+ *
+ * @see SingleVariableDeclaration
+ * @see VariableDeclarationFragment
+ * @since 2.0
+ */
+public abstract class VariableDeclaration extends ASTNode {
+
+ /**
+ * Returns structural property descriptor for the "extraDimensions" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ abstract SimplePropertyDescriptor internalExtraDimensionsProperty();
+
+ /**
+ * Returns structural property descriptor for the "extraDimensions" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final SimplePropertyDescriptor getExtraDimensionsProperty() {
+ return internalExtraDimensionsProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "initializer" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ abstract ChildPropertyDescriptor internalInitializerProperty();
+
+ /**
+ * Returns structural property descriptor for the "initializer" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildPropertyDescriptor getInitializerProperty() {
+ return internalInitializerProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ abstract ChildPropertyDescriptor internalNameProperty();
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ * @since 3.1
+ */
+ public final ChildPropertyDescriptor getNameProperty() {
+ return internalNameProperty();
+ }
+
+ /**
+ * Creates a new AST node for a variable declaration owned by the given AST.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns the name of the variable declared in this variable declaration.
+ *
+ * @return the variable name node
+ */
+ public abstract SimpleName getName();
+
+ /**
+ * Sets the name of the variable declared in this variable declaration
+ * to the given name.
+ *
+ * @param variableName the new variable name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public abstract void setName(SimpleName variableName);
+
+ /**
+ * Returns the number of extra array dimensions over and above the
+ * explicitly-specified type.
+ * <p>
+ * For example, <code>int x[][]</code> has a type of
+ * <code>int</code> and two extra array dimensions;
+ * <code>int[][] x</code> has a type of <code>int[][]</code>
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * variable declaration.
+ * </p>
+ *
+ * @return the number of extra array dimensions
+ * @since 2.1
+ */
+ public abstract int getExtraDimensions();
+
+ /**
+ * Sets the number of extra array dimensions over and above the
+ * explicitly-specified type.
+ * <p>
+ * For example, <code>int x[][]</code> has a type of
+ * <code>int</code> and two extra array dimensions;
+ * <code>int[][] x</code> has a type of <code>int[][]</code>
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * variable declaration.
+ * </p>
+ *
+ * @param dimensions the number of array dimensions
+ * @exception IllegalArgumentException if the number of dimensions is
+ * negative
+ * @since 2.1
+ */
+ public abstract void setExtraDimensions(int dimensions);
+
+ /**
+ * Returns the initializer of this variable declaration, or
+ * <code>null</code> if there is none.
+ *
+ * @return the initializer expression node, or <code>null</code> if
+ * there is none
+ */
+ public abstract Expression getInitializer();
+
+ /**
+ * Sets or clears the initializer of this variable declaration.
+ *
+ * @param initializer the initializer expression node, or <code>null</code>
+ * if there is none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public abstract void setInitializer(Expression initializer);
+
+ /**
+ * Resolves and returns the binding for the variable declared in this
+ * variable declaration.
+ * <p>
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ * </p>
+ *
+ * @return the binding, or <code>null</code> if the binding cannot be
+ * resolved
+ */
+ public IVariableBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveVariable(this);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java
new file mode 100644
index 000000000..e02331c43
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationExpression.java
@@ -0,0 +1,435 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration expression AST node type.
+ * <p>
+ * This kind of node collects together several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a single expression
+ * (<code>Expression</code>), all sharing the same modifiers and base type.
+ * This type of node can be used as the initializer of a
+ * <code>ForStatement</code>, or wrapped in an <code>ExpressionStatement</code>
+ * to form the equivalent of a <code>VariableDeclarationStatement</code>.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * VariableDeclarationExpression:
+ * { Modifier } Type VariableDeclarationFragment
+ * { <b>,</b> VariableDeclarationFragment }
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ * <pre>
+ * VariableDeclarationExpression:
+ * { ExtendedModifier } Type VariableDeclarationFragment
+ * { <b>,</b> VariableDeclarationFragment }
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationExpression extends Expression {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationExpression.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationExpression.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationExpression.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationExpression.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: <code>IExtendedModifier</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.0
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifier flags; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable declaration fragments (element type:
+ * {@link VariableDeclarationFragment}). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented local variable declaration expression node
+ * owned by the given AST. By default, the variable declaration has: no
+ * modifiers, an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationExpression(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationExpression result =
+ new VariableDeclarationExpression(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ * <p>
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ * </p>
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: <code>IExtendedModifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ * <p>
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from <code>modifiers()</code>.
+ * </p>
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenient method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ * <p>
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ * </p>
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /**
+ * Returns the base type declared in this variable declaration.
+ * <p>
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ * </p>
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this variable declaration to the given
+ * type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this
+ * expression. Adding and removing nodes from this list affects this node
+ * dynamically. All nodes in this list must be
+ * <code>VariableDeclarationFragment</code>s; attempts to add any other
+ * type of node will trigger an exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * expression (element type: <code>VariableDeclarationFragment</code>)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
new file mode 100644
index 000000000..efacf8ebc
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Variable declaration fragment AST node type, used in field declarations,
+ * local variable declarations, and <code>ForStatement</code> initializers.
+ * It contrast to <code>SingleVariableDeclaration</code>, fragments are
+ * missing the modifiers and the type; these are located in the fragment's
+ * parent node.
+ *
+ * <pre>
+ * VariableDeclarationFragment:
+ * Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationFragment extends VariableDeclaration {
+
+ /**
+ * The "name" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationFragment.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationFragment.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationFragment.class, "initializer", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationFragment.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The variable name; lazily initialized; defaults to an unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName variableName = null;
+
+ /**
+ * The number of extra array dimensions that this variable has;
+ * defaults to 0.
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The initializer expression, or <code>null</code> if none;
+ * defaults to none.
+ */
+ private Expression optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for a variable declaration fragment owned by the
+ * given AST. By default, the variable declaration has: an unspecified
+ * (but legal) variable name, no initializer, and no extra array dimensions.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationFragment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+ return EXTRA_DIMENSIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final ChildPropertyDescriptor internalInitializerProperty() {
+ return INITIALIZER_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ * @since 3.1
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_FRAGMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationFragment result = new VariableDeclarationFragment(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setName((SimpleName) getName().clone(target));
+ result.setExtraDimensions(getExtraDimensions());
+ result.setInitializer(
+ (Expression) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public SimpleName getName() {
+ if (this.variableName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.variableName == null) {
+ preLazyInit();
+ this.variableName = new SimpleName(this.ast);
+ postLazyInit(this.variableName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.variableName;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setName(SimpleName variableName) {
+ if (variableName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.variableName;
+ preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ this.variableName = variableName;
+ postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration.
+ * <p>
+ * For example, in the AST for <code>int[] i, j[], k[][]</code> the
+ * variable declaration fragments for the variables <code>i</code>,
+ * <code>j</code>, and <code>k</code>, have 0, 1, and 2 extra array
+ * dimensions, respectively.
+ * </p>
+ *
+ * @return the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration
+ * @since 2.0
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /**
+ * Sets the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration.
+ * <p>
+ * For example, in the AST for <code>int[] i, j[], k[][]</code> the
+ * variable declaration fragments for the variables <code>i</code>,
+ * <code>j</code>, and <code>k</code>, have 0, 1, and 2 extra array
+ * dimensions, respectively.
+ * </p>
+ *
+ * @param dimensions the given dimensions
+ * @since 2.0
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public Expression getInitializer() {
+ return this.optionalInitializer;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setInitializer(Expression initializer) {
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.variableName == null ? 0 : getName().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java
new file mode 100644
index 000000000..fd7d71753
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationStatement.java
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration statement AST node type.
+ * <p>
+ * This kind of node collects several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a statement
+ * (<code>Statement</code>), all sharing the same modifiers and base type.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * VariableDeclarationStatement:
+ * { Modifier } Type VariableDeclarationFragment
+ * { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ * <pre>
+ * VariableDeclarationStatement:
+ * { ExtendedModifier } Type VariableDeclarationFragment
+ * { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * <p>
+ * Note: This type of node is a convenience of sorts.
+ * An equivalent way to represent the same statement is to use
+ * a <code>VariableDeclarationExpression</code>
+ * wrapped in an <code>ExpressionStatement</code>.
+ * </p>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationStatement extends Statement {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ * @since 3.0
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationStatement.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ * @since 3.1
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationStatement.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ * @since 3.0
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.0
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ * @since 3.1
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationStatement.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationStatement.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: <code>IExtendedModifier</code>).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ * @since 3.1
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifier flagss; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in JLS3.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable variable declaration fragments (element type:
+ * {@link VariableDeclarationFragment}). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented local variable declaration statement node owned
+ * by the given AST. By default, the variable declaration has: no modifiers,
+ * an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationStatement(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationStatement result =
+ new VariableDeclarationStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ * <p>
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ * </p>
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: <code>IExtendedModifier</code>)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @since 3.1
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ * <p>
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from <code>modifiers()</code>.
+ * </p>
+ *
+ * @return the bit-wise or of <code>Modifier</code> constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenience method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ * <p>
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ * </p>
+ *
+ * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ * @since 3.1
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /**
+ * Returns the base type declared in this variable declaration statement.
+ * <p>
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ * </p>
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this variable declaration statement to
+ * the given type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this statement.
+ * Adding and removing nodes from this list affects this node dynamically.
+ * All nodes in this list must be <code>VariableDeclarationFragment</code>s;
+ * attempts to add any other type of node will trigger an
+ * exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * statement (element type: <code>VariableDeclarationFragment</code>)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
new file mode 100644
index 000000000..272937062
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * While statement AST node type.
+ *
+ * <pre>
+ * WhileStatement:
+ * <b>while</b> <b>(</b> Expression <b>)</b> Statement
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class WhileStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(WhileStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ * @since 3.0
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(WhileStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(WhileStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ * @since 3.0
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new unparented while statement node owned by the given
+ * AST. By default, the expresssion is unspecified, but legal, and
+ * the body statement is an empty block.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ WhileStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return WHILE_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ WhileStatement result = new WhileStatement(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this while statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this while statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this while statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this while statement.
+ * <p>
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the body of a while statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the body of a <code>WhileStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
new file mode 100644
index 000000000..ed415af22
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a wildcard type (added in JLS3 API).
+ * <pre>
+ * WildcardType:
+ * <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ]
+ * </pre>
+ * <p>
+ * Not all node arrangements will represent legal Java constructs. In particular,
+ * it is nonsense if a wildcard type node appears anywhere other than as an
+ * argument of a <code>ParameterizedType</code> node.
+ * </p>
+ *
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class WildcardType extends Type {
+
+ /**
+ * The "bound" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BOUND_PROPERTY =
+ new ChildPropertyDescriptor(WildcardType.class, "bound", Type.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "upperBound" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor UPPER_BOUND_PROPERTY =
+ new SimplePropertyDescriptor(WildcardType.class, "upperBound", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(WildcardType.class, propertyList);
+ addProperty(BOUND_PROPERTY, propertyList);
+ addProperty(UPPER_BOUND_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional type bound node; <code>null</code> if none;
+ * defaults to none.
+ */
+ private Type optionalBound = null;
+
+ /**
+ * Indicates whether the wildcard bound is an upper bound
+ * ("extends") as opposed to a lower bound ("super").
+ * Defaults to <code>true</code> initially.
+ */
+ private boolean isUpperBound = true;
+
+ /**
+ * Creates a new unparented node for a wildcard type owned by the
+ * given AST. By default, no upper bound.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ WildcardType(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == UPPER_BOUND_PROPERTY) {
+ if (get) {
+ return isUpperBound();
+ } else {
+ setUpperBound(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == BOUND_PROPERTY) {
+ if (get) {
+ return getBound();
+ } else {
+ setBound((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return WILDCARD_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ WildcardType result = new WildcardType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setBound((Type) ASTNode.copySubtree(target, getBound()), isUpperBound());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getBound());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns whether this wildcard type is an upper bound
+ * ("extends") as opposed to a lower bound ("super").
+ * <p>
+ * Note that this property is irrelevant for wildcards
+ * that do not have a bound.
+ * </p>
+ *
+ * @return <code>true</code> if an upper bound,
+ * and <code>false</code> if a lower bound
+ * @see #setBound(Type)
+ */
+ public boolean isUpperBound() {
+ return this.isUpperBound;
+ }
+
+ /**
+ * Returns the bound of this wildcard type if it has one.
+ * If {@link #isUpperBound isUpperBound} returns true, this
+ * is an upper bound ("? extends B"); if it returns false, this
+ * is a lower bound ("? super B").
+ *
+ * @return the bound of this wildcard type, or <code>null</code>
+ * if none
+ * @see #setBound(Type)
+ */
+ public Type getBound() {
+ return this.optionalBound;
+ }
+
+ /**
+ * Sets the bound of this wildcard type to the given type and
+ * marks it as an upper or a lower bound. The method is
+ * equivalent to calling <code>setBound(type); setUpperBound(isUpperBound)</code>.
+ *
+ * @param type the new bound of this wildcard type, or <code>null</code>
+ * if none
+ * @param isUpperBound <code>true</code> for an upper bound ("? extends B"),
+ * and <code>false</code> for a lower bound ("? super B")
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @see #getBound()
+ * @see #isUpperBound()
+ */
+ public void setBound(Type type, boolean isUpperBound) {
+ setBound(type);
+ setUpperBound(isUpperBound);
+ }
+
+ /**
+ * Sets the bound of this wildcard type to the given type.
+ *
+ * @param type the new bound of this wildcard type, or <code>null</code>
+ * if none
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @see #getBound()
+ */
+ public void setBound(Type type) {
+ ASTNode oldChild = this.optionalBound;
+ preReplaceChild(oldChild, type, BOUND_PROPERTY);
+ this.optionalBound = type;
+ postReplaceChild(oldChild, type, BOUND_PROPERTY);
+ }
+
+ /**
+ * Sets whether this wildcard type is an upper bound
+ * ("extends") as opposed to a lower bound ("super").
+ *
+ * @param isUpperBound <code>true</code> if an upper bound,
+ * and <code>false</code> if a lower bound
+ * @see #isUpperBound()
+ */
+ public void setUpperBound(boolean isUpperBound) {
+ preValueChange(UPPER_BOUND_PROPERTY);
+ this.isUpperBound = isUpperBound;
+ postValueChange(UPPER_BOUND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalBound == null ? 0 : getBound().treeSize());
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WithinStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WithinStatement.java
new file mode 100644
index 000000000..ebee09b14
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WithinStatement.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NEW for OTDT, built in analogy to WhileStatement.
+ *
+ * Represents a within statement (OTJLD §5.2(a)), e.g.
+ * <code>
+ * within(new MyTeam())
+ * {
+ * foo();
+ * }
+ * </code>
+ * or
+ * <code>
+ * within(myTeam)
+ * {
+ * foo();
+ * }
+ * </code>
+ *
+ *
+ * Within Statements consist of a team expression and
+ * a body element (org.eclipse.jdtd.core.dom.Block).
+ *
+ * Within statements can be used in the following AST-nodes:
+ * Block
+ *
+ * @author mkr
+ */
+public class WithinStatement extends Statement
+{
+ /**
+ * The "team expression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor TEAM_EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(WithinStatement.class, "team expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(WithinStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ @SuppressWarnings("rawtypes")
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static
+ {
+ List<StructuralPropertyDescriptor> propertyList = new ArrayList<StructuralPropertyDescriptor>(3);
+ createPropertyList(WithinStatement.class, propertyList);
+ addProperty(TEAM_EXPRESSION_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS&ast;</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ @SuppressWarnings("rawtypes")
+ public static List propertyDescriptors(int apiLevel)
+ {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+
+ private Expression teamExpression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement. This is an addition to the statements List.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new withinStatement node owned by the given AST.
+ * By default, the withinStatement is empty.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ WithinStatement(AST ast)
+ {
+ super(ast);
+ }
+
+ @SuppressWarnings("rawtypes")
+ List internalStructuralPropertiesForType(int apiLevel)
+ {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean isGet, ASTNode child)
+ {
+ if (property == BODY_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getBody();
+ }
+ else
+ {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ if (property == TEAM_EXPRESSION_PROPERTY)
+ {
+ if (isGet)
+ {
+ return getTeamExpression();
+ }
+ else
+ {
+ setTeamExpression((Expression) child);
+ return null;
+ }
+
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, isGet, child);
+ }
+
+ int getNodeType0()
+ {
+ return WITHIN_STATEMENT;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other)
+ {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ ASTNode clone0(AST target)
+ {
+ WithinStatement result = new WithinStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setTeamExpression((Expression) getTeamExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+
+ return result;
+ }
+
+ void accept0(ASTVisitor visitor)
+ {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren)
+ {
+ acceptChild(visitor, this.teamExpression);
+ acceptChild(visitor, this.body);
+ }
+ visitor.endVisit(this);
+ }
+
+ int memSize()
+ {
+ // 3 * 4 == Number of single properties * 4
+ return super.memSize() + 3 * 4 + this.body.memSize();
+ }
+
+ int treeSize()
+ {
+ return memSize() + this.body.treeSize();
+ }
+
+ /**
+ * Returns the team exception of this within statement.
+ * @return team exception
+ */
+ public Expression getTeamExpression()
+ {
+ if (this.teamExpression == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this.teamExpression == null)
+ {
+ preLazyInit();
+ this.teamExpression = new SimpleName(this.ast);
+ postLazyInit(this.teamExpression, TEAM_EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.teamExpression;
+
+ }
+
+ /**
+ * Sets the expression of this while statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setTeamExpression(Expression expression)
+ {
+ if (expression == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.teamExpression;
+ preReplaceChild(oldChild, expression, TEAM_EXPRESSION_PROPERTY);
+ this.teamExpression = expression;
+ postReplaceChild(oldChild, expression, TEAM_EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this within statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody()
+ {
+ if (this.body == null)
+ {
+ // lazy init must be thread-safe for readers
+ synchronized (this)
+ {
+ if (this.body == null)
+ {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this within statement.
+ * <p>
+ * The Following is true for while statements (for within, too? (mkr)):<br />
+ * Special note: The Java language does not allow a local variable declaration
+ * to appear as the body of a while statement (they may only appear within a
+ * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+ * as the body of a <code>WithinStatement</code>. To get something that will
+ * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+ * inside a <code>Block</code>.
+ * </p>
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>a cycle in would be created</li>
+ * </ul>
+ */
+ public void setBody(Statement statement)
+ {
+ if (statement == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/package.html b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/package.html
new file mode 100644
index 000000000..f0ec90214
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/package.html
@@ -0,0 +1,24 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en] (Windows NT 5.0; U) [Netscape]">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+The Java DOM/AST is the set of classes that model the source code of a Java program
+as a structured document.
+
+<h2>
+Package Specification</h2>
+
+<p><br>This package contains the Java DOM/AST classes. An API for manipulating the
+source code of a Java program as a structured document. In particular, it provides
+a full abstract syntax tree for a Java compilation unit, which can be queried for
+resolved type information, and modified.
+The principal classes are {@link org.eclipse.jdt.core.dom.AST AST}
+{@link org.eclipse.jdt.core.dom.ASTNode ASTNode}, and
+{@link org.eclipse.jdt.core.dom.ASTParser ASTParser}.
+</body>
+</html>
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTNodeCreator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTNodeCreator.java
new file mode 100644
index 000000000..ae142d7bf
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTNodeCreator.java
@@ -0,0 +1,468 @@
+/*
+ * Created on 01.03.2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.eclipse.jdt.core.dom.rewrite;
+
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
+import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.FieldAccessSpec;
+import org.eclipse.jdt.core.dom.GuardPredicateDeclaration;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.MethodBindingOperator;
+import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.MethodMappingElement;
+import org.eclipse.jdt.core.dom.MethodSpec;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ParameterMapping;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclaration;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
+
+/**
+ * New for OTDT.
+ *
+ * @author ikeman
+ *
+ * This class provides helperMethods for the creation of DOMAST-Nodes.
+ *
+ * @version $Id: ASTNodeCreator.java 22581 2009-09-24 10:26:48Z stephan $
+ */
+@SuppressWarnings("unchecked") // assigning from parameterless lists :(
+public class ASTNodeCreator
+{
+
+ public static CompilationUnit createCU(AST ast, PackageDeclaration pack, List importList, List typeList)
+ {
+ CompilationUnit newCU = ast.newCompilationUnit();
+
+ if (pack != null)
+ newCU.setPackage(pack);
+
+ if (importList != null && importList.size()!= 0)
+ {
+ List<ImportDeclaration> cuImportList = newCU.imports();
+ for (int idx = 0; idx < importList.size(); idx++)
+ {
+ ImportDeclaration tmp = (ImportDeclaration)importList.get(idx);
+ cuImportList.add(tmp);
+ }
+ }
+
+ if (typeList != null && typeList.size()!= 0)
+ {
+ List<TypeDeclaration> cuTypeList = newCU.types();
+ for (int idx = 0; idx < typeList.size(); idx++)
+ {
+ TypeDeclaration tmp = (TypeDeclaration)typeList.get(idx);
+ cuTypeList.add(tmp);
+ }
+ }
+ return newCU;
+ }
+
+ /* km: not needed anymore?
+ public static TypeDeclaration createTeam(AST ast, Javadoc javadoc, int modifiers, boolean isInterface, boolean isRole,
+ String teamClassName, String superClassName, List superInterfaces, List bodyDeclarations)
+ {
+ TypeDeclaration newTypeDecl = ast.newTypeDeclaration();
+ newTypeDecl.setName(ast.newSimpleName(teamClassName));
+ newTypeDecl.setTeam(true);
+ if(ast.apiLevel() == AST.JLS2)
+ newTypeDecl.setModifiers(modifiers);
+ else
+ newTypeDecl.modifiers().addAll(ast.newModifiers(modifiers));
+
+ newTypeDecl.setRole(isRole);
+ newTypeDecl.setInterface(isInterface);
+
+ if (javadoc != null)
+ newTypeDecl.setJavadoc(javadoc);
+
+ if(ast.apiLevel() == AST.JLS2) {
+ if (superClassName != null)
+ newTypeDecl.setSuperclass(ast.newName(superClassName));
+
+ if (superInterfaces != null && superInterfaces.size()!= 0)
+ {
+ List superInterfacesList = newTypeDecl.superInterfaces();
+ for (int idx = 0; idx < superInterfaces.size(); idx++)
+ {
+ SimpleName tmp = (SimpleName)superInterfaces.get(idx);
+ superInterfacesList.add(tmp);
+ }
+ }
+ }
+ else {
+
+ }
+
+ if (bodyDeclarations != null && bodyDeclarations.size()!= 0)
+ {
+ List bodyDeclarationList = newTypeDecl.bodyDeclarations();
+ for (int idx = 0; idx < bodyDeclarations.size(); idx++)
+ {
+ Object tmp = bodyDeclarations.get(idx);
+ bodyDeclarationList.add(tmp);
+ }
+ }
+ return newTypeDecl;
+ }
+
+
+ public static RoleTypeDeclaration createRole(AST ast, Javadoc javadoc, int modifier, String roleName, String baseClassName,
+ String teamClassName, String superClassName, List superInterfaces, boolean isTeam,
+ List bodyDeclarations)
+ {
+ RoleTypeDeclaration role = ast.newRoleTypeDeclaration();
+
+ if(ast.apiLevel() == AST.JLS2)
+ role.setModifiers(modifier);
+ else
+ role.modifiers().addAll(ast.newModifiers(modifier));
+
+ role.setName(ast.newName(roleName));
+ role.setTeamClass(ast.newName(teamClassName));
+ role.setTeam(isTeam);
+ role.setRole(true);
+
+ if (javadoc != null)
+ role.setJavadoc(javadoc);
+
+ if (baseClassName != null)
+ role.setBaseClass(ast.newName(baseClassName));
+
+ if (superClassName != null)
+ role.setSuperclass(ast.newName(superClassName));
+
+ if (superInterfaces != null && superInterfaces.size()!= 0)
+ {
+ List superInterfacesList = role.superInterfaces();
+ for (int idx = 0; idx < superInterfaces.size(); idx++)
+ {
+ SimpleName tmp = (SimpleName)superInterfaces.get(idx);
+ superInterfacesList.add(tmp);
+ }
+ }
+
+ if (bodyDeclarations != null && bodyDeclarations.size()!= 0)
+ {
+ List bodyDeclarationList = role.bodyDeclarations();
+ for (int idx = 0; idx < bodyDeclarations.size(); idx++)
+ {
+ Object tmp = bodyDeclarations.get(idx);
+ bodyDeclarationList.add(tmp);
+ }
+ }
+ return role;
+ }
+*/
+ public static CallinMappingDeclaration createCallinMappingDeclaration
+ (AST ast, Javadoc javadoc, int modifier, MethodSpec roleMethod, List baseMethods, List paramMappings)
+ {
+ CallinMappingDeclaration newCallinMapping = ast.newCallinMappingDeclaration();
+ newCallinMapping.setCallinModifier(modifier);
+
+ newCallinMapping.setRoleMappingElement(roleMethod);
+
+ if (javadoc != null)
+ newCallinMapping.setJavadoc(javadoc);
+
+ if (baseMethods != null && baseMethods.size()!= 0)
+ {
+ List<MethodSpec> baseMappingList = newCallinMapping.getBaseMappingElements();
+ for (int idx = 0; idx < baseMethods.size(); idx++)
+ {
+ MethodSpec tmp = (MethodSpec)baseMethods.get(idx);
+ baseMappingList.add(tmp);
+ }
+ }
+ if (paramMappings != null && paramMappings.size()!= 0)
+ {
+ List<ParameterMapping> parameterMappingList = newCallinMapping.getParameterMappings();
+ while(!paramMappings.isEmpty())
+ {
+ ParameterMapping tmp = (ParameterMapping)paramMappings.remove(0);
+ parameterMappingList.add(tmp);
+ }
+ }
+ return newCallinMapping;
+ }
+
+ @SuppressWarnings("deprecation")
+ public static CalloutMappingDeclaration createCalloutMappingDeclaration(
+ AST ast,
+ Javadoc javadoc,
+ int modifier,
+ MethodMappingElement roleMethod,
+ MethodMappingElement baseMethod,
+ int bindingModifier,
+ List paramMappings,
+ boolean calloutOverride,
+ boolean signatureFlag)
+ {
+ CalloutMappingDeclaration newCalloutMapping = ast.newCalloutMappingDeclaration();
+
+ if (javadoc != null)
+ newCalloutMapping.setJavadoc(javadoc);
+
+ if(ast.apiLevel() == AST.JLS2)
+ newCalloutMapping.setModifiers(modifier);
+ else
+ newCalloutMapping.modifiers().addAll(ast.newModifiers(modifier));
+
+
+ newCalloutMapping.setSignatureFlag(signatureFlag);
+ newCalloutMapping.setRoleMappingElement(roleMethod);
+ newCalloutMapping.setBaseMappingElement(baseMethod);
+
+ ModifierKeyword keyword = null;
+ switch (bindingModifier) {
+ case Modifier.OT_SET_CALLOUT: keyword = ModifierKeyword.SET_KEYWORD; break;
+ case Modifier.OT_GET_CALLOUT: keyword = ModifierKeyword.GET_KEYWORD; break;
+ }
+ int calloutKind = calloutOverride ? MethodBindingOperator.KIND_CALLOUT_OVERRIDE : MethodBindingOperator.KIND_CALLOUT;
+ newCalloutMapping.setBindingOperator(ast.newMethodBindingOperator(keyword, calloutKind));
+
+ if (paramMappings != null && paramMappings.size()!= 0)
+ {
+ List<ParameterMapping> parameterMapping = newCalloutMapping.getParameterMappings();
+ while(!paramMappings.isEmpty())
+ {
+ ParameterMapping tmp = (ParameterMapping)paramMappings.remove(0);
+ parameterMapping.add(tmp);
+ }
+ }
+ return newCalloutMapping;
+ }
+
+ public static FieldAccessSpec createFieldAccSpec(AST ast, boolean isSetter, String fieldName, PrimitiveType.Code simpleType, String type, boolean hasSignature)
+ {
+ FieldAccessSpec newFieldAcc = ast.newFieldAccessSpec();
+ newFieldAcc.setName(ast.newSimpleName(fieldName));
+
+ if (simpleType!= null)
+ newFieldAcc.setFieldType(ast.newPrimitiveType(simpleType));
+
+ if (type!= null)
+ newFieldAcc.setFieldType(ast.newSimpleType(ast.newName(type)));
+
+ newFieldAcc.setSignatureFlag(hasSignature);
+ return newFieldAcc;
+ }
+ public static FieldAccessSpec createFieldAccSpec(AST ast, String fieldName, Type type) {
+ FieldAccessSpec newFieldAcc= ast.newFieldAccessSpec();
+ newFieldAcc.setName(ast.newSimpleName(fieldName));
+ newFieldAcc.setFieldType(type);
+ newFieldAcc.setSignatureFlag(true);
+ return newFieldAcc;
+ }
+ public static MethodSpec createMethodSpec(AST ast, String methodName, String returnType, List<String> argumentNames, List<String> argumentTypes, List<Integer> dimensions, boolean signatureFlag)
+ {
+ MethodSpec methodSpec = ast.newMethodSpec();
+ methodSpec.setName(ast.newSimpleName(methodName));
+ methodSpec.setReturnType2(createType(ast, returnType));
+ methodSpec.setSignatureFlag(signatureFlag);
+
+ if (argumentTypes !=null && argumentTypes.size()!=0)
+ {
+ List<VariableDeclaration> methodParameters = methodSpec.parameters();
+ for (int idx = 0; idx < argumentTypes.size(); idx++)
+ {
+ String argumentName = (argumentNames != null)
+ ? argumentNames.get(idx)
+ : "arg"+idx; //$NON-NLS-1$
+ VariableDeclaration tmp = createArgument(ast, 0, createType(ast, argumentTypes.get(idx)), argumentName, dimensions.get(idx), null);
+ methodParameters.add(tmp);
+ }
+ }
+ return methodSpec;
+ }
+
+ public static MethodSpec createMethodSpec(AST ast, String methodName, Type returnType, List parameters, boolean signatureFlag)
+ {
+ MethodSpec methodSpec = ast.newMethodSpec();
+ methodSpec.setName(ast.newSimpleName(methodName));
+ methodSpec.setSignatureFlag(signatureFlag);
+ methodSpec.setReturnType2(returnType);
+
+ if (parameters!=null && parameters.size()!=0)
+ {
+ List<VariableDeclaration> methodParameters = methodSpec.parameters();
+ for (int idx = 0; idx < parameters.size(); idx++)
+ {
+ VariableDeclaration tmp = (VariableDeclaration)parameters.get(idx);
+ methodParameters.add(tmp);
+ }
+ }
+ return methodSpec;
+ }
+
+ public static GuardPredicateDeclaration createGuardPredicate(AST ast, boolean isBase, Expression expression) {
+ GuardPredicateDeclaration result = ast.newGuardPredicateDeclaration();
+ result.setBase(isBase);
+ result.setExpression(expression);
+ return result;
+ }
+
+ public static Type createType(AST ast, String typeName)
+ {
+ Type primType = getPrimitveType(ast, typeName);
+ if (primType != null)
+ return primType;
+
+ if (typeName.endsWith("[]")) //$NON-NLS-1$
+ {
+ String [] name = typeName.split("\\[\\]"); //$NON-NLS-1$
+ if (name[0] != null)
+ {
+ Type primitiveType = getPrimitveType(ast, name[0]);
+ if (primitiveType!= null)
+ return ast.newArrayType(primitiveType);
+ else
+ {
+ Name nameNode = ast.newName(name[0]);
+ Type simpleType = ast.newSimpleType(nameNode);
+ return ast.newArrayType(simpleType);
+ }
+ }
+ }
+
+ Name name = ast.newName(typeName);
+ Type simpleType = ast.newSimpleType(name);
+
+ return simpleType;
+ }
+
+ private static Type getPrimitveType(AST ast, String typeName)
+ {
+ if (typeName.equals(PrimitiveType.BOOLEAN.toString()))
+ return ast.newPrimitiveType(PrimitiveType.BOOLEAN);
+
+ if (typeName.equals(PrimitiveType.BYTE.toString()))
+ return ast.newPrimitiveType(PrimitiveType.BYTE);
+
+ if (typeName.equals(PrimitiveType.CHAR.toString()))
+ return ast.newPrimitiveType(PrimitiveType.CHAR);
+
+ if (typeName.equals(PrimitiveType.DOUBLE.toString()))
+ return ast.newPrimitiveType(PrimitiveType.DOUBLE);
+
+ if (typeName.equals(PrimitiveType.FLOAT.toString()))
+ return ast.newPrimitiveType(PrimitiveType.FLOAT);
+
+ if (typeName.equals(PrimitiveType.INT.toString()))
+ return ast.newPrimitiveType(PrimitiveType.INT);
+
+ if (typeName.equals(PrimitiveType.LONG.toString()))
+ return ast.newPrimitiveType(PrimitiveType.LONG);
+
+ if (typeName.equals(PrimitiveType.SHORT.toString()))
+ return ast.newPrimitiveType(PrimitiveType.SHORT);
+
+ if (typeName.equals(PrimitiveType.VOID.toString()))
+ return ast.newPrimitiveType(PrimitiveType.VOID);
+
+ return null;
+ }
+
+ @SuppressWarnings("deprecation")
+ public static SingleVariableDeclaration createArgument(AST ast, int modifier, Type parameterType, String parameterName, int dimension,
+ Expression initializer)
+ {
+ SingleVariableDeclaration methodSpecParameter = ast.newSingleVariableDeclaration();
+ if(ast.apiLevel() == AST.JLS2)
+ methodSpecParameter.setModifiers(modifier);
+ else
+ methodSpecParameter.modifiers().addAll(ast.newModifiers(modifier));
+
+ methodSpecParameter.setType(parameterType);
+ methodSpecParameter.setName(ast.newSimpleName(parameterName));
+ methodSpecParameter.setExtraDimensions(dimension);
+ methodSpecParameter.setInitializer(initializer);
+ return methodSpecParameter;
+ }
+
+ public static ParameterMapping createParameterMapping(AST ast, Expression expression, SimpleName identName,
+ String direction, boolean resultFlag)
+ {
+ ParameterMapping newParameterMapping = ast.newParameterMapping();
+ newParameterMapping.setExpression(expression);
+ newParameterMapping.setDirection(direction);
+ newParameterMapping.setIdentifier(identName);
+ newParameterMapping.setResultFlag(resultFlag);
+ return newParameterMapping;
+ }
+
+ public static Expression createExpression(AST ast, String expressionName, String methodName)
+ {
+ MethodInvocation expression = ast.newMethodInvocation();
+ expression.setExpression(ast.newSimpleName(expressionName));
+ expression.setName(ast.newSimpleName(methodName));
+ return expression;
+ }
+
+
+ /**
+ * Parses the source string of an expression and returns a dom ast expression,
+ * that belongs to the given ast, or <code>null</code> if something goes wrong.
+ */
+ public static Expression createExpression(AST ast, String expr)
+ {
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+ parser.setKind(ASTParser.K_EXPRESSION);
+ parser.setSource(expr.toCharArray());
+ ASTNode parsedNode = parser.createAST(null);
+ if (parsedNode instanceof Expression)
+ {
+ Expression exprNode = (Expression)parsedNode;
+
+ // copy the parsed expression node to the current AST
+ Expression newExprNode = (Expression)ASTNode.copySubtree(ast, exprNode);
+ return newExprNode;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public static Expression createExpression(AST ast, Expression innerExpression, String className,
+ List arguments, AnonymousClassDeclaration anonymousClass)
+ {
+ ClassInstanceCreation expression = ast.newClassInstanceCreation();
+ expression.setType(ast.newSimpleType(ast.newName(className)));
+ expression.setExpression(innerExpression);
+ expression.setAnonymousClassDeclaration(anonymousClass);
+
+ if (arguments!=null && arguments.size()!=0)
+ {
+ List<Expression> classArguments = expression.arguments();
+ for (int idx = 0; idx < arguments.size(); idx++)
+ {
+ Expression tmp = (Expression)arguments.get(idx);
+ classArguments.add(tmp);
+ }
+ }
+ return expression;
+ }
+}
+
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
new file mode 100644
index 000000000..695b0b091
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
@@ -0,0 +1,717 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom.rewrite;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.TrackedNodePosition;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+
+/**
+ * Infrastructure for modifying code by describing changes to AST nodes.
+ * The AST rewriter collects descriptions of modifications to nodes and
+ * translates these descriptions into text edits that can then be applied to
+ * the original source. The key thing is that this is all done without actually
+ * modifying the original AST, which has the virtue of allowing one to entertain
+ * several alternate sets of changes on the same AST (e.g., for calculating
+ * quick fix proposals). The rewrite infrastructure tries to generate minimal
+ * text changes, preserve existing comments and indentation, and follow code
+ * formatter settings. If the freedom to explore multiple alternate changes is
+ * not required, consider using the AST's built-in rewriter
+ * (see {@link org.eclipse.jdt.core.dom.CompilationUnit#rewrite(IDocument, Map)}).
+ * <p>
+ * The following code snippet illustrated usage of this class:
+ * </p>
+ * <pre>
+ * Document document = new Document("import java.util.List;\nclass X {}\n");
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);
+ * parser.setSource(document.get().toCharArray());
+ * CompilationUnit cu = (CompilationUnit) parser.createAST(null);
+ * AST ast = cu.getAST();
+ * ImportDeclaration id = ast.newImportDeclaration();
+ * id.setName(ast.newName(new String[] {"java", "util", "Set"}));
+ * ASTRewrite rewriter = ASTRewrite.create(ast);
+ * TypeDeclaration td = (TypeDeclaration) cu.types().get(0);
+ * ITrackedNodePosition tdLocation = rewriter.track(td);
+ * ListRewrite lrw = rewriter.getListRewrite(cu, CompilationUnit.IMPORTS_PROPERTY);
+ * lrw.insertLast(id, null);
+ * TextEdit edits = rewriter.rewriteAST(document, null);
+ * UndoEdit undo = null;
+ * try {
+ * undo = edits.apply(document);
+ * } catch(MalformedTreeException e) {
+ * e.printStackTrace();
+ * } catch(BadLocationException e) {
+ * e.printStackTrace();
+ * }
+ * assert "import java.util.List;\nimport java.util.Set;\nclass X {}\n".equals(document.get());
+ * // tdLocation.getStartPosition() and tdLocation.getLength()
+ * // are new source range for "class X {}" in document.get()
+ * </pre>
+ * <p>
+ * This class is not intended to be subclassed.
+ * </p>
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ASTRewrite {
+
+ /** root node for the rewrite: Only nodes under this root are accepted */
+ private final AST ast;
+
+ private final RewriteEventStore eventStore;
+ private final NodeInfoStore nodeStore;
+
+ /**
+ * Target source range computer; null means uninitialized;
+ * lazy initialized to <code>new TargetSourceRangeComputer()</code>.
+ * @since 3.1
+ */
+ private TargetSourceRangeComputer targetSourceRangeComputer = null;
+
+ /**
+ * Creates a new instance for describing manipulations of
+ * the given AST.
+ *
+ * @param ast the AST whose nodes will be rewritten
+ * @return the new rewriter instance
+ */
+ public static ASTRewrite create(AST ast) {
+ return new ASTRewrite(ast);
+ }
+
+ /**
+ * Internal constructor. Creates a new instance for the given AST.
+ * Clients should use {@link #create(AST)} to create instances.
+ *
+ * @param ast the AST being rewritten
+ */
+ protected ASTRewrite(AST ast) {
+ this.ast= ast;
+ this.eventStore= new RewriteEventStore();
+ this.nodeStore= new NodeInfoStore(ast);
+ }
+
+ /**
+ * Returns the AST the rewrite was set up on.
+ *
+ * @return the AST the rewrite was set up on
+ */
+ public final AST getAST() {
+ return this.ast;
+ }
+
+ /**
+ * Internal method. Returns the internal event store.
+ * Clients should not use.
+ * @return Returns the internal event store. Clients should not use.
+ */
+ protected final RewriteEventStore getRewriteEventStore() {
+ return this.eventStore;
+ }
+
+ /**
+ * Internal method. Returns the internal node info store.
+ * Clients should not use.
+ * @return Returns the internal info store. Clients should not use.
+ */
+ protected final NodeInfoStore getNodeStore() {
+ return this.nodeStore;
+ }
+
+ /**
+ * Converts all modifications recorded by this rewriter
+ * into an object representing the corresponding text
+ * edits to the given document containing the original source
+ * code. The document itself is not modified.
+ * <p>
+ * For nodes in the original that are being replaced or deleted,
+ * this rewriter computes the adjusted source ranges
+ * by calling <code>getTargetSourceRangeComputer().computeSourceRange(node)</code>.
+ * </p>
+ * <p>
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications are added to the ones
+ * already on record. If this method is called again later,
+ * the resulting text edit object will accurately reflect
+ * the net cumulative affect of all those changes.
+ * </p>
+ *
+ * @param document original document containing source code
+ * @param options the table of formatter options
+ * (key type: <code>String</code>; value type: <code>String</code>);
+ * or <code>null</code> to use the standard global options
+ * {@link JavaCore#getOptions() JavaCore.getOptions()}
+ * @return text edit object describing the changes to the
+ * document corresponding to the changes recorded by this rewriter
+ * @throws IllegalArgumentException An <code>IllegalArgumentException</code>
+ * is thrown if the document passed does not correspond to the AST that is rewritten.
+ */
+ public TextEdit rewriteAST(IDocument document, Map options) throws IllegalArgumentException {
+ if (document == null) {
+ throw new IllegalArgumentException();
+ }
+
+ ASTNode rootNode= getRootNode();
+ if (rootNode == null) {
+ return new MultiTextEdit(); // no changes
+ }
+
+ char[] content= document.get().toCharArray();
+ LineInformation lineInfo= LineInformation.create(document);
+ String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+
+ ASTNode astRoot= rootNode.getRoot();
+ List commentNodes= astRoot instanceof CompilationUnit ? ((CompilationUnit) astRoot).getCommentList() : null;
+ Map currentOptions = options == null ? JavaCore.getOptions() : options;
+ return internalRewriteAST(content, lineInfo, lineDelim, commentNodes, currentOptions, rootNode, (RecoveryScannerData)((CompilationUnit) astRoot).getStatementsRecoveryData());
+ }
+
+ /**
+ * Converts all modifications recorded by this rewriter into an object representing the the corresponding text
+ * edits to the source of a {@link ITypeRoot} from which the AST was created from.
+ * The type root's source itself is not modified by this method call.
+ * <p>
+ * Important: This API can only be used if the modified AST has been created from a
+ * {@link ITypeRoot} with source. That means {@link ASTParser#setSource(ICompilationUnit)},
+ * {@link ASTParser#setSource(IClassFile)} or {@link ASTParser#setSource(ITypeRoot)}
+ * has been used when initializing the {@link ASTParser}. A {@link IllegalArgumentException} is thrown
+ * otherwise. An {@link IllegalArgumentException} is also thrown when the type roots buffer does not correspond
+ * anymore to the AST. Use {@link #rewriteAST(IDocument, Map)} for all ASTs created from other content.
+ * </p>
+ * <p>
+ * For nodes in the original that are being replaced or deleted,
+ * this rewriter computes the adjusted source ranges
+ * by calling <code>getTargetSourceRangeComputer().computeSourceRange(node)</code>.
+ * </p>
+ * <p>
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications are added to the ones
+ * already on record. If this method is called again later,
+ * the resulting text edit object will accurately reflect
+ * the net cumulative affect of all those changes.
+ * </p>
+ *
+ * @return text edit object describing the changes to the
+ * document corresponding to the changes recorded by this rewriter
+ * @throws JavaModelException A {@link JavaModelException} is thrown when
+ * the underlying compilation units buffer could not be accessed.
+ * @throws IllegalArgumentException An {@link IllegalArgumentException}
+ * is thrown if the document passed does not correspond to the AST that is rewritten.
+ *
+ * @since 3.2
+ */
+ public TextEdit rewriteAST() throws JavaModelException, IllegalArgumentException {
+ ASTNode rootNode= getRootNode();
+ if (rootNode == null) {
+ return new MultiTextEdit(); // no changes
+ }
+
+ ASTNode root= rootNode.getRoot();
+ if (!(root instanceof CompilationUnit)) {
+ throw new IllegalArgumentException("This API can only be used if the AST is created from a compilation unit or class file"); //$NON-NLS-1$
+ }
+ CompilationUnit astRoot= (CompilationUnit) root;
+ ITypeRoot typeRoot = astRoot.getTypeRoot();
+ if (typeRoot == null || typeRoot.getBuffer() == null) {
+ throw new IllegalArgumentException("This API can only be used if the AST is created from a compilation unit or class file"); //$NON-NLS-1$
+ }
+
+ char[] content= typeRoot.getBuffer().getCharacters();
+ LineInformation lineInfo= LineInformation.create(astRoot);
+ String lineDelim= typeRoot.findRecommendedLineSeparator();
+ Map options= typeRoot.getJavaProject().getOptions(true);
+
+ return internalRewriteAST(content, lineInfo, lineDelim, astRoot.getCommentList(), options, rootNode, (RecoveryScannerData)astRoot.getStatementsRecoveryData());
+ }
+
+ private TextEdit internalRewriteAST(char[] content, LineInformation lineInfo, String lineDelim, List commentNodes, Map options, ASTNode rootNode, RecoveryScannerData recoveryScannerData) {
+ TextEdit result= new MultiTextEdit();
+ //validateASTNotModified(rootNode);
+
+ TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
+ this.eventStore.prepareMovedNodes(sourceRangeComputer);
+//{ObjectTeams: OT/J source?
+ if (this.isOTJsource)
+ options.put(CompilerOptions.OPTION_AllowScopedKeywords, CompilerOptions.DISABLED);
+ // FIXME(SH): else set PureJava to ENABLED??
+// SH}
+
+ ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, commentNodes, options, sourceRangeComputer, recoveryScannerData);
+ rootNode.accept(visitor); // throws IllegalArgumentException
+
+ this.eventStore.revertMovedNodes();
+ return result;
+ }
+
+ private ASTNode getRootNode() {
+ ASTNode node= null;
+ int start= -1;
+ int end= -1;
+
+ for (Iterator iter= getRewriteEventStore().getChangeRootIterator(); iter.hasNext();) {
+ ASTNode curr= (ASTNode) iter.next();
+ if (!RewriteEventStore.isNewNode(curr)) {
+ int currStart= curr.getStartPosition();
+ int currEnd= currStart + curr.getLength();
+ if (node == null || currStart < start && currEnd > end) {
+ start= currStart;
+ end= currEnd;
+ node= curr;
+ } else if (currStart < start) {
+ start= currStart;
+ } else if (currEnd > end) {
+ end= currEnd;
+ }
+ }
+ }
+ if (node != null) {
+ int currStart= node.getStartPosition();
+ int currEnd= currStart + node.getLength();
+ while (start < currStart || end > currEnd) { // go up until a node covers all
+ node= node.getParent();
+ currStart= node.getStartPosition();
+ currEnd= currStart + node.getLength();
+ }
+ ASTNode parent= node.getParent(); // go up until a parent has different range
+ while (parent != null && parent.getStartPosition() == node.getStartPosition() && parent.getLength() == node.getLength()) {
+ node= parent;
+ parent= node.getParent();
+ }
+ }
+ return node;
+ }
+
+ /*
+ private void validateASTNotModified(ASTNode root) throws IllegalArgumentException {
+ GenericVisitor isModifiedVisitor= new GenericVisitor() {
+ protected boolean visitNode(ASTNode node) {
+ if ((node.getFlags() & ASTNode.ORIGINAL) == 0) {
+ throw new IllegalArgumentException("The AST that is rewritten must not be modified."); //$NON-NLS-1$
+ }
+ return true;
+ }
+ };
+ root.accept(isModifiedVisitor);
+ }
+ */
+
+ /**
+ * Removes the given node from its parent in this rewriter. The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node should not be there.
+ *
+ * @param node the node being removed. The node can either be an original node in the AST
+ * or (since 3.4) a new node already inserted or used as replacement in this AST rewriter.
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not
+ * part of this rewriter's AST, or if the described modification is invalid
+ * (such as removing a required node)
+ */
+ public final void remove(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+
+ StructuralPropertyDescriptor property;
+ ASTNode parent;
+ if (RewriteEventStore.isNewNode(node)) { // remove a new node, bug 164862
+ PropertyLocation location= this.eventStore.getPropertyLocation(node, RewriteEventStore.NEW);
+ if (location != null) {
+ property= location.getProperty();
+ parent= location.getParent();
+ } else {
+ throw new IllegalArgumentException("Node is not part of the rewriter's AST"); //$NON-NLS-1$
+ }
+ } else {
+ property= node.getLocationInParent();
+ parent= node.getParent();
+ }
+
+ if (property.isChildListProperty()) {
+ getListRewrite(parent, (ChildListPropertyDescriptor) property).remove(node, editGroup);
+ } else {
+ set(parent, property, null, editGroup);
+ }
+ }
+
+ /**
+ * Replaces the given node in this rewriter. The replacement node
+ * must either be brand new (not part of the original AST) or a placeholder
+ * node (for example, one created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been replaced.
+ *
+ * @param node the node being replaced. The node can either be an original node in the AST
+ * or (since 3.4) a new node already inserted or used as replacement in this AST rewriter.
+ * @param replacement the replacement node, or <code>null</code> if no
+ * replacement
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the replacement node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ */
+ public final void replace(ASTNode node, ASTNode replacement, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+
+ StructuralPropertyDescriptor property;
+ ASTNode parent;
+ if (RewriteEventStore.isNewNode(node)) { // replace a new node, bug 164862
+ PropertyLocation location= this.eventStore.getPropertyLocation(node, RewriteEventStore.NEW);
+ if (location != null) {
+ property= location.getProperty();
+ parent= location.getParent();
+ } else {
+ throw new IllegalArgumentException("Node is not part of the rewriter's AST"); //$NON-NLS-1$
+ }
+ } else {
+ property= node.getLocationInParent();
+ parent= node.getParent();
+ }
+
+ if (property.isChildListProperty()) {
+ getListRewrite(parent, (ChildListPropertyDescriptor) property).replace(node, replacement, editGroup);
+ } else {
+ set(parent, property, replacement, editGroup);
+ }
+ }
+
+ /**
+ * Sets the given property of the given node. If the given property is a child
+ * property, the value must be a replacement node that is either be brand new
+ * (not part of the original AST) or a placeholder node (for example, one
+ * created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}); or it must be
+ * <code>null</code>, indicating that the child should be deleted.
+ * If the given property is a simple property, the value must be the new
+ * value (primitive types must be boxed) or <code>null</code>.
+ * The AST itself is not actually modified in any way; rather, the rewriter
+ * just records a note that this node has been changed in the specified way.
+ *
+ * @param node the node
+ * @param property the node's property; either a simple property or a child property
+ * @param value the replacement child or new value, or <code>null</code> if none
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node or property is null, or if the node
+ * is not part of this rewriter's AST, or if the property is not a node property,
+ * or if the described modification is invalid
+ */
+ public final void set(ASTNode node, StructuralPropertyDescriptor property, Object value, TextEditGroup editGroup) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+ validateIsCorrectAST(node);
+ validatePropertyType(property, value);
+ validateIsPropertyOfNode(property, node);
+
+ NodeRewriteEvent nodeEvent= this.eventStore.getNodeEvent(node, property, true);
+ nodeEvent.setNewValue(value);
+ if (editGroup != null) {
+ this.eventStore.setEventEditGroup(nodeEvent, editGroup);
+ }
+ }
+
+ /**
+ * Returns the value of the given property as managed by this rewriter. If the property
+ * has been removed, <code>null</code> is returned. If it has been replaced, the replacing value
+ * is returned. If the property has not been changed yet, the original value is returned.
+ * <p>
+ * For child list properties use {@link ListRewrite#getRewrittenList()} to get access to the
+ * rewritten nodes in a list. </p>
+ *
+ * @param node the node
+ * @param property the node's property
+ * @return the value of the given property as managed by this rewriter
+ *
+ * @since 3.2
+ */
+ public Object get(ASTNode node, StructuralPropertyDescriptor property) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+ if (property.isChildListProperty()) {
+ throw new IllegalArgumentException("Use the list rewriter to access nodes in a list"); //$NON-NLS-1$
+ }
+ return this.eventStore.getNewValue(node, property);
+ }
+
+ /**
+ * Creates and returns a new rewriter for describing modifications to the
+ * given list property of the given node.
+ *
+ * @param node the node
+ * @param property the node's property; the child list property
+ * @return a new list rewriter object
+ * @throws IllegalArgumentException if the node or property is null, or if the node
+ * is not part of this rewriter's AST, or if the property is not a node property,
+ * or if the described modification is invalid
+ */
+ public final ListRewrite getListRewrite(ASTNode node, ChildListPropertyDescriptor property) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+
+ validateIsCorrectAST(node);
+ validateIsListProperty(property);
+ validateIsPropertyOfNode(property, node);
+
+ return new ListRewrite(this, node, property);
+ }
+
+ /**
+ * Returns an object that tracks the source range of the given node
+ * across the rewrite to its AST. Upon return, the result object reflects
+ * the given node's current source range in the AST. After
+ * <code>rewrite</code> is called, the result object is updated to
+ * reflect the given node's source range in the rewritten AST.
+ *
+ * @param node the node to track
+ * @return an object that tracks the source range of <code>node</code>
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST, or if the node is already being
+ * tracked
+ */
+ public final ITrackedNodePosition track(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ TextEditGroup group= this.eventStore.getTrackedNodeData(node);
+ if (group == null) {
+ group= new TextEditGroup("internal"); //$NON-NLS-1$
+ this.eventStore.setTrackedNodeData(node, group);
+ }
+ return new TrackedNodePosition(group, node);
+ }
+
+ private void validateIsExistingNode(ASTNode node) {
+ if (node.getStartPosition() == -1) {
+ throw new IllegalArgumentException("Node is not an existing node"); //$NON-NLS-1$
+ }
+ }
+
+ private void validateIsCorrectAST(ASTNode node) {
+ if (node.getAST() != getAST()) {
+ throw new IllegalArgumentException("Node is not inside the AST"); //$NON-NLS-1$
+ }
+ }
+
+ private void validateIsListProperty(StructuralPropertyDescriptor property) {
+ if (!property.isChildListProperty()) {
+ String message= property.getId() + " is not a list property"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ private void validateIsPropertyOfNode(StructuralPropertyDescriptor property, ASTNode node) {
+ if (!property.getNodeClass().isInstance(node)) {
+ String message= property.getId() + " is not a property of type " + node.getClass().getName(); //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ private void validatePropertyType(StructuralPropertyDescriptor prop, Object node) {
+ if (prop.isChildListProperty()) {
+ String message= "Can not modify a list property, use a list rewriter"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Creates and returns a placeholder node for a source string that is to be inserted into
+ * the output document at the position corresponding to the placeholder.
+ * The string will be inserted without being reformatted beyond correcting
+ * the indentation level. The placeholder node can either be inserted as new or
+ * used to replace an existing node.
+ *
+ * @param code the string to be inserted; lines should should not have extra indentation
+ * @param nodeType the ASTNode type that corresponds to the passed code.
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the code is null, or if the node
+ * type is invalid
+ */
+ public final ASTNode createStringPlaceholder(String code, int nodeType) {
+ if (code == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode placeholder= getNodeStore().newPlaceholderNode(nodeType);
+ if (placeholder == null) {
+ throw new IllegalArgumentException("String placeholder is not supported for type" + nodeType); //$NON-NLS-1$
+ }
+
+ getNodeStore().markAsStringPlaceholder(placeholder, code);
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a node that represents a sequence of nodes.
+ * Each of the given nodes must be either be brand new (not part of the original AST), or
+ * a placeholder node (for example, one created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}), or another group node.
+ * The type of the returned node is unspecified. The returned node can be used
+ * to replace an existing node (or as an element of another group node).
+ * When the document is rewritten, the source code for each of the given nodes is
+ * inserted, in order, into the output document at the position corresponding to the
+ * group (indentation is adjusted).
+ *
+ * @param targetNodes the nodes to go in the group
+ * @return the new group node
+ * @throws IllegalArgumentException if the targetNodes is <code>null</code> or empty
+ * @since 3.1
+ */
+ public final ASTNode createGroupNode(ASTNode[] targetNodes) {
+ if (targetNodes == null || targetNodes.length == 0) {
+ throw new IllegalArgumentException();
+ }
+ Block res= getNodeStore().createCollapsePlaceholder();
+ ListRewrite listRewrite= getListRewrite(res, Block.STATEMENTS_PROPERTY);
+ for (int i= 0; i < targetNodes.length; i++) {
+ listRewrite.insertLast(targetNodes[i], null);
+ }
+ return res;
+ }
+
+
+ private ASTNode createTargetNode(ASTNode node, boolean isMove) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ validateIsExistingNode(node);
+ validateIsCorrectAST(node);
+ CopySourceInfo info= getRewriteEventStore().markAsCopySource(node.getParent(), node.getLocationInParent(), node, isMove);
+
+ ASTNode placeholder= getNodeStore().newPlaceholderNode(node.getNodeType());
+ if (placeholder == null) {
+ throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + node.getClass().getName()); //$NON-NLS-1$
+ }
+ getNodeStore().markAsCopyTarget(placeholder, info);
+
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a placeholder node for a true copy of the given node.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param node the node to create a copy placeholder for
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST
+ */
+ public final ASTNode createCopyTarget(ASTNode node) {
+ return createTargetNode(node, false);
+ }
+
+ /**
+ * Creates and returns a placeholder node for the new locations of the given node.
+ * After obtaining a placeholder, the node should then to be removed or replaced.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, the source code for the given
+ * node is inserted into the output document at the position corresponding to the
+ * placeholder (indentation is adjusted).
+ *
+ * @param node the node to create a move placeholder for
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST
+ */
+ public final ASTNode createMoveTarget(ASTNode node) {
+ return createTargetNode(node, true);
+ }
+
+ /**
+ * Returns the extended source range computer for this AST rewriter.
+ * The default value is a <code>new TargetSourceRangeComputer()</code>.
+ *
+ * @return an extended source range computer
+ * @since 3.1
+ */
+ public final TargetSourceRangeComputer getExtendedSourceRangeComputer() {
+ if (this.targetSourceRangeComputer == null) {
+ // lazy initialize
+ this.targetSourceRangeComputer = new TargetSourceRangeComputer();
+ }
+ return this.targetSourceRangeComputer;
+ }
+
+ /**
+ * Sets a custom target source range computer for this AST rewriter. This is advanced feature to modify how
+ * comments are associated with nodes, which should be done only in special cases.
+ *
+ * @param computer a target source range computer,
+ * or <code>null</code> to restore the default value of
+ * <code>new TargetSourceRangeComputer()</code>
+ * @since 3.1
+ */
+ public final void setTargetSourceRangeComputer(TargetSourceRangeComputer computer) {
+ // if computer==null, rely on lazy init code in getTargetSourceRangeComputer()
+ this.targetSourceRangeComputer = computer;
+ }
+
+ /**
+ * Returns a string suitable for debugging purposes (only).
+ *
+ * @return a debug string
+ */
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ buf.append("Events:\n"); //$NON-NLS-1$
+ // be extra careful of uninitialized or mangled instances
+ if (this.eventStore != null) {
+ buf.append(this.eventStore.toString());
+ }
+ return buf.toString();
+ }
+
+//{ObjectTeams:
+ boolean isOTJsource= false;
+ public void setToOTJ() {
+ this.isOTJsource= true;
+ }
+// SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ITrackedNodePosition.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ITrackedNodePosition.java
new file mode 100644
index 000000000..ddd62d5a1
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ITrackedNodePosition.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom.rewrite;
+
+/**
+ * A tracked node position is returned when a rewrite change is
+ * requested to be tracked.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see ASTRewrite#track(org.eclipse.jdt.core.dom.ASTNode)
+ * @since 3.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ITrackedNodePosition {
+
+ /**
+ * Returns the original or modified start position of the tracked node depending if called before
+ * or after the rewrite is applied. <code>-1</code> is returned for removed nodes.
+ *
+ * @return the original or modified start position of the tracked node
+ */
+ public int getStartPosition();
+
+ /**
+ * Returns the original or modified length of the tracked node depending if called before
+ * or after the rewrite is applied. <code>-1</code> is returned for removed nodes.
+ *
+ * @return the original or modified length of the tracked node
+ */
+ public int getLength();
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
new file mode 100644
index 000000000..528859529
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
@@ -0,0 +1,1227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IImportDeclaration;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.internal.core.dom.rewrite.ImportRewriteAnalyzer;
+import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+
+
+/**
+ * The {@link ImportRewrite} helps updating imports following a import order and on-demand imports threshold as configured by a project.
+ * <p>
+ * The import rewrite is created on a compilation unit and collects references to types that are added or removed. When adding imports, e.g. using
+ * {@link #addImport(String)}, the import rewrite evaluates if the type can be imported and returns the a reference to the type that can be used in code.
+ * This reference is either unqualified if the import could be added, or fully qualified if the import failed due to a conflict with another element of the same name.
+ * </p>
+ * <p>
+ * On {@link #rewriteImports(IProgressMonitor)} the rewrite translates these descriptions into
+ * text edits that can then be applied to the original source. The rewrite infrastructure tries to generate minimal text changes and only
+ * works on the import statements. It is possible to combine the result of an import rewrite with the result of a {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite}
+ * as long as no import statements are modified by the AST rewrite.
+ * </p>
+ * <p>The options controlling the import order and on-demand thresholds are:
+ * <ul><li>{@link #setImportOrder(String[])} specifies the import groups and their preferred order</li>
+ * <li>{@link #setOnDemandImportThreshold(int)} specifies the number of imports in a group needed for a on-demand import statement (star import)</li>
+ * <li>{@link #setStaticOnDemandImportThreshold(int)} specifies the number of static imports in a group needed for a on-demand import statement (star import)</li>
+ *</ul>
+ * This class is not intended to be subclassed.
+ * </p>
+ * @since 3.2
+ */
+@SuppressWarnings("unchecked")
+public final class ImportRewrite {
+
+ /**
+ * A {@link ImportRewrite.ImportRewriteContext} can optionally be used in e.g. {@link ImportRewrite#addImport(String, ImportRewrite.ImportRewriteContext)} to
+ * give more information about the types visible in the scope. These types can be for example inherited inner types where it is
+ * unnecessary to add import statements for.
+ *
+ * </p>
+ * <p>
+ * This class can be implemented by clients.
+ * </p>
+ */
+ public static abstract class ImportRewriteContext {
+
+ /**
+ * Result constant signaling that the given element is know in the context.
+ */
+ public final static int RES_NAME_FOUND= 1;
+
+ /**
+ * Result constant signaling that the given element is not know in the context.
+ */
+ public final static int RES_NAME_UNKNOWN= 2;
+
+ /**
+ * Result constant signaling that the given element is conflicting with an other element in the context.
+ */
+ public final static int RES_NAME_CONFLICT= 3;
+
+ /**
+ * Kind constant specifying that the element is a type import.
+ */
+ public final static int KIND_TYPE= 1;
+
+ /**
+ * Kind constant specifying that the element is a static field import.
+ */
+ public final static int KIND_STATIC_FIELD= 2;
+
+ /**
+ * Kind constant specifying that the element is a static method import.
+ */
+ public final static int KIND_STATIC_METHOD= 3;
+
+ /**
+ * Searches for the given element in the context and reports if the element is known ({@link #RES_NAME_FOUND}),
+ * unknown ({@link #RES_NAME_UNKNOWN}) or if its name conflicts ({@link #RES_NAME_CONFLICT}) with an other element.
+ * @param qualifier The qualifier of the element, can be package or the qualified name of a type
+ * @param name The simple name of the element; either a type, method or field name or * for on-demand imports.
+ * @param kind The kind of the element. Can be either {@link #KIND_TYPE}, {@link #KIND_STATIC_FIELD} or
+ * {@link #KIND_STATIC_METHOD}. Implementors should be prepared for new, currently unspecified kinds and return
+ * {@link #RES_NAME_UNKNOWN} by default.
+ * @return Returns the result of the lookup. Can be either {@link #RES_NAME_FOUND}, {@link #RES_NAME_UNKNOWN} or
+ * {@link #RES_NAME_CONFLICT}.
+ */
+ public abstract int findInContext(String qualifier, String name, int kind);
+ }
+
+ private static final char STATIC_PREFIX= 's';
+ private static final char NORMAL_PREFIX= 'n';
+//{ObjectTeams:
+ private static final char BASE_PREFIX= 'b';
+// SH}
+
+ private final ImportRewriteContext defaultContext;
+
+ private final ICompilationUnit compilationUnit;
+ private final CompilationUnit astRoot;
+
+ private final boolean restoreExistingImports;
+ private final List existingImports;
+ private final Map importsKindMap;
+
+ private String[] importOrder;
+ private int importOnDemandThreshold;
+ private int staticImportOnDemandThreshold;
+
+ private List addedImports;
+ private List removedImports;
+
+ private String[] createdImports;
+ private String[] createdStaticImports;
+
+//{ObjectTeams: import base:
+ private List<String> importsToMarkAsBase;
+// SH}
+
+ private boolean filterImplicitImports;
+
+ /**
+ * Creates a {@link ImportRewrite} from a {@link ICompilationUnit}. If <code>restoreExistingImports</code>
+ * is <code>true</code>, all existing imports are kept, and new imports will be inserted at best matching locations. If
+ * <code>restoreExistingImports</code> is <code>false</code>, the existing imports will be removed and only the
+ * newly added imports will be created.
+ * <p>
+ * Note that {@link #create(ICompilationUnit, boolean)} is more efficient than this method if an AST for
+ * the compilation unit is already available.
+ * </p>
+ * @param cu the compilation unit to create the imports for
+ * @param restoreExistingImports specifies if the existing imports should be kept or removed.
+ * @return the created import rewriter.
+ * @throws JavaModelException thrown when the compilation unit could not be accessed.
+ */
+ public static ImportRewrite create(ICompilationUnit cu, boolean restoreExistingImports) throws JavaModelException {
+ if (cu == null) {
+ throw new IllegalArgumentException("Compilation unit must not be null"); //$NON-NLS-1$
+ }
+ List existingImport= null;
+ if (restoreExistingImports) {
+ existingImport= new ArrayList();
+ IImportDeclaration[] imports= cu.getImports();
+ for (int i= 0; i < imports.length; i++) {
+ IImportDeclaration curr= imports[i];
+ char prefix= Flags.isStatic(curr.getFlags()) ? STATIC_PREFIX : NORMAL_PREFIX;
+ existingImport.add(prefix + curr.getElementName());
+ }
+ }
+ return new ImportRewrite(cu, null, existingImport);
+ }
+
+ /**
+ * Creates a {@link ImportRewrite} from a an AST ({@link CompilationUnit}). The AST has to be created from a
+ * {@link ICompilationUnit}, that means {@link ASTParser#setSource(ICompilationUnit)} has been used when creating the
+ * AST. If <code>restoreExistingImports</code> is <code>true</code>, all existing imports are kept, and new imports
+ * will be inserted at best matching locations. If <code>restoreExistingImports</code> is <code>false</code>, the
+ * existing imports will be removed and only the newly added imports will be created.
+ * <p>
+ * Note that this method is more efficient than using {@link #create(ICompilationUnit, boolean)} if an AST is already available.
+ * </p>
+ * @param astRoot the AST root node to create the imports for
+ * @param restoreExistingImports specifies if the existing imports should be kept or removed.
+ * @return the created import rewriter.
+ * @throws IllegalArgumentException thrown when the passed AST is null or was not created from a compilation unit.
+ */
+ public static ImportRewrite create(CompilationUnit astRoot, boolean restoreExistingImports) {
+ if (astRoot == null) {
+ throw new IllegalArgumentException("AST must not be null"); //$NON-NLS-1$
+ }
+ ITypeRoot typeRoot = astRoot.getTypeRoot();
+ if (!(typeRoot instanceof ICompilationUnit)) {
+ throw new IllegalArgumentException("AST must have been constructed from a Java element"); //$NON-NLS-1$
+ }
+ List existingImport= null;
+ if (restoreExistingImports) {
+ existingImport= new ArrayList();
+ List imports= astRoot.imports();
+ for (int i= 0; i < imports.size(); i++) {
+ ImportDeclaration curr= (ImportDeclaration) imports.get(i);
+ StringBuffer buf= new StringBuffer();
+ buf.append(curr.isStatic() ? STATIC_PREFIX : NORMAL_PREFIX).append(curr.getName().getFullyQualifiedName());
+ if (curr.isOnDemand()) {
+ if (buf.length() > 1)
+ buf.append('.');
+ buf.append('*');
+ }
+ existingImport.add(buf.toString());
+ }
+ }
+ return new ImportRewrite((ICompilationUnit) typeRoot, astRoot, existingImport);
+ }
+
+ private ImportRewrite(ICompilationUnit cu, CompilationUnit astRoot, List existingImports) {
+ this.compilationUnit= cu;
+ this.astRoot= astRoot; // might be null
+ if (existingImports != null) {
+ this.existingImports= existingImports;
+ this.restoreExistingImports= !existingImports.isEmpty();
+ } else {
+ this.existingImports= new ArrayList();
+ this.restoreExistingImports= false;
+ }
+ this.filterImplicitImports= true;
+
+ this.defaultContext= new ImportRewriteContext() {
+ public int findInContext(String qualifier, String name, int kind) {
+ return findInImports(qualifier, name, kind);
+ }
+ };
+ this.addedImports= null; // Initialized on use
+ this.removedImports= null; // Initialized on use
+ this.createdImports= null;
+ this.createdStaticImports= null;
+//{ObjectTeams:
+ this.importsToMarkAsBase = null;
+// SH}
+
+ this.importOrder= CharOperation.NO_STRINGS;
+ this.importOnDemandThreshold= 99;
+ this.staticImportOnDemandThreshold= 99;
+
+ this.importsKindMap = new HashMap();
+ }
+
+
+ /**
+ * Defines the import groups and order to be used by the {@link ImportRewrite}.
+ * Imports are added to the group matching their qualified name most. The empty group name groups all imports not matching
+ * any other group. Static imports are managed in separate groups. Static import group names are prefixed with a '#' character.
+ * @param order A list of strings defining the import groups. A group name must be a valid package name or empty. If can be
+ * prefixed by the '#' character for static import groups
+ */
+ public void setImportOrder(String[] order) {
+ if (order == null)
+ throw new IllegalArgumentException("Order must not be null"); //$NON-NLS-1$
+ this.importOrder= order;
+ }
+
+ /**
+ * Sets the on-demand import threshold for normal (non-static) imports.
+ * This threshold defines the number of imports that need to be in a group to use
+ * a on-demand (star) import declaration instead.
+ *
+ * @param threshold a positive number defining the on-demand import threshold
+ * for normal (non-static) imports.
+ * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
+ * if the number is not positive.
+ */
+ public void setOnDemandImportThreshold(int threshold) {
+ if (threshold <= 0)
+ throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
+ this.importOnDemandThreshold= threshold;
+ }
+
+ /**
+ * Sets the on-demand import threshold for static imports.
+ * This threshold defines the number of imports that need to be in a group to use
+ * a on-demand (star) import declaration instead.
+ *
+ * @param threshold a positive number defining the on-demand import threshold
+ * for normal (non-static) imports.
+ * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
+ * if the number is not positive.
+ */
+ public void setStaticOnDemandImportThreshold(int threshold) {
+ if (threshold <= 0)
+ throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
+ this.staticImportOnDemandThreshold= threshold;
+ }
+
+ /**
+ * The compilation unit for which this import rewrite was created for.
+ * @return the compilation unit for which this import rewrite was created for.
+ */
+ public ICompilationUnit getCompilationUnit() {
+ return this.compilationUnit;
+ }
+
+ /**
+ * Returns the default rewrite context that only knows about the imported types. Clients
+ * can write their own context and use the default context for the default behavior.
+ * @return the default import rewrite context.
+ */
+ public ImportRewriteContext getDefaultImportRewriteContext() {
+ return this.defaultContext;
+ }
+
+ /**
+ * Specifies that implicit imports (types in default package, package <code>java.lang</code> or
+ * in the same package as the rewrite compilation unit should not be created except if necessary
+ * to resolve an on-demand import conflict. The filter is enabled by default.
+ * @param filterImplicitImports if set, implicit imports will be filtered.
+ */
+ public void setFilterImplicitImports(boolean filterImplicitImports) {
+ this.filterImplicitImports= filterImplicitImports;
+ }
+
+ private static int compareImport(char prefix, String qualifier, String name, String curr) {
+ if (curr.charAt(0) != prefix || !curr.endsWith(name)) {
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+
+ curr= curr.substring(1); // remove the prefix
+
+ if (curr.length() == name.length()) {
+ if (qualifier.length() == 0) {
+ return ImportRewriteContext.RES_NAME_FOUND;
+ }
+ return ImportRewriteContext.RES_NAME_CONFLICT;
+ }
+ // at this place: curr.length > name.length
+
+ int dotPos= curr.length() - name.length() - 1;
+ if (curr.charAt(dotPos) != '.') {
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+ if (qualifier.length() != dotPos || !curr.startsWith(qualifier)) {
+ return ImportRewriteContext.RES_NAME_CONFLICT;
+ }
+ return ImportRewriteContext.RES_NAME_FOUND;
+ }
+
+ /**
+ * Not API, package visibility as accessed from an anonymous type
+ */
+ /* package */ final int findInImports(String qualifier, String name, int kind) {
+ boolean allowAmbiguity= (kind == ImportRewriteContext.KIND_STATIC_METHOD) || (name.length() == 1 && name.charAt(0) == '*');
+ List imports= this.existingImports;
+ char prefix= (kind == ImportRewriteContext.KIND_TYPE) ? NORMAL_PREFIX : STATIC_PREFIX;
+
+ for (int i= imports.size() - 1; i >= 0 ; i--) {
+ String curr= (String) imports.get(i);
+ int res= compareImport(prefix, qualifier, name, curr);
+ if (res != ImportRewriteContext.RES_NAME_UNKNOWN) {
+ if (!allowAmbiguity || res == ImportRewriteContext.RES_NAME_FOUND) {
+ if (prefix != STATIC_PREFIX) {
+ return res;
+ }
+ Object currKind = this.importsKindMap.get(curr.substring(1));
+ if (currKind != null && currKind.equals(this.importsKindMap.get(qualifier + '.' + name))) {
+ return res;
+ }
+ }
+ }
+ }
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
+ * in the code as a reference to the type. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param typeSig the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImportFromSignature(String typeSig, AST ast) {
+ return addImportFromSignature(typeSig, ast, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
+ * in the code as a reference to the type. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param typeSig the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @param context an optional context that knows about types visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImportFromSignature(String typeSig, AST ast, ImportRewriteContext context) {
+ if (typeSig == null || typeSig.length() == 0) {
+ throw new IllegalArgumentException("Invalid type signature: empty or null"); //$NON-NLS-1$
+ }
+ int sigKind= Signature.getTypeSignatureKind(typeSig);
+ switch (sigKind) {
+ case Signature.BASE_TYPE_SIGNATURE:
+ return ast.newPrimitiveType(PrimitiveType.toCode(Signature.toString(typeSig)));
+ case Signature.ARRAY_TYPE_SIGNATURE:
+ Type elementType= addImportFromSignature(Signature.getElementType(typeSig), ast, context);
+ return ast.newArrayType(elementType, Signature.getArrayCount(typeSig));
+ case Signature.CLASS_TYPE_SIGNATURE:
+ String erasureSig= Signature.getTypeErasure(typeSig);
+
+ String erasureName= Signature.toString(erasureSig);
+ if (erasureSig.charAt(0) == Signature.C_RESOLVED) {
+ erasureName= internalAddImport(erasureName, context);
+ }
+ Type baseType= ast.newSimpleType(ast.newName(erasureName));
+ String[] typeArguments= Signature.getTypeArguments(typeSig);
+ if (typeArguments.length > 0) {
+ ParameterizedType type= ast.newParameterizedType(baseType);
+ List argNodes= type.typeArguments();
+ for (int i= 0; i < typeArguments.length; i++) {
+ String curr= typeArguments[i];
+ if (containsNestedCapture(curr)) { // see bug 103044
+ argNodes.add(ast.newWildcardType());
+ } else {
+ argNodes.add(addImportFromSignature(curr, ast, context));
+ }
+ }
+ return type;
+ }
+ return baseType;
+ case Signature.TYPE_VARIABLE_SIGNATURE:
+ return ast.newSimpleType(ast.newSimpleName(Signature.toString(typeSig)));
+ case Signature.WILDCARD_TYPE_SIGNATURE:
+ WildcardType wildcardType= ast.newWildcardType();
+ char ch= typeSig.charAt(0);
+ if (ch != Signature.C_STAR) {
+ Type bound= addImportFromSignature(typeSig.substring(1), ast, context);
+ wildcardType.setBound(bound, ch == Signature.C_EXTENDS);
+ }
+ return wildcardType;
+ case Signature.CAPTURE_TYPE_SIGNATURE:
+ return addImportFromSignature(typeSig.substring(1), ast, context);
+ default:
+ throw new IllegalArgumentException("Unknown type signature kind: " + typeSig); //$NON-NLS-1$
+ }
+ }
+
+
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding the signature of the type to be added.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(ITypeBinding binding) {
+ return addImport(binding, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding the signature of the type to be added.
+ * @param context an optional context that knows about types visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(ITypeBinding binding, ImportRewriteContext context) {
+ if (binding.isPrimitive() || binding.isTypeVariable() || binding.isRecovered()) {
+ return binding.getName();
+ }
+
+ ITypeBinding normalizedBinding= normalizeTypeBinding(binding);
+ if (normalizedBinding == null) {
+ return "invalid"; //$NON-NLS-1$
+ }
+ if (normalizedBinding.isWildcardType()) {
+ StringBuffer res= new StringBuffer("?"); //$NON-NLS-1$
+ ITypeBinding bound= normalizedBinding.getBound();
+ if (bound != null && !bound.isWildcardType() && !bound.isCapture()) { // bug 95942
+ if (normalizedBinding.isUpperbound()) {
+ res.append(" extends "); //$NON-NLS-1$
+ } else {
+ res.append(" super "); //$NON-NLS-1$
+ }
+ res.append(addImport(bound, context));
+ }
+ return res.toString();
+ }
+
+ if (normalizedBinding.isArray()) {
+ StringBuffer res= new StringBuffer(addImport(normalizedBinding.getElementType(), context));
+ for (int i= normalizedBinding.getDimensions(); i > 0; i--) {
+ res.append("[]"); //$NON-NLS-1$
+ }
+ return res.toString();
+ }
+
+ String qualifiedName= getRawQualifiedName(normalizedBinding);
+ if (qualifiedName.length() > 0) {
+//{ObjectTeams: silently refuse to import a role type:
+/* orig:
+ String str= internalAddImport(qualifiedName, context);
+ :giro */
+ String str= importRefusingRole(binding, qualifiedName, context);
+// SH}
+
+
+ ITypeBinding[] typeArguments= normalizedBinding.getTypeArguments();
+ if (typeArguments.length > 0) {
+ StringBuffer res= new StringBuffer(str);
+ res.append('<');
+ for (int i= 0; i < typeArguments.length; i++) {
+ if (i > 0) {
+ res.append(',');
+ }
+ ITypeBinding curr= typeArguments[i];
+ if (containsNestedCapture(curr, false)) { // see bug 103044
+ res.append('?');
+ } else {
+ res.append(addImport(curr, context));
+ }
+ }
+ res.append('>');
+ return res.toString();
+ }
+ return str;
+ }
+ return getRawName(normalizedBinding);
+ }
+
+ private boolean containsNestedCapture(ITypeBinding binding, boolean isNested) {
+ if (binding == null || binding.isPrimitive() || binding.isTypeVariable()) {
+ return false;
+ }
+ if (binding.isCapture()) {
+ if (isNested) {
+ return true;
+ }
+ return containsNestedCapture(binding.getWildcard(), true);
+ }
+ if (binding.isWildcardType()) {
+ return containsNestedCapture(binding.getBound(), true);
+ }
+ if (binding.isArray()) {
+ return containsNestedCapture(binding.getElementType(), true);
+ }
+ ITypeBinding[] typeArguments= binding.getTypeArguments();
+ for (int i= 0; i < typeArguments.length; i++) {
+ if (containsNestedCapture(typeArguments[i], true)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean containsNestedCapture(String signature) {
+ return signature.length() > 1 && signature.indexOf(Signature.C_CAPTURE, 1) != -1;
+ }
+
+ private static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
+ if (binding != null && !binding.isNullType() && !"void".equals(binding.getName())) { //$NON-NLS-1$
+ if (binding.isAnonymous()) {
+ ITypeBinding[] baseBindings= binding.getInterfaces();
+ if (baseBindings.length > 0) {
+ return baseBindings[0];
+ }
+ return binding.getSuperclass();
+ }
+ if (binding.isCapture()) {
+ return binding.getWildcard();
+ }
+ return binding;
+ }
+ return null;
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
+ * in the code. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImport(ITypeBinding binding, AST ast) {
+ return addImport(binding, ast, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
+ * in the code. The type binding can be an array binding, type variable or wildcard.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
+ * of wildcards are ignored.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @param context an optional context that knows about types visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImport(ITypeBinding binding, AST ast, ImportRewriteContext context) {
+ if (binding.isPrimitive()) {
+ return ast.newPrimitiveType(PrimitiveType.toCode(binding.getName()));
+ }
+
+ ITypeBinding normalizedBinding= normalizeTypeBinding(binding);
+ if (normalizedBinding == null) {
+ return ast.newSimpleType(ast.newSimpleName("invalid")); //$NON-NLS-1$
+ }
+
+ if (normalizedBinding.isTypeVariable()) {
+ // no import
+ return ast.newSimpleType(ast.newSimpleName(binding.getName()));
+ }
+ if (normalizedBinding.isWildcardType()) {
+ WildcardType wcType= ast.newWildcardType();
+ ITypeBinding bound= normalizedBinding.getBound();
+ if (bound != null && !bound.isWildcardType() && !bound.isCapture()) { // bug 96942
+ Type boundType= addImport(bound, ast, context);
+ wcType.setBound(boundType, normalizedBinding.isUpperbound());
+ }
+ return wcType;
+ }
+
+ if (normalizedBinding.isArray()) {
+ Type elementType= addImport(normalizedBinding.getElementType(), ast, context);
+ return ast.newArrayType(elementType, normalizedBinding.getDimensions());
+ }
+
+ String qualifiedName= getRawQualifiedName(normalizedBinding);
+ if (qualifiedName.length() > 0) {
+//{ObjectTeams: silently refuse to import a role type:
+/* orig:
+ String res= internalAddImport(qualifiedName, context);
+ :giro */
+ String res= importRefusingRole(binding, qualifiedName, context);
+// SH}
+
+ ITypeBinding[] typeArguments= normalizedBinding.getTypeArguments();
+ if (typeArguments.length > 0) {
+ Type erasureType= ast.newSimpleType(ast.newName(res));
+ ParameterizedType paramType= ast.newParameterizedType(erasureType);
+ List arguments= paramType.typeArguments();
+ for (int i= 0; i < typeArguments.length; i++) {
+ ITypeBinding curr= typeArguments[i];
+ if (containsNestedCapture(curr, false)) { // see bug 103044
+ arguments.add(ast.newWildcardType());
+ } else {
+ arguments.add(addImport(curr, ast, context));
+ }
+ }
+ return paramType;
+ }
+/* orig:
+ return ast.newSimpleType(ast.newName(res));
+ :giro */
+ Type type = ast.newSimpleType(ast.newName(res));
+ if (binding.isDependentType(true)) {
+ // ignoring value parameters would introduce type errors in refactorings.
+ String[] segments = binding.getAnchorPath();
+ if (segments.length > 0) {
+ ParameterizedType pType = ast.newParameterizedType(type);
+ pType.typeArguments().add(ast.newTypeAnchor(ast.newName(segments)));
+ type = pType;
+ }
+ }
+ return type;
+ }
+ return ast.newSimpleType(ast.newName(getRawName(normalizedBinding)));
+ }
+
+//{ObjectTeams: try to add an import but refuse if binding is a role.
+ private String importRefusingRole(ITypeBinding binding, String qualifiedName, ImportRewriteContext context) {
+ String res= qualifiedName;
+ if (binding.isRole()) { // still need to extract the simple name
+ int pos = qualifiedName.lastIndexOf('.');
+ if (pos > -1)
+ res= qualifiedName.substring(pos+1);
+ } else
+ res= internalAddImport(qualifiedName, context);
+ return res;
+ }
+// SH}
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can only be an array or non-generic type.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param qualifiedTypeName the qualified type name of the type to be added
+ * @param context an optional context that knows about types visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(String qualifiedTypeName, ImportRewriteContext context) {
+ int angleBracketOffset= qualifiedTypeName.indexOf('<');
+ if (angleBracketOffset != -1) {
+ return internalAddImport(qualifiedTypeName.substring(0, angleBracketOffset), context) + qualifiedTypeName.substring(angleBracketOffset);
+ }
+ int bracketOffset= qualifiedTypeName.indexOf('[');
+ if (bracketOffset != -1) {
+ return internalAddImport(qualifiedTypeName.substring(0, bracketOffset), context) + qualifiedTypeName.substring(bracketOffset);
+ }
+ return internalAddImport(qualifiedTypeName, context);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can only be an array or non-generic type.
+ * <p>
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param qualifiedTypeName the qualified type name of the type to be added
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(String qualifiedTypeName) {
+ return addImport(qualifiedTypeName, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ * <p>
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding The binding of the static field or method to be added.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
+ * or method.
+ */
+ public String addStaticImport(IBinding binding) {
+ return addStaticImport(binding, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ * <p>
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param binding The binding of the static field or method to be added.
+ * @param context an optional context that knows about members visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
+ * or method.
+ */
+ public String addStaticImport(IBinding binding, ImportRewriteContext context) {
+ if (Modifier.isStatic(binding.getModifiers())) {
+ if (binding instanceof IVariableBinding) {
+ IVariableBinding variableBinding= (IVariableBinding) binding;
+ if (variableBinding.isField()) {
+ ITypeBinding declaringType= variableBinding.getDeclaringClass();
+ return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), true, context);
+ }
+ } else if (binding instanceof IMethodBinding) {
+ ITypeBinding declaringType= ((IMethodBinding) binding).getDeclaringClass();
+ return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), false, context);
+ }
+ }
+ throw new IllegalArgumentException("Binding must be a static field or method."); //$NON-NLS-1$
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ * <p>
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param declaringTypeName The qualified name of the static's member declaring type
+ * @param simpleName the simple name of the member; either a field or a method name.
+ * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
+ * method.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ */
+ public String addStaticImport(String declaringTypeName, String simpleName, boolean isField) {
+ return addStaticImport(declaringTypeName, simpleName, isField, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ * <p>
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ * </p>
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ * </p>
+ * @param declaringTypeName The qualified name of the static's member declaring type
+ * @param simpleName the simple name of the member; either a field or a method name.
+ * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
+ * method.
+ * @param context an optional context that knows about members visible in the current scope or <code>null</code>
+ * to use the default context only using the available imports.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ */
+ public String addStaticImport(String declaringTypeName, String simpleName, boolean isField, ImportRewriteContext context) {
+ String key = declaringTypeName + '.' + simpleName;
+ if (declaringTypeName.indexOf('.') == -1) {
+ return key;
+ }
+ if (context == null) {
+ context= this.defaultContext;
+ }
+ int kind= isField ? ImportRewriteContext.KIND_STATIC_FIELD : ImportRewriteContext.KIND_STATIC_METHOD;
+ this.importsKindMap.put(key, new Integer(kind));
+ int res= context.findInContext(declaringTypeName, simpleName, kind);
+ if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
+ return key;
+ }
+ if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
+ addEntry(STATIC_PREFIX + key);
+ }
+ return simpleName;
+ }
+
+ private String internalAddImport(String fullTypeName, ImportRewriteContext context) {
+ int idx= fullTypeName.lastIndexOf('.');
+ String typeContainerName, typeName;
+ if (idx != -1) {
+ typeContainerName= fullTypeName.substring(0, idx);
+ typeName= fullTypeName.substring(idx + 1);
+ } else {
+ typeContainerName= ""; //$NON-NLS-1$
+ typeName= fullTypeName;
+ }
+
+ if (typeContainerName.length() == 0 && PrimitiveType.toCode(typeName) != null) {
+ return fullTypeName;
+ }
+
+ if (context == null)
+ context= this.defaultContext;
+
+ int res= context.findInContext(typeContainerName, typeName, ImportRewriteContext.KIND_TYPE);
+ if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
+ return fullTypeName;
+ }
+ if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
+ addEntry(NORMAL_PREFIX + fullTypeName);
+ }
+ return typeName;
+ }
+
+ private void addEntry(String entry) {
+ this.existingImports.add(entry);
+
+ if (this.removedImports != null) {
+ if (this.removedImports.remove(entry)) {
+ return;
+ }
+ }
+
+ if (this.addedImports == null) {
+ this.addedImports= new ArrayList();
+ }
+ this.addedImports.add(entry);
+ }
+
+ private boolean removeEntry(String entry) {
+ if (this.existingImports.remove(entry)) {
+ if (this.addedImports != null) {
+ if (this.addedImports.remove(entry)) {
+ return true;
+ }
+ }
+ if (this.removedImports == null) {
+ this.removedImports= new ArrayList();
+ }
+ this.removedImports.add(entry);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Records to remove a import. No remove is recorded if no such import exists or if such an import is recorded
+ * to be added. In that case the record of the addition is discarded.
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that an import has been removed.
+ * </p>
+ * @param qualifiedName The import name to remove.
+ * @return <code>true</code> is returned of an import of the given name could be found.
+ */
+ public boolean removeImport(String qualifiedName) {
+ return removeEntry(NORMAL_PREFIX + qualifiedName);
+ }
+
+ /**
+ * Records to remove a static import. No remove is recorded if no such import exists or if such an import is recorded
+ * to be added. In that case the record of the addition is discarded.
+ * <p>
+ * The content of the compilation unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been removed.
+ * </p>
+ * @param qualifiedName The import name to remove.
+ * @return <code>true</code> is returned of an import of the given name could be found.
+ */
+ public boolean removeStaticImport(String qualifiedName) {
+ return removeEntry(STATIC_PREFIX + qualifiedName);
+ }
+
+ private static String getRawName(ITypeBinding normalizedBinding) {
+ return normalizedBinding.getTypeDeclaration().getName();
+ }
+
+ private static String getRawQualifiedName(ITypeBinding normalizedBinding) {
+ return normalizedBinding.getTypeDeclaration().getQualifiedName();
+ }
+
+
+ /**
+ * Converts all modifications recorded by this rewriter into an object representing the corresponding text
+ * edits to the source code of the rewrite's compilation unit. The compilation unit itself is not modified.
+ * <p>
+ * Calling this methods does not discard the modifications on record. Subsequence modifications are added
+ * to the ones already on record. If this method is called again later, the resulting text edit object will accurately
+ * reflect the net cumulative affect of all those changes.
+ * </p>
+ * @param monitor the progress monitor or <code>null</code>
+ * @return text edit object describing the changes to the document corresponding to the changes
+ * recorded by this rewriter
+ * @throws CoreException the exception is thrown if the rewrite fails.
+ */
+ public final TextEdit rewriteImports(IProgressMonitor monitor) throws CoreException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+
+ try {
+ monitor.beginTask(Messages.bind(Messages.importRewrite_processDescription), 2);
+ if (!hasRecordedChanges()) {
+ this.createdImports= CharOperation.NO_STRINGS;
+ this.createdStaticImports= CharOperation.NO_STRINGS;
+ return new MultiTextEdit();
+ }
+
+ CompilationUnit usedAstRoot= this.astRoot;
+ if (usedAstRoot == null) {
+ ASTParser parser= ASTParser.newParser(AST.JLS3);
+ parser.setSource(this.compilationUnit);
+ parser.setFocalPosition(0); // reduced AST
+ parser.setResolveBindings(false);
+ usedAstRoot= (CompilationUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
+ }
+
+ ImportRewriteAnalyzer computer= new ImportRewriteAnalyzer(this.compilationUnit, usedAstRoot, this.importOrder, this.importOnDemandThreshold, this.staticImportOnDemandThreshold, this.restoreExistingImports);
+ computer.setFilterImplicitImports(this.filterImplicitImports);
+
+ if (this.addedImports != null) {
+ for (int i= 0; i < this.addedImports.size(); i++) {
+ String curr= (String) this.addedImports.get(i);
+//{ObjectTeams: base import:
+ if (BASE_PREFIX == curr.charAt(0))
+ computer.addBaseImport(curr.substring(1));
+ else
+ computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0), /*isBase*/false);
+ /* orig:
+ computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0));
+ :giro */
+// SH}
+ }
+ }
+
+ if (this.removedImports != null) {
+ for (int i= 0; i < this.removedImports.size(); i++) {
+ String curr= (String) this.removedImports.get(i);
+//{ObjectTeams: added isBase arg:
+/* orig:
+ computer.removeImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0));
+ :giro */
+ computer.removeImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0), BASE_PREFIX == curr.charAt(0));
+// SH}
+ }
+ }
+//{ObjectTeams: import base:
+ if (this.importsToMarkAsBase != null) {
+ for (int i= 0; i < this.importsToMarkAsBase.size(); i++) {
+ String curr = this.importsToMarkAsBase.get(i);
+ computer.setBase(curr);
+ }
+ }
+// SH}
+
+ TextEdit result= computer.getResultingEdits(new SubProgressMonitor(monitor, 1));
+ this.createdImports= computer.getCreatedImports();
+ this.createdStaticImports= computer.getCreatedStaticImports();
+ return result;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Returns all new non-static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
+ * or <code>null</code> if these methods have not been called yet.
+ * <p>
+ * Note that this list doesn't need to be the same as the added imports (see {@link #getAddedImports()}) as
+ * implicit imports are not created and some imports are represented by on-demand imports instead.
+ * </p>
+ * @return the created imports
+ */
+ public String[] getCreatedImports() {
+ return this.createdImports;
+ }
+
+ /**
+ * Returns all new static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
+ * or <code>null</code> if these methods have not been called yet.
+ * <p>
+ * Note that this list doesn't need to be the same as the added static imports ({@link #getAddedStaticImports()}) as
+ * implicit imports are not created and some imports are represented by on-demand imports instead.
+ * </p
+ * @return the created imports
+ */
+ public String[] getCreatedStaticImports() {
+ return this.createdStaticImports;
+ }
+
+ /**
+ * Returns all non-static imports that are recorded to be added.
+ *
+ * @return the imports recorded to be added.
+ */
+ public String[] getAddedImports() {
+ return filterFromList(this.addedImports, NORMAL_PREFIX);
+ }
+
+ /**
+ * Returns all static imports that are recorded to be added.
+ *
+ * @return the static imports recorded to be added.
+ */
+ public String[] getAddedStaticImports() {
+ return filterFromList(this.addedImports, STATIC_PREFIX);
+ }
+
+ /**
+ * Returns all non-static imports that are recorded to be removed.
+ *
+ * @return the imports recorded to be removed.
+ */
+ public String[] getRemovedImports() {
+ return filterFromList(this.removedImports, NORMAL_PREFIX);
+ }
+
+ /**
+ * Returns all static imports that are recorded to be removed.
+ *
+ * @return the static imports recorded to be removed.
+ */
+ public String[] getRemovedStaticImports() {
+ return filterFromList(this.removedImports, STATIC_PREFIX);
+ }
+
+ /**
+ * Returns <code>true</code> if imports have been recorded to be added or removed.
+ * @return boolean returns if any changes to imports have been recorded.
+ */
+ public boolean hasRecordedChanges() {
+ return !this.restoreExistingImports ||
+ (this.addedImports != null && !this.addedImports.isEmpty()) ||
+//{ObjectTeams:
+ (this.importsToMarkAsBase != null && !this.importsToMarkAsBase.isEmpty()) ||
+// SH}
+ (this.removedImports != null && !this.removedImports.isEmpty());
+ }
+
+//{ObjectTeams: my version of above in anticipation of https://bugs.eclipse.org/bugs/show_bug.cgi?id=271812
+ public boolean myHasRecordedChanges() {
+ return
+ (this.addedImports != null && !this.addedImports.isEmpty()) ||
+//{ObjectTeams:
+ (this.importsToMarkAsBase != null && !this.importsToMarkAsBase.isEmpty()) ||
+// SH}
+ (this.removedImports != null && !this.removedImports.isEmpty());
+ }
+// SH}
+
+ private static String[] filterFromList(List imports, char prefix) {
+ if (imports == null) {
+ return CharOperation.NO_STRINGS;
+ }
+ ArrayList res= new ArrayList();
+ for (int i= 0; i < imports.size(); i++) {
+ String curr= (String) imports.get(i);
+ if (prefix == curr.charAt(0)) {
+ res.add(curr.substring(1));
+ }
+ }
+ return (String[]) res.toArray(new String[res.size()]);
+ }
+
+//{ObjectTeams: import base (not like the others, since this only changes an existing import).
+ public boolean setImportBase(IBinding binding) {
+ if (!(binding instanceof ITypeBinding))
+ throw new IllegalArgumentException("Binding must be a type."); //$NON-NLS-1$
+ return setImportBase(((ITypeBinding)binding).getQualifiedName(), this.defaultContext);
+ }
+
+ public boolean setImportBase(String qualifiedTypeName, ImportRewriteContext context) {
+ int lastDot = qualifiedTypeName.lastIndexOf('.');
+ if (lastDot == -1) {
+ return false;
+ }
+ if (context == null) {
+ context= this.defaultContext;
+ }
+ int kind= ImportRewriteContext.KIND_TYPE;
+ String qualifier = qualifiedTypeName.substring(0, lastDot);
+ String simpleName = qualifiedTypeName.substring(lastDot+1);
+ int res= context.findInContext(qualifier, simpleName, kind);
+ if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
+ return false;
+ }
+ if (res == ImportRewriteContext.RES_NAME_FOUND) {
+ if (this.importsToMarkAsBase == null)
+ this.importsToMarkAsBase = new ArrayList(1);
+ this.importsToMarkAsBase.add(qualifiedTypeName);
+ }
+ return true;
+ }
+ // Note: the "base" modifier will be provided by role org.eclipse.objectteams.otdt.ui.assist.BaseImportRewriting.ImportRewriteAdaptor
+ public String addImportBase(String baseName) {
+ return this.addImport(baseName);
+ }
+// SH}
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
new file mode 100644
index 000000000..133a3be1a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
@@ -0,0 +1,440 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom.rewrite;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.text.edits.TextEditGroup;
+
+/**
+ * For describing manipulations to a child list property of an AST node.
+ * <p>
+ * This class is not intended to be subclassed.
+ * </p>
+ * @see ASTRewrite#getListRewrite(ASTNode, ChildListPropertyDescriptor)
+ * @since 3.0
+ */
+public final class ListRewrite {
+
+ private ASTNode parent;
+ private StructuralPropertyDescriptor childProperty;
+ private ASTRewrite rewriter;
+
+
+ /* package*/ ListRewrite(ASTRewrite rewriter, ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ this.rewriter= rewriter;
+ this.parent= parent;
+//{ObjectTeams: correct invalid combination TypeDeclaration/RoleTypeDeclaration:
+ // note: clients like ModifierCorrectionSubProcessor might need to handle
+ // RoleTypeDeclarations without explict knowledge.
+ if ( parent.getNodeType() == ASTNode.ROLE_TYPE_DECLARATION
+ && childProperty.getNodeClass() == TypeDeclaration.class)
+ {
+ if (childProperty == TypeDeclaration.MODIFIERS2_PROPERTY)
+ childProperty = RoleTypeDeclaration.MODIFIERS2_PROPERTY;
+ else if (childProperty == TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY)
+ childProperty = RoleTypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
+ else if (childProperty == TypeDeclaration.TYPE_PARAMETERS_PROPERTY)
+ childProperty = RoleTypeDeclaration.TYPE_PARAMETERS_PROPERTY;
+ else if (childProperty == TypeDeclaration.BODY_DECLARATIONS_PROPERTY)
+ childProperty = RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY;
+ }
+// SH}
+ this.childProperty= childProperty;
+ }
+
+ private RewriteEventStore getRewriteStore() {
+ return this.rewriter.getRewriteEventStore();
+ }
+
+ private ListRewriteEvent getEvent() {
+ return getRewriteStore().getListEvent(this.parent, this.childProperty, true);
+ }
+
+ /**
+ * Returns the parent of the list for which this list rewriter was created.
+
+ * @return the node that contains the list for which this list rewriter was created
+ * @see #getLocationInParent()
+ * @since 3.1
+ */
+ public ASTNode getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Returns the property of the parent node for which this list rewriter was created.
+ *
+ * @return the property of the parent node for which this list rewriter was created
+ * @see #getParent()
+ * @since 3.1
+ */
+ public StructuralPropertyDescriptor getLocationInParent() {
+ return this.childProperty;
+ }
+
+ /**
+ * Removes the given node from its parent's list property in the rewriter.
+ * The node must be contained in the list.
+ * The AST itself is not actually modified in any way; rather, the rewriter
+ * just records a note that this node has been removed from this list.
+ *
+ * @param node the node being removed. The node can either be an original node in this list
+ * or (since 3.4) a new node already inserted or used as replacement in this AST rewriter.
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not
+ * part of this rewriter's AST, or if the described modification is invalid
+ * (not a member of this node's original list)
+ */
+ public void remove(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ RewriteEvent event= getEvent().removeEntry(node);
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+ /**
+ * Returns the ASTRewrite instance from which this ListRewriter has been created from.
+ * @return the parent AST Rewriter instance.
+ * @since 3.1
+ */
+ public ASTRewrite getASTRewrite() {
+ return this.rewriter;
+ }
+
+
+ /**
+ * Replaces the given node from its parent's list property in the rewriter.
+ * The node must be contained in the list.
+ * The replacement node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been replaced in this list.
+ *
+ * @param node the node being removed. The node can either be an original node in this list
+ * or (since 3.4) a new node already inserted or used as replacement in this AST rewriter.
+ * @param replacement the replacement node, or <code>null</code> if no
+ * replacement
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the replacement node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ */
+ public void replace(ASTNode node, ASTNode replacement, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ RewriteEvent event= getEvent().replaceEntry(node, replacement);
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+ /**
+ * Inserts the given node into the list after the given element.
+ * The existing node must be in the list, either as an original or as a new
+ * node that has been inserted.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param element the element after which the given node is to be inserted
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node or element is null,
+ * or if the node is not part of this rewriter's AST, or if the inserted node
+ * is not a new node (or placeholder), or if <code>element</code> is not a member
+ * of the list (original or new), or if the described modification is
+ * otherwise invalid
+ */
+ public void insertAfter(ASTNode node, ASTNode element, TextEditGroup editGroup) {
+ if (node == null || element == null) {
+ throw new IllegalArgumentException();
+ }
+ int index= getEvent().getIndex(element, ListRewriteEvent.BOTH);
+ if (index == -1) {
+ throw new IllegalArgumentException("Node does not exist"); //$NON-NLS-1$
+ }
+ internalInsertAt(node, index + 1, true, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list before the given element.
+ * The existing node must be in the list, either as an original or as a new
+ * node that has been inserted.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param element the element before which the given node is to be inserted
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node or element is null,
+ * or if the node is not part of this rewriter's AST, or if the inserted node
+ * is not a new node (or placeholder), or if <code>element</code> is not a member
+ * of the list (original or new), or if the described modification is
+ * otherwise invalid
+ */
+ public void insertBefore(ASTNode node, ASTNode element, TextEditGroup editGroup) {
+ if (node == null || element == null) {
+ throw new IllegalArgumentException();
+ }
+ int index= getEvent().getIndex(element, ListRewriteEvent.BOTH);
+ if (index == -1) {
+ throw new IllegalArgumentException("Node does not exist"); //$NON-NLS-1$
+ }
+ internalInsertAt(node, index, false, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the start of the list.
+ * Equivalent to <code>insertAt(node, 0, editGroup)</code>.
+ *
+ * @param node the node to insert
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @see #insertAt(ASTNode, int, TextEditGroup)
+ */
+ public void insertFirst(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, 0, false, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the end of the list.
+ * Equivalent to <code>insertAt(node, -1, editGroup)</code>.
+ *
+ * @param node the node to insert
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @see #insertAt(ASTNode, int, TextEditGroup)
+ */
+ public void insertLast(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, -1, true, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the given index.
+ * The index corresponds to a combined list of original and new nodes;
+ * removed or replaced nodes are still in the combined list.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param index insertion index in the combined list of original and
+ * inserted nodes; <code>-1</code> indicates insertion as the last element
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or <code>null</code> if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @throws IndexOutOfBoundsException if the index is negative and not -1,
+ * or if it is larger than the size of the combined list
+ */
+ public void insertAt(ASTNode node, int index, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, index, isInsertBoundToPreviousByDefault(node), editGroup);
+ }
+
+ private void internalInsertAt(ASTNode node, int index, boolean boundToPrevious, TextEditGroup editGroup) {
+ RewriteEvent event= getEvent().insert(node, index);
+ if (boundToPrevious) {
+ getRewriteStore().setInsertBoundToPrevious(node);
+ }
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+
+ private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) {
+ if (first == null || last == null) {
+ throw new IllegalArgumentException();
+ }
+
+ NodeInfoStore nodeStore= this.rewriter.getNodeStore();
+ ASTNode placeholder= nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
+ if (placeholder == null) {
+ throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + first.getClass().getName()); //$NON-NLS-1$
+ }
+
+ Block internalPlaceHolder= nodeStore.createCollapsePlaceholder();
+ CopySourceInfo info= getRewriteStore().createRangeCopy(this.parent, this.childProperty, first, last, isMove, internalPlaceHolder, replacingNode, editGroup);
+ nodeStore.markAsCopyTarget(placeholder, info);
+
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a placeholder node for a true copy of a range of nodes of the
+ * current list.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are <code>null</code>, if a node is not a child of the current list or if the first node
+ * is not before the last node. An <code>IllegalArgumentException</code> is
+ * also thrown if the copied range is overlapping with an other moved or copied range.
+ */
+ public final ASTNode createCopyTarget(ASTNode first, ASTNode last) {
+ if (first == last) {
+ return this.rewriter.createCopyTarget(first);
+ } else {
+ return createTargetNode(first, last, false, null, null);
+ }
+ }
+
+ /**
+ * Creates and returns a placeholder node for a move of a range of nodes of the
+ * current list.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are <code>null</code>, if a node is not a child of the current list or if the first node
+ * is not before the last node. An <code>IllegalArgumentException</code> is
+ * also thrown if the moved range is overlapping with an other moved or copied range.
+ *
+ * @since 3.1
+ */
+ public final ASTNode createMoveTarget(ASTNode first, ASTNode last) {
+ return createMoveTarget(first, last, null, null);
+ }
+
+ /**
+ * Creates and returns a placeholder node for a move of a range of nodes of the
+ * current list. The moved nodes can optionally be replaced by a specified node.
+ *
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @param replacingNode a node that is set at the location of the moved nodes
+ * or <code>null</code> to remove all nodes
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits fro a replace, or <code>null</code> if ungrouped
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or
+ * last node are <code>null</code>, if a node is not a child of the current list or
+ * if the first node is not before the last node. An <code>IllegalArgumentException
+ * </code> is also thrown if the moved range is overlapping with an other moved
+ * or copied range.
+ *
+ * @since 3.1
+ */
+ public final ASTNode createMoveTarget(ASTNode first, ASTNode last, ASTNode replacingNode, TextEditGroup editGroup) {
+ if (first == last) {
+ replace(first, replacingNode, editGroup);
+ return this.rewriter.createMoveTarget(first);
+ } else {
+ return createTargetNode(first, last, true, replacingNode, editGroup);
+ }
+ }
+
+ /*
+ * Heuristic to decide if a inserted node is bound to previous or the next sibling.
+ */
+ private boolean isInsertBoundToPreviousByDefault(ASTNode node) {
+ return (node instanceof Statement || node instanceof FieldDeclaration);
+ }
+
+ /**
+ * Returns the original nodes in the list property managed by this
+ * rewriter. The returned list is unmodifiable.
+ *
+ * @return a list of all original nodes in the list
+ */
+ public List getOriginalList() {
+ List list= (List) getEvent().getOriginalValue();
+ return Collections.unmodifiableList(list);
+ }
+
+ /**
+ * Returns the nodes in the revised list property managed by this
+ * rewriter. The returned list is unmodifiable.
+ *
+ * @return a list of all nodes in the list taking into account
+ * all the described changes
+ */
+ public List getRewrittenList() {
+ List list= (List) getEvent().getNewValue();
+ return Collections.unmodifiableList(list);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java
new file mode 100644
index 000000000..2ed0c9f22
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom.rewrite;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+
+/**
+ * An object for computing adjusted source ranges for AST nodes
+ * that are being replaced or deleted.
+ * <p>
+ * For example, a refactoring like inline method may choose to replace
+ * calls to the method but leave intact any comments immediately preceding
+ * the calls. On the other hand, a refactoring like extract method may choose
+ * to extract not only the nodes for the selected code but also any
+ * comments preceding or following them.
+ * </p>
+ * <p>
+ * Clients should subclass if they need to influence the
+ * the source range to be affected when replacing or deleting a particular node.
+ * An instance of the subclass should be registered with
+ * {@link ASTRewrite#setTargetSourceRangeComputer(TargetSourceRangeComputer)}.
+ * During a call to {@link ASTRewrite#rewriteAST(org.eclipse.jface.text.IDocument, java.util.Map)},
+ * the {@link #computeSourceRange(ASTNode)} method on this object will be
+ * used to compute the source range for a node being deleted or replaced.
+ * </p>
+ *
+ * @since 3.1
+ */
+public class TargetSourceRangeComputer {
+
+ /**
+ * Reified source range. Instances are &quot;value&quot; object
+ * (cannot be modified).
+ *
+ * @since 3.1
+ */
+ public static final class SourceRange {
+ /**
+ * 0-based character index, or <code>-1</code>
+ * if no source position information is known.
+ */
+ private int startPosition;
+
+ /**
+ * (possibly 0) length, or <code>0</code>
+ * if no source position information is known.
+ */
+ private int length;
+
+ /**
+ * Creates a new source range.
+ *
+ * @param startPosition the 0-based character index, or <code>-1</code>
+ * if no source position information is known
+ * @param length the (possibly 0) length, or <code>0</code>
+ * if no source position information is known
+ */
+ public SourceRange(int startPosition, int length) {
+ this.startPosition = startPosition;
+ this.length = length;
+ }
+
+ /**
+ * Returns the start position.
+ *
+ * @return the 0-based character index, or <code>-1</code>
+ * if no source position information is known
+ */
+ public int getStartPosition() {
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the source length.
+ *
+ * @return a (possibly 0) length, or <code>0</code>
+ * if no source position information is known
+ */
+ public int getLength() {
+ return this.length;
+ }
+ }
+
+ /**
+ * Creates a new target source range computer.
+ */
+ public TargetSourceRangeComputer() {
+ // do nothing
+ }
+
+ /**
+ * Returns the target source range of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ * <p>
+ * The returned source ranges must satisfy the following conditions:
+ * <dl>
+ * <li>no two source ranges in an AST may be overlapping</li>
+ * <li>a source range of a parent node must fully cover the source ranges of its children</li>
+ * </dl>
+ * </p>
+ * <p>
+ * The default implementation uses
+ * {@link CompilationUnit#getExtendedStartPosition(ASTNode)}
+ * and {@link CompilationUnit#getExtendedLength(ASTNode)}
+ * to compute the target source range. Clients may override or
+ * extend this method to expand or contract the source range of the
+ * given node. The resulting source range must cover at least the
+ * original source range of the node.
+ * </p>
+ *
+ * @param node the node with a known source range in the compilation unit
+ * being rewritten
+ * @return the exact source range in the compilation unit being rewritten
+ * that should be replaced (or deleted)
+ */
+ public SourceRange computeSourceRange(ASTNode node) {
+ ASTNode root= node.getRoot();
+ if (root instanceof CompilationUnit) {
+ CompilationUnit cu= (CompilationUnit) root;
+ return new SourceRange(cu.getExtendedStartPosition(node), cu.getExtendedLength(node));
+ }
+ return new SourceRange(node.getStartPosition(), node.getLength());
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/package.html b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/package.html
new file mode 100644
index 000000000..2f568acad
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/package.html
@@ -0,0 +1,18 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+The Java DOM/AST rewrite is the set of classes that are used to make changes to an existing DOM/AST tree.
+
+<h2>
+Package Specification</h2>
+
+<p>This package contains the Java DOM/AST classes used to make changes to an existing DOM/AST tree.
+The principal classes are {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite ASTRewrite} and
+{@link org.eclipse.jdt.core.dom.rewrite.ListRewrite ListRewrite}.</p>
+</body>
+</html>
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
new file mode 100644
index 000000000..587384abd
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
@@ -0,0 +1,2102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: NaiveASTFlattener.java 22567 2009-09-22 16:34:06Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.*;
+
+/**
+ * Internal AST visitor for serializing an AST in a quick and dirty fashion.
+ * For various reasons the resulting string is not necessarily legal
+ * Java code; and even if it is legal Java code, it is not necessarily the string
+ * that corresponds to the given AST. Although useless for most purposes, it's
+ * fine for generating debug print strings.
+ * <p>
+ * Example usage:
+ * <code>
+ * <pre>
+ * NaiveASTFlattener p = new NaiveASTFlattener();
+ * node.accept(p);
+ * String result = p.getResult();
+ * </pre>
+ * </code>
+ * Call the <code>reset</code> method to clear the previous result before reusing an
+ * existing instance.
+ * </p>
+ *
+ * @since 2.0
+ */
+public class NaiveASTFlattener extends ASTVisitor {
+ /**
+ * Internal synonym for {@link AST#JLS2}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private static final int JLS2 = AST.JLS2;
+
+ /**
+ * The string buffer into which the serialized representation of the AST is
+ * written.
+ */
+ protected StringBuffer buffer;
+
+ private int indent = 0;
+
+ /**
+ * Creates a new AST printer.
+ */
+ public NaiveASTFlattener() {
+ this.buffer = new StringBuffer();
+ }
+
+ /**
+ * Internal synonym for {@link ClassInstanceCreation#getName()}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private Name getName(ClassInstanceCreation node) {
+ return node.getName();
+ }
+
+ /**
+ * Returns the string accumulated in the visit.
+ *
+ * @return the serialized
+ */
+ public String getResult() {
+ return this.buffer.toString();
+ }
+
+ /**
+ * Internal synonym for {@link MethodDeclaration#getReturnType()}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private Type getReturnType(MethodDeclaration node) {
+ return node.getReturnType();
+ }
+
+ /**
+ * Internal synonym for {@link TypeDeclaration#getSuperclass()}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private Name getSuperclass(TypeDeclaration node) {
+ return node.getSuperclass();
+ }
+
+ /**
+ * Internal synonym for {@link TypeDeclarationStatement#getTypeDeclaration()}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private TypeDeclaration getTypeDeclaration(TypeDeclarationStatement node) {
+ return node.getTypeDeclaration();
+ }
+
+ void printIndent() {
+ for (int i = 0; i < this.indent; i++)
+ this.buffer.append(" "); //$NON-NLS-1$
+ }
+
+ /**
+ * Appends the text representation of the given modifier flags, followed by a single space.
+ * Used for JLS2 modifiers.
+ *
+ * @param modifiers the modifier flags
+ */
+ void printModifiers(int modifiers) {
+ if (Modifier.isPublic(modifiers)) {
+ this.buffer.append("public ");//$NON-NLS-1$
+ }
+ if (Modifier.isProtected(modifiers)) {
+ this.buffer.append("protected ");//$NON-NLS-1$
+ }
+ if (Modifier.isPrivate(modifiers)) {
+ this.buffer.append("private ");//$NON-NLS-1$
+ }
+ if (Modifier.isStatic(modifiers)) {
+ this.buffer.append("static ");//$NON-NLS-1$
+ }
+ if (Modifier.isAbstract(modifiers)) {
+ this.buffer.append("abstract ");//$NON-NLS-1$
+ }
+ if (Modifier.isFinal(modifiers)) {
+ this.buffer.append("final ");//$NON-NLS-1$
+ }
+ if (Modifier.isSynchronized(modifiers)) {
+ this.buffer.append("synchronized ");//$NON-NLS-1$
+ }
+ if (Modifier.isVolatile(modifiers)) {
+ this.buffer.append("volatile ");//$NON-NLS-1$
+ }
+ if (Modifier.isNative(modifiers)) {
+ this.buffer.append("native ");//$NON-NLS-1$
+ }
+ if (Modifier.isStrictfp(modifiers)) {
+ this.buffer.append("strictfp ");//$NON-NLS-1$
+ }
+ if (Modifier.isTransient(modifiers)) {
+ this.buffer.append("transient ");//$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Appends the text representation of the given modifier flags, followed by a single space.
+ * Used for 3.0 modifiers and annotations.
+ *
+ * @param ext the list of modifier and annotation nodes
+ * (element type: <code>IExtendedModifiers</code>)
+ */
+ void printModifiers(List ext) {
+ for (Iterator it = ext.iterator(); it.hasNext(); ) {
+ ASTNode p = (ASTNode) it.next();
+ p.accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Resets this printer so that it can be used again.
+ */
+ public void reset() {
+ this.buffer.setLength(0);
+ }
+
+ /**
+ * Internal synonym for {@link TypeDeclaration#superInterfaces()}. Use to alleviate
+ * deprecation warnings.
+ * @deprecated
+ * @since 3.4
+ */
+ private List superInterfaces(TypeDeclaration node) {
+ return node.superInterfaces();
+ }
+
+ /*
+ * @see ASTVisitor#visit(AnnotationTypeDeclaration)
+ * @since 3.1
+ */
+ public boolean visit(AnnotationTypeDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ printModifiers(node.modifiers());
+ this.buffer.append("@interface ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append(" {");//$NON-NLS-1$
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.accept(this);
+ }
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(AnnotationTypeMemberDeclaration)
+ * @since 3.1
+ */
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ printModifiers(node.modifiers());
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append("()");//$NON-NLS-1$
+ if (node.getDefault() != null) {
+ this.buffer.append(" default ");//$NON-NLS-1$
+ node.getDefault().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(AnonymousClassDeclaration)
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration b = (BodyDeclaration) it.next();
+ b.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayAccess)
+ */
+ public boolean visit(ArrayAccess node) {
+ node.getArray().accept(this);
+ this.buffer.append("[");//$NON-NLS-1$
+ node.getIndex().accept(this);
+ this.buffer.append("]");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayCreation)
+ */
+ public boolean visit(ArrayCreation node) {
+ this.buffer.append("new ");//$NON-NLS-1$
+ ArrayType at = node.getType();
+ int dims = at.getDimensions();
+ Type elementType = at.getElementType();
+ elementType.accept(this);
+ for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) {
+ this.buffer.append("[");//$NON-NLS-1$
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ this.buffer.append("]");//$NON-NLS-1$
+ dims--;
+ }
+ // add empty "[]" for each extra array dimension
+ for (int i= 0; i < dims; i++) {
+ this.buffer.append("[]");//$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayInitializer)
+ */
+ public boolean visit(ArrayInitializer node) {
+ this.buffer.append("{");//$NON-NLS-1$
+ for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("}");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayType)
+ */
+ public boolean visit(ArrayType node) {
+ node.getComponentType().accept(this);
+ this.buffer.append("[]");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(AssertStatement)
+ */
+ public boolean visit(AssertStatement node) {
+ printIndent();
+ this.buffer.append("assert ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ if (node.getMessage() != null) {
+ this.buffer.append(" : ");//$NON-NLS-1$
+ node.getMessage().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Assignment)
+ */
+ public boolean visit(Assignment node) {
+ node.getLeftHandSide().accept(this);
+ this.buffer.append(node.getOperator().toString());
+ node.getRightHandSide().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Block)
+ */
+ public boolean visit(Block node) {
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+ Statement s = (Statement) it.next();
+ s.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BlockComment)
+ * @since 3.0
+ */
+ public boolean visit(BlockComment node) {
+ printIndent();
+ this.buffer.append("/* */");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BooleanLiteral)
+ */
+ public boolean visit(BooleanLiteral node) {
+ if (node.booleanValue() == true) {
+ this.buffer.append("true");//$NON-NLS-1$
+ } else {
+ this.buffer.append("false");//$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BreakStatement)
+ */
+ public boolean visit(BreakStatement node) {
+ printIndent();
+ this.buffer.append("break");//$NON-NLS-1$
+ if (node.getLabel() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getLabel().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CastExpression)
+ */
+ public boolean visit(CastExpression node) {
+ this.buffer.append("(");//$NON-NLS-1$
+ node.getType().accept(this);
+ this.buffer.append(")");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CatchClause)
+ */
+ public boolean visit(CatchClause node) {
+ this.buffer.append("catch (");//$NON-NLS-1$
+ node.getException().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CharacterLiteral)
+ */
+ public boolean visit(CharacterLiteral node) {
+ this.buffer.append(node.getEscapedValue());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ClassInstanceCreation)
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("new ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() == JLS2) {
+ getName(node).accept(this);
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ node.getType().accept(this);
+ }
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ if (node.getAnonymousClassDeclaration() != null) {
+ node.getAnonymousClassDeclaration().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CompilationUnit)
+ */
+ public boolean visit(CompilationUnit node) {
+ if (node.getPackage() != null) {
+ node.getPackage().accept(this);
+ }
+ for (Iterator it = node.imports().iterator(); it.hasNext(); ) {
+ ImportDeclaration d = (ImportDeclaration) it.next();
+ d.accept(this);
+ }
+ for (Iterator it = node.types().iterator(); it.hasNext(); ) {
+ AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
+ d.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConditionalExpression)
+ */
+ public boolean visit(ConditionalExpression node) {
+ node.getExpression().accept(this);
+ this.buffer.append(" ? ");//$NON-NLS-1$
+ node.getThenExpression().accept(this);
+ this.buffer.append(" : ");//$NON-NLS-1$
+ node.getElseExpression().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConstructorInvocation)
+ */
+ public boolean visit(ConstructorInvocation node) {
+ printIndent();
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("this(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ContinueStatement)
+ */
+ public boolean visit(ContinueStatement node) {
+ printIndent();
+ this.buffer.append("continue");//$NON-NLS-1$
+ if (node.getLabel() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getLabel().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(DoStatement)
+ */
+ public boolean visit(DoStatement node) {
+ printIndent();
+ this.buffer.append("do ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ this.buffer.append(" while (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EmptyStatement)
+ */
+ public boolean visit(EmptyStatement node) {
+ printIndent();
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnhancedForStatement)
+ * @since 3.1
+ */
+ public boolean visit(EnhancedForStatement node) {
+ printIndent();
+ this.buffer.append("for (");//$NON-NLS-1$
+ node.getParameter().accept(this);
+ this.buffer.append(" : ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnumConstantDeclaration)
+ * @since 3.1
+ */
+ public boolean visit(EnumConstantDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ printModifiers(node.modifiers());
+ node.getName().accept(this);
+ if (!node.arguments().isEmpty()) {
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ }
+ if (node.getAnonymousClassDeclaration() != null) {
+ node.getAnonymousClassDeclaration().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnumDeclaration)
+ * @since 3.1
+ */
+ public boolean visit(EnumDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ printModifiers(node.modifiers());
+ this.buffer.append("enum ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ if (!node.superInterfaceTypes().isEmpty()) {
+ this.buffer.append("implements ");//$NON-NLS-1$
+ for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ this.buffer.append("{");//$NON-NLS-1$
+ for (Iterator it = node.enumConstants().iterator(); it.hasNext(); ) {
+ EnumConstantDeclaration d = (EnumConstantDeclaration) it.next();
+ d.accept(this);
+ // enum constant declarations do not include punctuation
+ if (it.hasNext()) {
+ // enum constant declarations are separated by commas
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ if (!node.bodyDeclarations().isEmpty()) {
+ this.buffer.append("; ");//$NON-NLS-1$
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.accept(this);
+ // other body declarations include trailing punctuation
+ }
+ }
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ExpressionStatement)
+ */
+ public boolean visit(ExpressionStatement node) {
+ printIndent();
+ node.getExpression().accept(this);
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldAccess)
+ */
+ public boolean visit(FieldAccess node) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldDeclaration)
+ */
+ public boolean visit(FieldDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ForStatement)
+ */
+ public boolean visit(ForStatement node) {
+ printIndent();
+ this.buffer.append("for (");//$NON-NLS-1$
+ for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) this.buffer.append(", ");//$NON-NLS-1$
+ }
+ this.buffer.append("; ");//$NON-NLS-1$
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ }
+ this.buffer.append("; ");//$NON-NLS-1$
+ for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) this.buffer.append(", ");//$NON-NLS-1$
+ }
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(IfStatement)
+ */
+ public boolean visit(IfStatement node) {
+ printIndent();
+ this.buffer.append("if (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getThenStatement().accept(this);
+ if (node.getElseStatement() != null) {
+ this.buffer.append(" else ");//$NON-NLS-1$
+ node.getElseStatement().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ImportDeclaration)
+ */
+ public boolean visit(ImportDeclaration node) {
+ printIndent();
+ this.buffer.append("import ");//$NON-NLS-1$
+//{ObjectTeams: base import
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isBase()) {
+ this.buffer.append("base ");//$NON-NLS-1$
+ }
+ }
+// SH}
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isStatic()) {
+ this.buffer.append("static ");//$NON-NLS-1$
+ }
+ }
+ node.getName().accept(this);
+ if (node.isOnDemand()) {
+ this.buffer.append(".*");//$NON-NLS-1$
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(InfixExpression)
+ */
+ public boolean visit(InfixExpression node) {
+ node.getLeftOperand().accept(this);
+ this.buffer.append(' '); // for cases like x= i - -1; or x= i++ + ++i;
+ this.buffer.append(node.getOperator().toString());
+ this.buffer.append(' ');
+ node.getRightOperand().accept(this);
+ final List extendedOperands = node.extendedOperands();
+ if (extendedOperands.size() != 0) {
+ this.buffer.append(' ');
+ for (Iterator it = extendedOperands.iterator(); it.hasNext(); ) {
+ this.buffer.append(node.getOperator().toString()).append(' ');
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Initializer)
+ */
+ public boolean visit(Initializer node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(InstanceofExpression)
+ */
+ public boolean visit(InstanceofExpression node) {
+ node.getLeftOperand().accept(this);
+ this.buffer.append(" instanceof ");//$NON-NLS-1$
+ node.getRightOperand().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Javadoc)
+ */
+ public boolean visit(Javadoc node) {
+ printIndent();
+ this.buffer.append("/** ");//$NON-NLS-1$
+ for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
+ ASTNode e = (ASTNode) it.next();
+ e.accept(this);
+ }
+ this.buffer.append("\n */\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LabeledStatement)
+ */
+ public boolean visit(LabeledStatement node) {
+ printIndent();
+ node.getLabel().accept(this);
+ this.buffer.append(": ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LineComment)
+ * @since 3.0
+ */
+ public boolean visit(LineComment node) {
+ this.buffer.append("//\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MarkerAnnotation)
+ * @since 3.1
+ */
+ public boolean visit(MarkerAnnotation node) {
+ this.buffer.append("@");//$NON-NLS-1$
+ node.getTypeName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MemberRef)
+ * @since 3.0
+ */
+ public boolean visit(MemberRef node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ }
+ this.buffer.append("#");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MemberValuePair)
+ * @since 3.1
+ */
+ public boolean visit(MemberValuePair node) {
+ node.getName().accept(this);
+ this.buffer.append("=");//$NON-NLS-1$
+ node.getValue().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodDeclaration)
+ */
+ public boolean visit(MethodDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ if (!node.typeParameters().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+ TypeParameter t = (TypeParameter) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ if (!node.isConstructor()) {
+ if (node.getAST().apiLevel() == JLS2) {
+ getReturnType(node).accept(this);
+ } else {
+ if (node.getReturnType2() != null) {
+ node.getReturnType2().accept(this);
+ } else {
+ // methods really ought to have a return type
+ this.buffer.append("void");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+ SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
+ v.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]"); //$NON-NLS-1$
+ }
+ if (!node.thrownExceptions().isEmpty()) {
+ this.buffer.append(" throws ");//$NON-NLS-1$
+ for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
+ Name n = (Name) it.next();
+ n.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (node.getBody() == null) {
+ this.buffer.append(";\n");//$NON-NLS-1$
+ } else {
+ node.getBody().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodInvocation)
+ */
+ public boolean visit(MethodInvocation node) {
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodRef)
+ * @since 3.0
+ */
+ public boolean visit(MethodRef node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ }
+ this.buffer.append("#");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+ MethodRefParameter e = (MethodRefParameter) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodRefParameter)
+ * @since 3.0
+ */
+ public boolean visit(MethodRefParameter node) {
+ node.getType().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isVarargs()) {
+ this.buffer.append("...");//$NON-NLS-1$
+ }
+ }
+ if (node.getName() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getName().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Modifier)
+ * @since 3.1
+ */
+ public boolean visit(Modifier node) {
+ this.buffer.append(node.getKeyword().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NormalAnnotation)
+ * @since 3.1
+ */
+ public boolean visit(NormalAnnotation node) {
+ this.buffer.append("@");//$NON-NLS-1$
+ node.getTypeName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.values().iterator(); it.hasNext(); ) {
+ MemberValuePair p = (MemberValuePair) it.next();
+ p.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NullLiteral)
+ */
+ public boolean visit(NullLiteral node) {
+ this.buffer.append("null");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NumberLiteral)
+ */
+ public boolean visit(NumberLiteral node) {
+ this.buffer.append(node.getToken());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PackageDeclaration)
+ */
+ public boolean visit(PackageDeclaration node) {
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ for (Iterator it = node.annotations().iterator(); it.hasNext(); ) {
+ Annotation p = (Annotation) it.next();
+ p.accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ printIndent();
+ this.buffer.append("package ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ParameterizedType)
+ * @since 3.1
+ */
+ public boolean visit(ParameterizedType node) {
+ node.getType().accept(this);
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ParenthesizedExpression)
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ this.buffer.append("(");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PostfixExpression)
+ */
+ public boolean visit(PostfixExpression node) {
+ node.getOperand().accept(this);
+ this.buffer.append(node.getOperator().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrefixExpression)
+ */
+ public boolean visit(PrefixExpression node) {
+ this.buffer.append(node.getOperator().toString());
+ node.getOperand().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrimitiveType)
+ */
+ public boolean visit(PrimitiveType node) {
+ this.buffer.append(node.getPrimitiveTypeCode().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedName)
+ */
+ public boolean visit(QualifiedName node) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedType)
+ * @since 3.1
+ */
+ public boolean visit(QualifiedType node) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ReturnStatement)
+ */
+ public boolean visit(ReturnStatement node) {
+ printIndent();
+ this.buffer.append("return");//$NON-NLS-1$
+ if (node.getExpression() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleName)
+ */
+ public boolean visit(SimpleName node) {
+ this.buffer.append(node.getIdentifier());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleType)
+ */
+ public boolean visit(SimpleType node) {
+ return true;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SingleMemberAnnotation)
+ * @since 3.1
+ */
+ public boolean visit(SingleMemberAnnotation node) {
+ this.buffer.append("@");//$NON-NLS-1$
+ node.getTypeName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ node.getValue().accept(this);
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SingleVariableDeclaration)
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ printIndent();
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isVarargs()) {
+ this.buffer.append("...");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getName().accept(this);
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]"); //$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ this.buffer.append("=");//$NON-NLS-1$
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(StringLiteral)
+ */
+ public boolean visit(StringLiteral node) {
+ this.buffer.append(node.getEscapedValue());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperConstructorInvocation)
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ printIndent();
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("super(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperFieldAccess)
+ */
+ public boolean visit(SuperFieldAccess node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("super.");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperMethodInvocation)
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("super.");//$NON-NLS-1$
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchCase)
+ */
+ public boolean visit(SwitchCase node) {
+ if (node.isDefault()) {
+ this.buffer.append("default :\n");//$NON-NLS-1$
+ } else {
+ this.buffer.append("case ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(":\n");//$NON-NLS-1$
+ }
+ this.indent++; //decremented in visit(SwitchStatement)
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchStatement)
+ */
+ public boolean visit(SwitchStatement node) {
+ this.buffer.append("switch (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+ Statement s = (Statement) it.next();
+ s.accept(this);
+ this.indent--; // incremented in visit(SwitchCase)
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SynchronizedStatement)
+ */
+ public boolean visit(SynchronizedStatement node) {
+ this.buffer.append("synchronized (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TagElement)
+ * @since 3.0
+ */
+ public boolean visit(TagElement node) {
+ if (node.isNested()) {
+ // nested tags are always enclosed in braces
+ this.buffer.append("{");//$NON-NLS-1$
+ } else {
+ // top-level tags always begin on a new line
+ this.buffer.append("\n * ");//$NON-NLS-1$
+ }
+ boolean previousRequiresWhiteSpace = false;
+ if (node.getTagName() != null) {
+ this.buffer.append(node.getTagName());
+ previousRequiresWhiteSpace = true;
+ }
+ boolean previousRequiresNewLine = false;
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ ASTNode e = (ASTNode) it.next();
+ // assume text elements include necessary leading and trailing whitespace
+ // but Name, MemberRef, MethodRef, and nested TagElement do not include white space
+ boolean currentIncludesWhiteSpace = (e instanceof TextElement);
+ if (previousRequiresNewLine && currentIncludesWhiteSpace) {
+ this.buffer.append("\n * ");//$NON-NLS-1$
+ }
+ previousRequiresNewLine = currentIncludesWhiteSpace;
+ // add space if required to separate
+ if (previousRequiresWhiteSpace && !currentIncludesWhiteSpace) {
+ this.buffer.append(" "); //$NON-NLS-1$
+ }
+ e.accept(this);
+ previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement);
+ }
+ if (node.isNested()) {
+ this.buffer.append("}");//$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TextElement)
+ * @since 3.0
+ */
+ public boolean visit(TextElement node) {
+ this.buffer.append(node.getText());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThisExpression)
+ */
+ public boolean visit(ThisExpression node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("this");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThrowStatement)
+ */
+ public boolean visit(ThrowStatement node) {
+ printIndent();
+ this.buffer.append("throw ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TryStatement)
+ */
+ public boolean visit(TryStatement node) {
+ printIndent();
+ this.buffer.append("try ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) {
+ CatchClause cc = (CatchClause) it.next();
+ cc.accept(this);
+ }
+ if (node.getFinally() != null) {
+ this.buffer.append(" finally ");//$NON-NLS-1$
+ node.getFinally().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclaration)
+ */
+ public boolean visit(TypeDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
+ node.getName().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeParameters().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+ TypeParameter t = (TypeParameter) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() == JLS2) {
+ if (getSuperclass(node) != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ getSuperclass(node).accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (!superInterfaces(node).isEmpty()) {
+ this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+ for (Iterator it = superInterfaces(node).iterator(); it.hasNext(); ) {
+ Name n = (Name) it.next();
+ n.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.getSuperclassType() != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ node.getSuperclassType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (!node.superInterfaceTypes().isEmpty()) {
+ this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+ for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclarationStatement)
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ if (node.getAST().apiLevel() == JLS2) {
+ getTypeDeclaration(node).accept(this);
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ node.getDeclaration().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeLiteral)
+ */
+ public boolean visit(TypeLiteral node) {
+ node.getType().accept(this);
+ this.buffer.append(".class");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeParameter)
+ * @since 3.1
+ */
+ public boolean visit(TypeParameter node) {
+ node.getName().accept(this);
+ if (!node.typeBounds().isEmpty()) {
+//{ObjectTeams: "base" bound?
+ if (node.hasBaseBound())
+ this.buffer.append(" base "); //$NON-NLS-1$
+ else
+// SH}
+ this.buffer.append(" extends ");//$NON-NLS-1$
+ for (Iterator it = node.typeBounds().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(" & ");//$NON-NLS-1$
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationExpression)
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationFragment)
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ node.getName().accept(this);
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]");//$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ this.buffer.append("=");//$NON-NLS-1$
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationStatement)
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ printIndent();
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(WhileStatement)
+ */
+ public boolean visit(WhileStatement node) {
+ printIndent();
+ this.buffer.append("while (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(WildcardType)
+ * @since 3.1
+ */
+ public boolean visit(WildcardType node) {
+ this.buffer.append("?");//$NON-NLS-1$
+ Type bound = node.getBound();
+ if (bound != null) {
+ if (node.isUpperBound()) {
+ this.buffer.append(" extends ");//$NON-NLS-1$
+ } else {
+ this.buffer.append(" super ");//$NON-NLS-1$
+ }
+ bound.accept(this);
+ }
+ return false;
+ }
+
+//{ObjectTeams: visit methods for OT-specific types
+ /*
+ * @see ASTVisitor#visit(MethodSpec)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(MethodSpec node)
+ {
+ if (node.getAST().apiLevel() == JLS2)
+ throw new UnsupportedOperationException("JLS2 no longer supported for OT/J");
+ if (node.hasSignature())
+ {
+ if (!node.typeParameters().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+ TypeParameter t = (TypeParameter) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("> ");//$NON-NLS-1$
+ }
+ node.getReturnType2().accept(this);
+ if (node.hasCovariantReturn())
+ buffer.append('+');
+ buffer.append(" ");
+ }
+ node.getName().accept(this);
+ if (node.hasSignature())
+ {
+ buffer.append("(");
+ for (Iterator iter = node.parameters().iterator(); iter.hasNext(); )
+ {
+ SingleVariableDeclaration var = (SingleVariableDeclaration) iter.next();
+ var.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(",");
+ }
+ }
+ buffer.append(")");
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldAccessSpec)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(FieldAccessSpec node)
+ {
+ if (node.hasSignature())
+ {
+ node.getFieldType().accept(this); // TODO(SH): must this be updated similar to returnType2?
+ buffer.append(" ");
+ }
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CallinMappingDeclaration)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(CallinMappingDeclaration node)
+ {
+ if (node.getJavadoc() != null)
+ {
+ node.getJavadoc().accept(this);
+ }
+
+ if ((node.getRoleMappingElement() != null)
+ && (node.getBaseMappingElements() != null))
+ {
+ node.getRoleMappingElement().accept(this);
+ buffer.append(" ");
+ buffer.append(CallinMappingDeclaration.CALLIN);
+ buffer.append(" ");
+ if (node.getCallinModifier() != 0)
+ {
+ node.callinModifier().accept(this);
+ buffer.append(" ");
+ }
+
+ for (Iterator iter = node.getBaseMappingElements().iterator(); iter.hasNext();)
+ {
+ MethodSpec rightMethodSpec = (MethodSpec) iter.next();
+ rightMethodSpec.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(", ");
+ }
+ }
+ }
+ else
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+
+ GuardPredicateDeclaration guard = node.getGuardPredicate();
+ if (guard != null) {
+ if (guard.isBase())
+ buffer.append(" base when(");
+ else
+ buffer.append(" when(");
+ guard.getExpression().accept(this);
+ buffer.append(")");
+ }
+
+ if (!node.getParameterMappings().isEmpty())
+ {
+ buffer.append(" with\n{\n");
+ for (Iterator iter = node.getParameterMappings().iterator(); iter.hasNext(); )
+ {
+ buffer.append("\t");
+ ParameterMapping parameterMapping = (ParameterMapping) iter.next();
+ parameterMapping.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(",\n");
+ }
+ }
+ buffer.append("\n}");
+ }
+ else
+ {
+ buffer.append(";");
+ }
+
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CalloutMappingDeclaration)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(CalloutMappingDeclaration node)
+ {
+ if (node.getJavadoc() != null)
+ {
+ node.getJavadoc().accept(this);
+ }
+ printModifiers(node.modifiers());
+ if ((node.getRoleMappingElement() != null)
+ && (node.getBaseMappingElement() != null))
+ {
+ node.getRoleMappingElement().accept(this);
+ buffer.append(" ");
+ if (node.isCalloutOverride())
+ {
+ buffer.append(CalloutMappingDeclaration.CALLOUT_OVERRIDE);
+ }
+ else
+ {
+ buffer.append(CalloutMappingDeclaration.CALLOUT);
+ }
+ buffer.append(" ");
+ switch (node.bindingOperator().getBindingModifier()) {
+ case Modifier.OT_SET_CALLOUT : buffer.append("set "); break;
+ case Modifier.OT_GET_CALLOUT : buffer.append("get "); break;
+ }
+ node.getBaseMappingElement().accept(this);
+ }
+ else
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+
+ if (!node.getParameterMappings().isEmpty())
+ {
+ buffer.append(" with\n{\n");
+ for (Iterator iter = node.getParameterMappings().iterator(); iter.hasNext(); )
+ {
+ buffer.append("\t");
+ ParameterMapping parameterMapping = (ParameterMapping) iter.next();
+ parameterMapping.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(",\n");
+ }
+ }
+ buffer.append("\n}");
+ }
+ else
+ {
+ buffer.append(";");
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LiftingType)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(LiftingType node)
+ {
+ node.getBaseType().accept(this);
+ buffer.append(" as ");
+ node.getRoleType().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeAnchor)
+ */
+ public boolean visit(TypeAnchor node)
+ {
+ buffer.append('@');
+ node.getPath().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(WithinStatement)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(WithinStatement node)
+ {
+ buffer.append("within(");
+ node.getTeamExpression().accept(this);
+ buffer.append(") ");
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TSuperMessageSend)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(TSuperMessageSend node)
+ {
+ ASTNode qualifier = node.getQualifier();
+ if (qualifier != null) {
+ qualifier.accept(this);
+ buffer.append('.');
+ }
+
+ buffer.append("tsuper.");
+ node.getName().accept(this);
+ buffer.append("(");
+ for (Iterator iter = node.getArguments().iterator(); iter.hasNext(); )
+ {
+ Expression var = (Expression)iter.next();
+ var.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TSuperConstructorInvocation)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(TSuperConstructorInvocation node)
+ {
+ buffer.append("tsuper");
+ buffer.append("(");
+ for (Iterator iter = node.getArguments().iterator(); iter.hasNext(); )
+ {
+ Expression var = (Expression)iter.next();
+ var.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+ return false;
+ }
+
+
+
+ /*
+ * @see ASTVisitor#visit(BaseCallMessageSend)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(BaseCallMessageSend node)
+ {
+ buffer.append("base.");
+ buffer.append(node.getName());
+ buffer.append("(");
+ for (Iterator iter = node.getArguments().iterator(); iter.hasNext(); )
+ {
+ Expression var = (Expression)iter.next();
+ var.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BaseConstructorMessageSend)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(BaseConstructorInvocation node)
+ {
+ buffer.append("base(");
+ for (Iterator iter = node.getArguments().iterator(); iter.hasNext(); )
+ {
+ Expression var = (Expression)iter.next();
+ var.accept(this);
+ if (iter.hasNext())
+ {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(");");
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ParameterMapping)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(ParameterMapping node)
+ {
+ if (node.getExpression() != null)
+ {
+ if (node.getDirection().equals("->"))
+ {
+ node.getExpression().accept(this);
+ buffer.append(node.getDirection());
+ buffer.append(node.getIdentifier());
+ }
+ if (node.getDirection().equals("<-"))
+ {
+ buffer.append(node.getIdentifier());
+ buffer.append(node.getDirection());
+ node.getExpression().accept(this);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(RoleTypeDeclaration)
+ */
+ public boolean visit(RoleTypeDeclaration node) {
+ // COPY&PASTE from visit(TypeDeclaration) plus "playedBy Base"
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
+ node.getName().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeParameters().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+ TypeParameter t = (TypeParameter) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() == JLS2) {
+ if (this.getSuperclass(node) != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ this.getSuperclass(node).accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (!this.superInterfaces(node).isEmpty()) {
+ this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+ for (Iterator it = this.superInterfaces(node).iterator(); it.hasNext(); ) {
+ Name n = (Name) it.next();
+ n.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.getSuperclassType() != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ node.getSuperclassType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (!node.superInterfaceTypes().isEmpty()) {
+ this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+ for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (node.getBaseClassType() != null) {
+ this.buffer.append("playedBy ");//$NON-NLS-1$
+ node.getBaseClassType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+//gbr}
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
new file mode 100644
index 000000000..de5259b82
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -0,0 +1,4363 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTRewriteAnalyzer.java 23264 2010-01-15 23:44:16Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
+import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
+import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer.SourceRange;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.core.formatter.IndentManipulation;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.BlockContext;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.NodeMarker;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.Prefix;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.CopyPlaceholderData;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.StringPlaceholderData;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.text.edits.CopySourceEdit;
+import org.eclipse.text.edits.CopyTargetEdit;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MoveTargetEdit;
+import org.eclipse.text.edits.RangeMarker;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+
+
+/**
+ * Infrastructure to support code modifications. Existing code must stay untouched, new code
+ * added with correct formatting, moved code left with the user's formatting / comments.
+ * Idea:
+ * - Get the AST for existing code
+ * - Describe changes
+ * - This visitor analyzes the changes or annotations and generates text edits
+ * (text manipulation API) that describe the required code changes.
+ */
+public final class ASTRewriteAnalyzer extends ASTVisitor {
+
+ /**
+ * Internal synonym for deprecated constant AST.JLS2
+ * to alleviate deprecated warnings.
+ * @deprecated
+ */
+ /*package*/ static final int JLS2_INTERNAL = AST.JLS2;
+
+ TextEdit currentEdit;
+ final RewriteEventStore eventStore; // used from inner classes
+
+ private TokenScanner tokenScanner; // shared scanner
+
+ private final Map sourceCopyInfoToEdit;
+ private final Stack sourceCopyEndNodes;
+
+ private final char[] content;
+ private final LineInformation lineInfo;
+ private final ASTRewriteFormatter formatter;
+ private final NodeInfoStore nodeInfos;
+ private final TargetSourceRangeComputer extendedSourceRangeComputer;
+ private final LineCommentEndOffsets lineCommentEndOffsets;
+
+ private int beforeRequiredSpaceIndex = -1;
+
+ Map options;
+
+ private RecoveryScannerData recoveryScannerData;
+
+ /**
+ * Constructor for ASTRewriteAnalyzer.
+ * <p>The given options cannot be null.</p>
+ *
+ * @param content the content of the compilation unit to rewrite.
+ * @param lineInfo line information for the content of the compilation unit to rewrite.
+ * @param rootEdit the edit to add all generated edits to
+ * @param eventStore the event store containing the description of changes
+ * @param nodeInfos annotations to nodes, such as if a node is a string placeholder or a copy target
+ * @param comments list of comments of the compilation unit to rewrite (elements of type <code>Comment</code>) or <code>null</code>.
+ * @param options the current jdt.core options (formatting/compliance)
+ * @param extendedSourceRangeComputer the source range computer to use
+ * @param recoveryScannerData internal data used by {@link RecoveryScanner}
+ */
+ public ASTRewriteAnalyzer(
+ char[] content,
+ LineInformation lineInfo,
+ String lineDelim,
+ TextEdit rootEdit,
+ RewriteEventStore eventStore,
+ NodeInfoStore nodeInfos,
+ List comments,
+ Map options,
+ TargetSourceRangeComputer extendedSourceRangeComputer,
+ RecoveryScannerData recoveryScannerData) {
+ this.eventStore= eventStore;
+ this.content= content;
+ this.lineInfo= lineInfo;
+ this.nodeInfos= nodeInfos;
+ this.tokenScanner= null;
+ this.currentEdit= rootEdit;
+ this.sourceCopyInfoToEdit= new IdentityHashMap();
+ this.sourceCopyEndNodes= new Stack();
+
+ this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, lineDelim);
+
+ this.extendedSourceRangeComputer = extendedSourceRangeComputer;
+ this.lineCommentEndOffsets= new LineCommentEndOffsets(comments);
+
+ this.options = options;
+
+ this.recoveryScannerData = recoveryScannerData;
+ }
+
+ final TokenScanner getScanner() {
+ if (this.tokenScanner == null) {
+ CompilerOptions compilerOptions = new CompilerOptions(this.options);
+ Scanner scanner;
+ if (this.recoveryScannerData == null) {
+ scanner =
+ new Scanner(
+ true,/*tokenizeComments*/
+ false,/*tokenizeWhiteSpace*/
+ false,/*checkNonExternalizedStringLiterals*/
+ compilerOptions.sourceLevel,
+ compilerOptions.complianceLevel,
+ null/*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ } else {
+ scanner =
+ new RecoveryScanner(
+ false,/*tokenizeWhiteSpace*/
+ false,/*checkNonExternalizedStringLiterals*/
+ compilerOptions.sourceLevel,
+ compilerOptions.complianceLevel,
+ null/*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/,
+ this.recoveryScannerData);
+ }
+ scanner.setSource(this.content);
+ this.tokenScanner= new TokenScanner(scanner);
+ }
+ return this.tokenScanner;
+ }
+
+ final char[] getContent() {
+ return this.content;
+ }
+
+ final LineInformation getLineInformation() {
+ return this.lineInfo;
+ }
+
+ /**
+ * Returns the extended source range for a node.
+ *
+ * @return an extended source range (never null)
+ * @since 3.1
+ */
+ final SourceRange getExtendedRange(ASTNode node) {
+ if (this.eventStore.isRangeCopyPlaceholder(node)) {
+ return new SourceRange(node.getStartPosition(), node.getLength());
+ }
+ return this.extendedSourceRangeComputer.computeSourceRange(node);
+ }
+
+ final int getExtendedOffset(ASTNode node) {
+ return getExtendedRange(node).getStartPosition();
+ }
+
+ final int getExtendedEnd(ASTNode node) {
+ TargetSourceRangeComputer.SourceRange range= getExtendedRange(node);
+ return range.getStartPosition() + range.getLength();
+ }
+
+ final TextEdit getCopySourceEdit(CopySourceInfo info) {
+ TextEdit edit= (TextEdit) this.sourceCopyInfoToEdit.get(info);
+ if (edit == null) {
+ SourceRange range= getExtendedRange(info.getNode());
+ int start= range.getStartPosition();
+ int end= start + range.getLength();
+ if (info.isMove) {
+ MoveSourceEdit moveSourceEdit= new MoveSourceEdit(start, end - start);
+ moveSourceEdit.setTargetEdit(new MoveTargetEdit(0));
+ edit= moveSourceEdit;
+ } else {
+ CopySourceEdit copySourceEdit= new CopySourceEdit(start, end - start);
+ copySourceEdit.setTargetEdit(new CopyTargetEdit(0));
+ edit= copySourceEdit;
+ }
+ this.sourceCopyInfoToEdit.put(info, edit);
+ }
+ return edit;
+ }
+
+ private final int getChangeKind(ASTNode node, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(node, property);
+ if (event != null) {
+ return event.getChangeKind();
+ }
+ return RewriteEvent.UNCHANGED;
+ }
+
+ private final boolean hasChildrenChanges(ASTNode node) {
+ return this.eventStore.hasChangedProperties(node);
+ }
+
+ private final boolean isChanged(ASTNode node, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(node, property);
+ if (event != null) {
+ return event.getChangeKind() != RewriteEvent.UNCHANGED;
+ }
+ return false;
+ }
+
+ private final boolean isCollapsed(ASTNode node) {
+ return this.nodeInfos.isCollapsed(node);
+ }
+
+ final boolean isInsertBoundToPrevious(ASTNode node) {
+ return this.eventStore.isInsertBoundToPrevious(node);
+ }
+
+ private final TextEditGroup getEditGroup(ASTNode parent, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ return getEditGroup(event);
+ }
+ return null;
+ }
+
+ final RewriteEvent getEvent(ASTNode parent, StructuralPropertyDescriptor property) {
+ return this.eventStore.getEvent(parent, property);
+ }
+
+ final TextEditGroup getEditGroup(RewriteEvent change) {
+ return this.eventStore.getEventEditGroup(change);
+ }
+
+ private final Object getOriginalValue(ASTNode parent, StructuralPropertyDescriptor property) {
+ return this.eventStore.getOriginalValue(parent, property);
+ }
+
+ private final Object getNewValue(ASTNode parent, StructuralPropertyDescriptor property) {
+ return this.eventStore.getNewValue(parent, property);
+ }
+
+ final void addEdit(TextEdit edit) {
+ this.currentEdit.addChild(edit);
+ }
+
+ final String getLineDelimiter() {
+ return this.formatter.getLineDelimiter();
+ }
+
+ final String createIndentString(int indent) {
+ return this.formatter.createIndentString(indent);
+ }
+
+ final private String getIndentOfLine(int pos) {
+ int line= getLineInformation().getLineOfOffset(pos);
+ if (line >= 0) {
+ char[] cont= getContent();
+ int lineStart= getLineInformation().getLineOffset(line);
+ int i= lineStart;
+ while (i < cont.length && IndentManipulation.isIndentChar(this.content[i])) {
+ i++;
+ }
+ return new String(cont, lineStart, i - lineStart);
+ }
+ return Util.EMPTY_STRING;
+ }
+
+
+ final String getIndentAtOffset(int pos) {
+ return this.formatter.getIndentString(getIndentOfLine(pos));
+ }
+
+ final void doTextInsert(int offset, String insertString, TextEditGroup editGroup) {
+ if (insertString.length() > 0) {
+ // bug fix for 95839: problem with inserting at the end of a line comment
+ if (this.lineCommentEndOffsets.isEndOfLineComment(offset, this.content)) {
+ if (!insertString.startsWith(getLineDelimiter())) {
+ TextEdit edit= new InsertEdit(offset, getLineDelimiter()); // add a line delimiter
+ addEdit(edit);
+ if (editGroup != null) {
+ addEditGroup(editGroup, edit);
+ }
+ }
+ this.lineCommentEndOffsets.remove(offset); // only one line delimiter per line comment required
+ }
+ TextEdit edit= new InsertEdit(offset, insertString);
+ addEdit(edit);
+ if (editGroup != null) {
+ addEditGroup(editGroup, edit);
+ }
+ }
+ }
+
+ final void addEditGroup(TextEditGroup editGroup, TextEdit edit) {
+ editGroup.addTextEdit(edit);
+ }
+
+ final TextEdit doTextRemove(int offset, int len, TextEditGroup editGroup) {
+ if (len == 0) {
+ return null;
+ }
+ TextEdit edit= new DeleteEdit(offset, len);
+ addEdit(edit);
+ if (editGroup != null) {
+ addEditGroup(editGroup, edit);
+ }
+ return edit;
+ }
+
+ final void doTextRemoveAndVisit(int offset, int len, ASTNode node, TextEditGroup editGroup) {
+ TextEdit edit= doTextRemove(offset, len, editGroup);
+ if (edit != null) {
+ this.currentEdit= edit;
+ voidVisit(node);
+ this.currentEdit= edit.getParent();
+ } else {
+ voidVisit(node);
+ }
+ }
+
+ final int doVisit(ASTNode node) {
+ node.accept(this);
+ return getExtendedEnd(node);
+ }
+
+ private final int doVisit(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
+ Object node= getOriginalValue(parent, property);
+ if (property.isChildProperty() && node != null) {
+ return doVisit((ASTNode) node);
+ } else if (property.isChildListProperty()) {
+ return doVisitList((List) node, offset);
+ }
+ return offset;
+ }
+
+ private int doVisitList(List list, int offset) {
+ int endPos= offset;
+ for (Iterator iter= list.iterator(); iter.hasNext();) {
+ ASTNode curr= ((ASTNode) iter.next());
+ endPos= doVisit(curr);
+ }
+ return endPos;
+ }
+
+ final void voidVisit(ASTNode node) {
+ node.accept(this);
+ }
+
+ private final void voidVisit(ASTNode parent, StructuralPropertyDescriptor property) {
+ Object node= getOriginalValue(parent, property);
+ if (property.isChildProperty() && node != null) {
+ voidVisit((ASTNode) node);
+ } else if (property.isChildListProperty()) {
+ voidVisitList((List) node);
+ }
+ }
+
+ private void voidVisitList(List list) {
+ for (Iterator iter= list.iterator(); iter.hasNext();) {
+ doVisit(((ASTNode) iter.next()));
+ }
+ }
+
+ private final boolean doVisitUnchangedChildren(ASTNode parent) {
+ List properties= parent.structuralPropertiesForType();
+ for (int i= 0; i < properties.size(); i++) {
+ voidVisit(parent, (StructuralPropertyDescriptor) properties.get(i));
+ }
+ return false;
+ }
+
+
+ private final void doTextReplace(int offset, int len, String insertString, TextEditGroup editGroup) {
+ if (len > 0 || insertString.length() > 0) {
+ TextEdit edit= new ReplaceEdit(offset, len, insertString);
+ addEdit(edit);
+ if (editGroup != null) {
+ addEditGroup(editGroup, edit);
+ }
+ }
+ }
+
+ private final TextEdit doTextCopy(TextEdit sourceEdit, int destOffset, int sourceIndentLevel, String destIndentString, TextEditGroup editGroup) {
+ TextEdit targetEdit;
+ SourceModifier modifier= new SourceModifier(sourceIndentLevel, destIndentString, this.formatter.getTabWidth(), this.formatter.getIndentWidth());
+
+ if (sourceEdit instanceof MoveSourceEdit) {
+ MoveSourceEdit moveEdit= (MoveSourceEdit) sourceEdit;
+ moveEdit.setSourceModifier(modifier);
+
+ targetEdit= new MoveTargetEdit(destOffset, moveEdit);
+ addEdit(targetEdit);
+ } else {
+ CopySourceEdit copyEdit= (CopySourceEdit) sourceEdit;
+ copyEdit.setSourceModifier(modifier);
+
+ targetEdit= new CopyTargetEdit(destOffset, copyEdit);
+ addEdit(targetEdit);
+ }
+
+ if (editGroup != null) {
+ addEditGroup(editGroup, sourceEdit);
+ addEditGroup(editGroup, targetEdit);
+ }
+ return targetEdit;
+
+ }
+
+ private void changeNotSupported(ASTNode node) {
+ Assert.isTrue(false, "Change not supported in " + node.getClass().getName()); //$NON-NLS-1$
+ }
+
+
+ class ListRewriter {
+ protected String contantSeparator;
+ protected int startPos;
+
+ protected RewriteEvent[] list;
+
+ protected final ASTNode getOriginalNode(int index) {
+ return (ASTNode) this.list[index].getOriginalValue();
+ }
+
+ protected final ASTNode getNewNode(int index) {
+ return (ASTNode) this.list[index].getNewValue();
+ }
+
+ protected String getSeparatorString(int nodeIndex) {
+ return this.contantSeparator;
+ }
+
+ protected int getInitialIndent() {
+ return getIndent(this.startPos);
+ }
+
+ protected int getNodeIndent(int nodeIndex) {
+ ASTNode node= getOriginalNode(nodeIndex);
+ if (node == null) {
+ for (int i= nodeIndex - 1; i>= 0; i--) {
+ ASTNode curr= getOriginalNode(i);
+ if (curr != null) {
+ return getIndent(curr.getStartPosition());
+ }
+ }
+ return getInitialIndent();
+ }
+ return getIndent(node.getStartPosition());
+ }
+
+ protected int getStartOfNextNode(int nextIndex, int defaultPos) {
+ for (int i= nextIndex; i < this.list.length; i++) {
+ RewriteEvent elem= this.list[i];
+ if (elem.getChangeKind() != RewriteEvent.INSERTED) {
+ ASTNode node= (ASTNode) elem.getOriginalValue();
+ return getExtendedOffset(node);
+ }
+ }
+ return defaultPos;
+ }
+
+ protected int getEndOfNode(ASTNode node) {
+ return getExtendedEnd(node);
+ }
+
+ public final int rewriteList(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword, String separator) {
+ this.contantSeparator= separator;
+ return rewriteList(parent, property, offset, keyword);
+ }
+
+ private boolean insertAfterSeparator(ASTNode node) {
+ return !isInsertBoundToPrevious(node);
+ }
+
+ protected boolean mustRemoveSeparator(int originalOffset, int nodeIndex) {
+ return true;
+ }
+
+ public final int rewriteList(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword) {
+ this.startPos= offset;
+ this.list= getEvent(parent, property).getChildren();
+
+ int total= this.list.length;
+ if (total == 0) {
+ return this.startPos;
+ }
+
+ int currPos= -1;
+
+ int lastNonInsert= -1;
+ int lastNonDelete= -1;
+
+ for (int i= 0; i < total; i++) {
+ int currMark= this.list[i].getChangeKind();
+
+ if (currMark != RewriteEvent.INSERTED) {
+ lastNonInsert= i;
+ if (currPos == -1) {
+ ASTNode elem= (ASTNode) this.list[i].getOriginalValue();
+ currPos= getExtendedOffset(elem);
+ }
+ }
+ if (currMark != RewriteEvent.REMOVED) {
+ lastNonDelete= i;
+ }
+ }
+
+ if (currPos == -1) { // only inserts
+ if (keyword.length() > 0) { // creating a new list -> insert keyword first (e.g. " throws ")
+ TextEditGroup editGroup= getEditGroup(this.list[0]); // first node is insert
+ doTextInsert(offset, keyword, editGroup);
+ }
+ currPos= offset;
+ }
+ if (lastNonDelete == -1) { // all removed, set back to start so the keyword is removed as well
+ currPos= offset;
+ }
+
+ int prevEnd= currPos;
+ int prevMark= RewriteEvent.UNCHANGED;
+
+ final int NONE= 0, NEW= 1, EXISTING= 2;
+ int separatorState= NEW;
+
+ for (int i= 0; i < total; i++) {
+ RewriteEvent currEvent= this.list[i];
+ int currMark= currEvent.getChangeKind();
+ int nextIndex= i + 1;
+
+ if (currMark == RewriteEvent.INSERTED) {
+ TextEditGroup editGroup= getEditGroup(currEvent);
+ ASTNode node= (ASTNode) currEvent.getNewValue();
+
+ if (separatorState == NONE) { // element after last existing element (but not first)
+ doTextInsert(currPos, getSeparatorString(i - 1), editGroup); // insert separator
+ separatorState= NEW;
+ }
+ if (separatorState == NEW || insertAfterSeparator(node)) {
+ if (separatorState == EXISTING) {
+ updateIndent(prevMark, currPos, i, editGroup);
+ }
+
+ doTextInsert(currPos, node, getNodeIndent(i), true, editGroup); // insert node
+
+ separatorState= NEW;
+ if (i != lastNonDelete) {
+ if (this.list[nextIndex].getChangeKind() != RewriteEvent.INSERTED) {
+ doTextInsert(currPos, getSeparatorString(i), editGroup); // insert separator
+ } else {
+ separatorState= NONE;
+ }
+ }
+ } else { // EXISTING && insert before separator
+ doTextInsert(prevEnd, getSeparatorString(i - 1), editGroup);
+ doTextInsert(prevEnd, node, getNodeIndent(i), true, editGroup);
+ }
+ } else if (currMark == RewriteEvent.REMOVED) {
+ ASTNode node= (ASTNode) currEvent.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(currEvent);
+ int currEnd= getEndOfNode(node);
+ if (i > lastNonDelete && separatorState == EXISTING) {
+ // is last, remove previous separator: split delete to allow range copies
+ doTextRemove(prevEnd, currPos - prevEnd, editGroup); // remove separator
+ doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); // remove node
+ currPos= currEnd;
+ prevEnd= currEnd;
+ } else {
+ if (i < lastNonDelete) {
+ updateIndent(prevMark, currPos, i, editGroup);
+ }
+
+ // remove element and next separator
+ int end= getStartOfNextNode(nextIndex, currEnd); // start of next
+ doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); // remove node
+ if (mustRemoveSeparator(currPos, i)) {
+ doTextRemove(currEnd, end - currEnd, editGroup); // remove separator
+ }
+ currPos= end;
+ prevEnd= currEnd;
+ separatorState= NEW;
+ }
+ } else { // replaced or unchanged
+ if (currMark == RewriteEvent.REPLACED) {
+ ASTNode node= (ASTNode) currEvent.getOriginalValue();
+ int currEnd= getEndOfNode(node);
+
+ TextEditGroup editGroup= getEditGroup(currEvent);
+ ASTNode changed= (ASTNode) currEvent.getNewValue();
+
+ updateIndent(prevMark, currPos, i, editGroup);
+
+ doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup);
+ doTextInsert(currPos, changed, getNodeIndent(i), true, editGroup);
+
+ prevEnd= currEnd;
+ } else { // is unchanged
+ ASTNode node= (ASTNode) currEvent.getOriginalValue();
+ voidVisit(node);
+ }
+ if (i == lastNonInsert) { // last node or next nodes are all inserts
+ separatorState= NONE;
+ if (currMark == RewriteEvent.UNCHANGED) {
+ ASTNode node= (ASTNode) currEvent.getOriginalValue();
+ prevEnd= getEndOfNode(node);
+ }
+ currPos= prevEnd;
+ } else if (this.list[nextIndex].getChangeKind() != RewriteEvent.UNCHANGED) {
+ // no updates needed while nodes are unchanged
+ if (currMark == RewriteEvent.UNCHANGED) {
+ ASTNode node= (ASTNode) currEvent.getOriginalValue();
+ prevEnd= getEndOfNode(node);
+ }
+ currPos= getStartOfNextNode(nextIndex, prevEnd); // start of next
+ separatorState= EXISTING;
+ }
+ }
+
+ prevMark = currMark;
+ }
+ return currPos;
+ }
+
+ protected void updateIndent(int prevMark, int originalOffset, int nodeIndex, TextEditGroup editGroup) {
+ // Do nothing.
+ }
+ }
+
+ private int rewriteRequiredNode(ASTNode parent, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null && event.getChangeKind() == RewriteEvent.REPLACED) {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ SourceRange range= getExtendedRange(node);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+//{ObjectTeams: missing modifier?
+ boolean isMissingModifier = node instanceof Modifier
+ && ((Modifier)node).getKeyword() == ModifierKeyword.MISSING_KEYWORD;
+ if (isMissingModifier)
+ doTextInsert(offset, " ", editGroup); // separate insertion from preceding text. //$NON-NLS-1$
+// SH}
+ doTextRemoveAndVisit(offset, length, node, editGroup);
+ doTextInsert(offset, (ASTNode) event.getNewValue(), getIndent(offset), true, editGroup);
+ return offset + length;
+ }
+ return doVisit(parent, property, 0);
+ }
+
+ private int rewriteNode(ASTNode parent, StructuralPropertyDescriptor property, int offset, Prefix prefix) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ switch (event.getChangeKind()) {
+ case RewriteEvent.INSERTED: {
+ ASTNode node= (ASTNode) event.getNewValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ int indent= getIndent(offset);
+ doTextInsert(offset, prefix.getPrefix(indent), editGroup);
+ doTextInsert(offset, node, indent, true, editGroup);
+ return offset;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(event);
+
+ // if there is a prefix, remove the prefix as well
+ int nodeEnd;
+ int len;
+ if (offset == 0) {
+ SourceRange range= getExtendedRange(node);
+ offset= range.getStartPosition();
+ len= range.getLength();
+ nodeEnd= offset+len;
+ } else {
+ nodeEnd= getExtendedEnd(node);
+ len= nodeEnd-offset;
+ }
+ doTextRemoveAndVisit(offset, len, node, editGroup);
+ return nodeEnd;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ SourceRange range= getExtendedRange(node);
+ int nodeOffset= range.getStartPosition();
+ int nodeLen= range.getLength();
+ doTextRemoveAndVisit(nodeOffset, nodeLen, node, editGroup);
+ doTextInsert(nodeOffset, (ASTNode) event.getNewValue(), getIndent(offset), true, editGroup);
+ return nodeOffset + nodeLen;
+ }
+ }
+ }
+ return doVisit(parent, property, offset);
+ }
+
+ private int rewriteJavadoc(ASTNode node, StructuralPropertyDescriptor property) {
+ int pos= rewriteNode(node, property, node.getStartPosition(), ASTRewriteFormatter.NONE);
+ int changeKind= getChangeKind(node, property);
+ if (changeKind == RewriteEvent.INSERTED) {
+ String indent= getLineDelimiter() + getIndentAtOffset(pos);
+ doTextInsert(pos, indent, getEditGroup(node, property));
+ } else if (changeKind == RewriteEvent.REMOVED) {
+ try {
+ getScanner().readNext(pos, false);
+ doTextRemove(pos, getScanner().getCurrentStartOffset() - pos, getEditGroup(node, property));
+ pos= getScanner().getCurrentStartOffset();
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ return pos;
+ }
+
+
+ /*
+ * endpos can be -1 -> use the end pos of the body
+ */
+ private int rewriteBodyNode(ASTNode parent, StructuralPropertyDescriptor property, int offset, int endPos, int indent, BlockContext context) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ switch (event.getChangeKind()) {
+ case RewriteEvent.INSERTED: {
+ ASTNode node= (ASTNode) event.getNewValue();
+ TextEditGroup editGroup= getEditGroup(event);
+
+ String[] strings= context.getPrefixAndSuffix(indent, node, this.eventStore);
+
+ doTextInsert(offset, strings[0], editGroup);
+ doTextInsert(offset, node, indent, true, editGroup);
+ doTextInsert(offset, strings[1], editGroup);
+ return offset;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ if (endPos == -1) {
+ endPos= getExtendedEnd(node);
+ }
+
+ TextEditGroup editGroup= getEditGroup(event);
+ // if there is a prefix, remove the prefix as well
+ int len= endPos - offset;
+ doTextRemoveAndVisit(offset, len, node, editGroup);
+ return endPos;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ if (endPos == -1) {
+ endPos= getExtendedEnd(node);
+ }
+ TextEditGroup editGroup= getEditGroup(event);
+ int nodeLen= endPos - offset;
+
+ ASTNode replacingNode= (ASTNode) event.getNewValue();
+ String[] strings= context.getPrefixAndSuffix(indent, replacingNode, this.eventStore);
+ doTextRemoveAndVisit(offset, nodeLen, node, editGroup);
+
+ String prefix= strings[0];
+ doTextInsert(offset, prefix, editGroup);
+ String lineInPrefix= getCurrentLine(prefix, prefix.length());
+ if (prefix.length() != lineInPrefix.length()) {
+ // prefix contains a new line: update the indent to the one used in the prefix
+ indent= this.formatter.computeIndentUnits(lineInPrefix);
+ }
+ doTextInsert(offset, replacingNode, indent, true, editGroup);
+ doTextInsert(offset, strings[1], editGroup);
+ return endPos;
+ }
+ }
+ }
+ int pos= doVisit(parent, property, offset);
+ if (endPos != -1) {
+ return endPos;
+ }
+ return pos;
+ }
+
+ private int rewriteOptionalQualifier(ASTNode parent, StructuralPropertyDescriptor property, int startPos) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ switch (event.getChangeKind()) {
+ case RewriteEvent.INSERTED: {
+ ASTNode node= (ASTNode) event.getNewValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ doTextInsert(startPos, node, getIndent(startPos), true, editGroup);
+ doTextInsert(startPos, ".", editGroup); //$NON-NLS-1$
+ return startPos;
+ }
+ case RewriteEvent.REMOVED: {
+ try {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ int dotEnd= getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, node.getStartPosition() + node.getLength());
+ doTextRemoveAndVisit(startPos, dotEnd - startPos, node, editGroup);
+ return dotEnd;
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ TextEditGroup editGroup= getEditGroup(event);
+ SourceRange range= getExtendedRange(node);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+
+ doTextRemoveAndVisit(offset, length, node, editGroup);
+ doTextInsert(offset, (ASTNode) event.getNewValue(), getIndent(startPos), true, editGroup);
+ try {
+ return getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, offset + length);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ break;
+ }
+ }
+ }
+ Object node= getOriginalValue(parent, property);
+ if (node == null) {
+ return startPos;
+ }
+ int pos= doVisit((ASTNode) node);
+ try {
+ return getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return pos;
+ }
+
+ class ParagraphListRewriter extends ListRewriter {
+
+ public final static int DEFAULT_SPACING= 1;
+
+ private int initialIndent;
+ private int separatorLines;
+
+ public ParagraphListRewriter(int initialIndent, int separator) {
+ this.initialIndent= initialIndent;
+ this.separatorLines= separator;
+ }
+
+ protected int getInitialIndent() {
+ return this.initialIndent;
+ }
+
+ protected String getSeparatorString(int nodeIndex) {
+ return getSeparatorString(nodeIndex, nodeIndex + 1);
+ }
+
+ protected String getSeparatorString(int nodeIndex, int nextNodeIndex) {
+ int newLines= this.separatorLines == -1 ? getNewLines(nodeIndex) : this.separatorLines;
+
+ String lineDelim= getLineDelimiter();
+ StringBuffer buf= new StringBuffer(lineDelim);
+ for (int i= 0; i < newLines; i++) {
+ buf.append(lineDelim);
+ }
+ buf.append(createIndentString(getNodeIndent(nextNodeIndex)));
+ return buf.toString();
+ }
+
+ private ASTNode getNode(int nodeIndex) {
+ ASTNode elem= (ASTNode) this.list[nodeIndex].getOriginalValue();
+ if (elem == null) {
+ elem= (ASTNode) this.list[nodeIndex].getNewValue();
+ }
+ return elem;
+ }
+
+ private int getNewLines(int nodeIndex) {
+ ASTNode curr= getNode(nodeIndex);
+ ASTNode next= getNode(nodeIndex + 1);
+
+ int currKind= curr.getNodeType();
+ int nextKind= next.getNodeType();
+
+ ASTNode last= null;
+ ASTNode secondLast= null;
+ for (int i= 0; i < this.list.length; i++) {
+ ASTNode elem= (ASTNode) this.list[i].getOriginalValue();
+ if (elem != null) {
+ if (last != null) {
+ if (elem.getNodeType() == nextKind && last.getNodeType() == currKind) {
+ return countEmptyLines(last);
+ }
+ secondLast= last;
+ }
+ last= elem;
+ }
+ }
+ if (currKind == ASTNode.FIELD_DECLARATION && nextKind == ASTNode.FIELD_DECLARATION ) {
+ return 0;
+ }
+ if (secondLast != null) {
+ return countEmptyLines(secondLast);
+ }
+ return DEFAULT_SPACING;
+ }
+
+ private int countEmptyLines(ASTNode last) {
+ LineInformation lineInformation= getLineInformation();
+ int lastLine= lineInformation.getLineOfOffset(getExtendedEnd(last));
+ if (lastLine >= 0) {
+ int startLine= lastLine + 1;
+ int start= lineInformation.getLineOffset(startLine);
+ if (start < 0) {
+ return 0;
+ }
+ char[] cont= getContent();
+ int i= start;
+ while (i < cont.length && ScannerHelper.isWhitespace(cont[i])) {
+ i++;
+ }
+ if (i > start) {
+ lastLine= lineInformation.getLineOfOffset(i);
+ if (lastLine > startLine) {
+ return lastLine - startLine;
+ }
+ }
+ }
+ return 0;
+ }
+
+ protected boolean mustRemoveSeparator(int originalOffset, int nodeIndex) {
+ // Do not remove separator if the previous non removed node is on the same line and the next node is on another line
+ int previousNonRemovedNodeIndex = nodeIndex - 1;
+ while (previousNonRemovedNodeIndex >= 0 && this.list[previousNonRemovedNodeIndex].getChangeKind() == RewriteEvent.REMOVED) {
+ previousNonRemovedNodeIndex--;
+ }
+
+ if (previousNonRemovedNodeIndex > -1) {
+ LineInformation lineInformation = getLineInformation();
+
+ RewriteEvent prevEvent = this.list[previousNonRemovedNodeIndex];
+ int prevKind = prevEvent.getChangeKind();
+ if (prevKind == RewriteEvent.UNCHANGED || prevKind == RewriteEvent.REPLACED) {
+ ASTNode prevNode = (ASTNode) this.list[previousNonRemovedNodeIndex].getOriginalValue();
+ int prevEndPosition = prevNode.getStartPosition() + prevNode.getLength();
+ int prevLine = lineInformation.getLineOfOffset(prevEndPosition);
+ int line = lineInformation.getLineOfOffset(originalOffset);
+
+ if (prevLine == line && nodeIndex + 1 < this.list.length) {
+ RewriteEvent nextEvent = this.list[nodeIndex + 1];
+ int nextKind = nextEvent.getChangeKind();
+
+ if (nextKind == RewriteEvent.UNCHANGED || prevKind == RewriteEvent.REPLACED) {
+ ASTNode nextNode = (ASTNode) nextEvent.getOriginalValue();
+ int nextStartPosition = nextNode.getStartPosition();
+ int nextLine = lineInformation.getLineOfOffset(nextStartPosition);
+
+ return nextLine == line;
+ }
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private int rewriteParagraphList(ASTNode parent, StructuralPropertyDescriptor property, int insertPos, int insertIndent, int separator, int lead) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
+ return doVisit(parent, property, insertPos);
+ }
+
+ RewriteEvent[] events= event.getChildren();
+ ParagraphListRewriter listRewriter= new ParagraphListRewriter(insertIndent, separator);
+ StringBuffer leadString= new StringBuffer();
+ if (isAllOfKind(events, RewriteEvent.INSERTED)) {
+ for (int i= 0; i < lead; i++) {
+ leadString.append(getLineDelimiter());
+ }
+ leadString.append(createIndentString(insertIndent));
+ }
+ return listRewriter.rewriteList(parent, property, insertPos, leadString.toString());
+ }
+
+ private int rewriteOptionalTypeParameters(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword, boolean adjustOnNext, boolean needsSpaceOnRemoveAll) {
+ int pos= offset;
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ RewriteEvent[] children= event.getChildren();
+ try {
+ boolean isAllInserted= isAllOfKind(children, RewriteEvent.INSERTED);
+ if (isAllInserted && adjustOnNext) {
+ pos= getScanner().getNextStartOffset(pos, false); // adjust on next element
+ }
+ boolean isAllRemoved= !isAllInserted && isAllOfKind(children, RewriteEvent.REMOVED);
+ if (isAllRemoved) { // all removed: set start to left bracket
+ int posBeforeOpenBracket= getScanner().getTokenStartOffset(TerminalTokens.TokenNameLESS, pos);
+ if (posBeforeOpenBracket != pos) {
+ needsSpaceOnRemoveAll= false;
+ }
+ pos= posBeforeOpenBracket;
+ }
+ pos= new ListRewriter().rewriteList(parent, property, pos, String.valueOf('<'), ", "); //$NON-NLS-1$
+ if (isAllRemoved) { // all removed: remove right and space up to next element
+ int endPos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameGREATER, pos); // set pos to '>'
+ endPos= getScanner().getNextStartOffset(endPos, false);
+ String replacement= needsSpaceOnRemoveAll ? String.valueOf(' ') : Util.EMPTY_STRING;
+ doTextReplace(pos, endPos - pos, replacement, getEditGroup(children[children.length - 1]));
+ return endPos;
+ } else if (isAllInserted) {
+ doTextInsert(pos, String.valueOf('>' + keyword), getEditGroup(children[children.length - 1]));
+ return pos;
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= doVisit(parent, property, pos);
+ }
+ if (pos != offset) { // list contained some type -> parse after closing bracket
+ try {
+ return getScanner().getTokenEndOffset(TerminalTokens.TokenNameGREATER, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ return pos;
+ }
+
+ private boolean isAllOfKind(RewriteEvent[] children, int kind) {
+ for (int i= 0; i < children.length; i++) {
+ if (children[i].getChangeKind() != kind) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private int rewriteNodeList(ASTNode parent, StructuralPropertyDescriptor property, int pos, String keyword, String separator) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ return new ListRewriter().rewriteList(parent, property, pos, keyword, separator);
+ }
+ return doVisit(parent, property, pos);
+ }
+
+ private void rewriteMethodBody(MethodDeclaration parent, int startPos) {
+ RewriteEvent event= getEvent(parent, MethodDeclaration.BODY_PROPERTY);
+ if (event != null) {
+ switch (event.getChangeKind()) {
+ case RewriteEvent.INSERTED: {
+ int endPos= parent.getStartPosition() + parent.getLength();
+ TextEditGroup editGroup= getEditGroup(event);
+ ASTNode body= (ASTNode) event.getNewValue();
+ doTextRemove(startPos, endPos - startPos, editGroup);
+ int indent= getIndent(parent.getStartPosition());
+ String prefix= this.formatter.METHOD_BODY.getPrefix(indent);
+ doTextInsert(startPos, prefix, editGroup);
+ doTextInsert(startPos, body, indent, true, editGroup);
+ return;
+ }
+ case RewriteEvent.REMOVED: {
+ TextEditGroup editGroup= getEditGroup(event);
+ ASTNode body= (ASTNode) event.getOriginalValue();
+ int endPos= parent.getStartPosition() + parent.getLength();
+ doTextRemoveAndVisit(startPos, endPos - startPos, body, editGroup);
+ doTextInsert(startPos, ";", editGroup); //$NON-NLS-1$
+ return;
+ }
+ case RewriteEvent.REPLACED: {
+ TextEditGroup editGroup= getEditGroup(event);
+ ASTNode body= (ASTNode) event.getOriginalValue();
+ doTextRemoveAndVisit(body.getStartPosition(), body.getLength(), body, editGroup);
+ doTextInsert(body.getStartPosition(), (ASTNode) event.getNewValue(), getIndent(body.getStartPosition()), true, editGroup);
+ return;
+ }
+ }
+ }
+ voidVisit(parent, MethodDeclaration.BODY_PROPERTY);
+ }
+
+ private int rewriteExtraDimensions(ASTNode parent, StructuralPropertyDescriptor property, int pos) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
+ return ((Integer) getOriginalValue(parent, property)).intValue();
+ }
+ int oldDim= ((Integer) event.getOriginalValue()).intValue();
+ int newDim= ((Integer) event.getNewValue()).intValue();
+
+ if (oldDim != newDim) {
+ TextEditGroup editGroup= getEditGroup(event);
+ rewriteExtraDimensions(oldDim, newDim, pos, editGroup);
+ }
+ return oldDim;
+ }
+
+ private void rewriteExtraDimensions(int oldDim, int newDim, int pos, TextEditGroup editGroup) {
+
+ if (oldDim < newDim) {
+ for (int i= oldDim; i < newDim; i++) {
+ doTextInsert(pos, "[]", editGroup); //$NON-NLS-1$
+ }
+ } else if (newDim < oldDim) {
+ try {
+ getScanner().setOffset(pos);
+ for (int i= newDim; i < oldDim; i++) {
+ getScanner().readToToken(TerminalTokens.TokenNameRBRACKET);
+ }
+ doTextRemove(pos, getScanner().getCurrentEndOffset() - pos, editGroup);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ /*
+ * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset.
+ */
+ private int getPosAfterLeftBrace(int pos) {
+ try {
+ int nextToken= getScanner().readNext(pos, true);
+ if (nextToken == TerminalTokens.TokenNameLBRACE) {
+ return getScanner().getCurrentEndOffset();
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return pos;
+ }
+
+ final int getIndent(int offset) {
+ return this.formatter.computeIndentUnits(getIndentOfLine(offset));
+ }
+
+ final void doTextInsert(int insertOffset, ASTNode node, int initialIndentLevel, boolean removeLeadingIndent, TextEditGroup editGroup) {
+ ArrayList markers= new ArrayList();
+ String formatted= this.formatter.getFormattedResult(node, initialIndentLevel, markers);
+
+
+ int currPos= 0;
+ if (removeLeadingIndent) {
+ while (currPos < formatted.length() && ScannerHelper.isWhitespace(formatted.charAt(currPos))) {
+ currPos++;
+ }
+ }
+ for (int i= 0; i < markers.size(); i++) { // markers.size can change!
+ NodeMarker curr= (NodeMarker) markers.get(i);
+
+ int offset= curr.offset;
+ if (offset != currPos) {
+ String insertStr= formatted.substring(currPos, offset);
+ doTextInsert(insertOffset, insertStr, editGroup); // insert until the marker's begin
+ }
+
+ Object data= curr.data;
+ if (data instanceof TextEditGroup) { // tracking a node
+ // need to split and create 2 edits as tracking node can surround replaced node.
+ TextEdit edit= new RangeMarker(insertOffset, 0);
+ addEditGroup((TextEditGroup) data, edit);
+ addEdit(edit);
+ if (curr.length != 0) {
+ int end= offset + curr.length;
+ int k= i + 1;
+ while (k < markers.size() && ((NodeMarker) markers.get(k)).offset < end) {
+ k++;
+ }
+ curr.offset= end;
+ curr.length= 0;
+ markers.add(k, curr); // add again for end position
+ }
+ currPos= offset;
+ } else {
+ String destIndentString= this.formatter.getIndentString(getCurrentLine(formatted, offset));
+ if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
+ CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
+ int srcIndentLevel= getIndent(copySource.getNode().getStartPosition());
+ TextEdit sourceEdit= getCopySourceEdit(copySource);
+ doTextCopy(sourceEdit, insertOffset, srcIndentLevel, destIndentString, editGroup);
+ currPos= offset + curr.length; // continue to insert after the replaced string
+ if (needsNewLineForLineComment(copySource.getNode(), formatted, currPos)) {
+ doTextInsert(insertOffset, getLineDelimiter(), editGroup);
+ }
+ } else if (data instanceof StringPlaceholderData) { // replace with a placeholder
+ String code= ((StringPlaceholderData) data).code;
+ String str= this.formatter.changeIndent(code, 0, destIndentString);
+ doTextInsert(insertOffset, str, editGroup);
+ currPos= offset + curr.length; // continue to insert after the replaced string
+ }
+ }
+
+ }
+ if (currPos < formatted.length()) {
+ String insertStr= formatted.substring(currPos);
+ doTextInsert(insertOffset, insertStr, editGroup);
+ }
+ }
+
+ private boolean needsNewLineForLineComment(ASTNode node, String formatted, int offset) {
+ if (!this.lineCommentEndOffsets.isEndOfLineComment(getExtendedEnd(node), this.content)) {
+ return false;
+ }
+ // copied code ends with a line comment, but doesn't contain the new line
+ return offset < formatted.length() && !IndentManipulation.isLineDelimiterChar(formatted.charAt(offset));
+ }
+
+ private String getCurrentLine(String str, int pos) {
+ for (int i= pos - 1; i>= 0; i--) {
+ char ch= str.charAt(i);
+ if (IndentManipulation.isLineDelimiterChar(ch)) {
+ return str.substring(i + 1, pos);
+ }
+ }
+ return str.substring(0, pos);
+ }
+
+
+ private void rewriteModifiers(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event == null || event.getChangeKind() != RewriteEvent.REPLACED) {
+ return;
+ }
+ try {
+ int oldModifiers= ((Integer) event.getOriginalValue()).intValue();
+ int newModifiers= ((Integer) event.getNewValue()).intValue();
+ TextEditGroup editGroup= getEditGroup(event);
+
+ TokenScanner scanner= getScanner();
+
+ int tok= scanner.readNext(offset, false);
+ int startPos= scanner.getCurrentStartOffset();
+ int nextStart= startPos;
+ loop: while (true) {
+ if (TokenScanner.isComment(tok)) {
+ tok= scanner.readNext(true); // next non-comment token
+ }
+ boolean keep= true;
+ switch (tok) {
+ case TerminalTokens.TokenNamepublic: keep= Modifier.isPublic(newModifiers); break;
+ case TerminalTokens.TokenNameprotected: keep= Modifier.isProtected(newModifiers); break;
+ case TerminalTokens.TokenNameprivate: keep= Modifier.isPrivate(newModifiers); break;
+ case TerminalTokens.TokenNamestatic: keep= Modifier.isStatic(newModifiers); break;
+ case TerminalTokens.TokenNamefinal: keep= Modifier.isFinal(newModifiers); break;
+ case TerminalTokens.TokenNameabstract: keep= Modifier.isAbstract(newModifiers); break;
+ case TerminalTokens.TokenNamenative: keep= Modifier.isNative(newModifiers); break;
+ case TerminalTokens.TokenNamevolatile: keep= Modifier.isVolatile(newModifiers); break;
+ case TerminalTokens.TokenNamestrictfp: keep= Modifier.isStrictfp(newModifiers); break;
+ case TerminalTokens.TokenNametransient: keep= Modifier.isTransient(newModifiers); break;
+ case TerminalTokens.TokenNamesynchronized: keep= Modifier.isSynchronized(newModifiers); break;
+ default:
+ break loop;
+ }
+ tok= getScanner().readNext(false); // include comments
+ int currPos= nextStart;
+ nextStart= getScanner().getCurrentStartOffset();
+ if (!keep) {
+ doTextRemove(currPos, nextStart - currPos, editGroup);
+ }
+ }
+ int addedModifiers= newModifiers & ~oldModifiers;
+ if (addedModifiers != 0) {
+ if (startPos != nextStart) {
+ int visibilityModifiers= addedModifiers & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+ if (visibilityModifiers != 0) {
+ StringBuffer buf= new StringBuffer();
+ ASTRewriteFlattener.printModifiers(visibilityModifiers, buf);
+ doTextInsert(startPos, buf.toString(), editGroup);
+ addedModifiers &= ~visibilityModifiers;
+ }
+ }
+ StringBuffer buf= new StringBuffer();
+ ASTRewriteFlattener.printModifiers(addedModifiers, buf);
+ doTextInsert(nextStart, buf.toString(), editGroup);
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+
+ class ModifierRewriter extends ListRewriter {
+
+ private final Prefix annotationSeparation;
+
+ public ModifierRewriter(Prefix annotationSeparation) {
+ this.annotationSeparation= annotationSeparation;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.ListRewriter#getSeparatorString(int)
+ */
+ protected String getSeparatorString(int nodeIndex) {
+ ASTNode curr= getNewNode(nodeIndex);
+ if (curr instanceof Annotation) {
+ return this.annotationSeparation.getPrefix(getNodeIndent(nodeIndex + 1));
+ }
+ return super.getSeparatorString(nodeIndex);
+ }
+ }
+
+
+ private int rewriteModifiers2(ASTNode node, ChildListPropertyDescriptor property, int pos) {
+ RewriteEvent event= getEvent(node, property);
+ if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
+ return doVisit(node, property, pos);
+ }
+ RewriteEvent[] children= event.getChildren();
+ boolean isAllInsert= isAllOfKind(children, RewriteEvent.INSERTED);
+ boolean isAllRemove= isAllOfKind(children, RewriteEvent.REMOVED);
+ if (isAllInsert || isAllRemove) {
+ // update pos
+ try {
+ pos= getScanner().getNextStartOffset(pos, false);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+
+ Prefix formatterPrefix;
+ if (property == SingleVariableDeclaration.MODIFIERS2_PROPERTY)
+ formatterPrefix= this.formatter.PARAM_ANNOTATION_SEPARATION;
+ else
+ formatterPrefix= this.formatter.ANNOTATION_SEPARATION;
+
+ int endPos= new ModifierRewriter(formatterPrefix).rewriteList(node, property, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
+
+ try {
+ int nextPos= getScanner().getNextStartOffset(endPos, false);
+
+ boolean lastUnchanged= children[children.length - 1].getChangeKind() != RewriteEvent.UNCHANGED;
+
+ if (isAllRemove) {
+ doTextRemove(endPos, nextPos - endPos, getEditGroup(children[children.length - 1]));
+ return nextPos;
+ } else if (isAllInsert || (nextPos == endPos && lastUnchanged)) { // see bug 165654
+ RewriteEvent lastChild= children[children.length - 1];
+ String separator;
+ if (lastChild.getNewValue() instanceof Annotation) {
+ separator= formatterPrefix.getPrefix(getIndent(pos));
+ } else {
+ separator= String.valueOf(' ');
+ }
+ doTextInsert(endPos, separator, getEditGroup(lastChild));
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return endPos;
+ }
+
+
+ private void replaceOperation(int posBeforeOperation, String newOperation, TextEditGroup editGroup) {
+ try {
+ getScanner().readNext(posBeforeOperation, true);
+ doTextReplace(getScanner().getCurrentStartOffset(), getScanner().getCurrentLength(), newOperation, editGroup);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+
+ private void rewriteOperation(ASTNode parent, StructuralPropertyDescriptor property, int posBeforeOperation) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ try {
+ String newOperation= event.getNewValue().toString();
+ TextEditGroup editGroup= getEditGroup(event);
+ getScanner().readNext(posBeforeOperation, true);
+ doTextReplace(getScanner().getCurrentStartOffset(), getScanner().getCurrentLength(), newOperation, editGroup);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#postVisit(ASTNode)
+ */
+ public void postVisit(ASTNode node) {
+ TextEditGroup editGroup= this.eventStore.getTrackedNodeData(node);
+ if (editGroup != null) {
+ this.currentEdit= this.currentEdit.getParent();
+ }
+ // remove copy source edits
+ doCopySourcePostVisit(node, this.sourceCopyEndNodes);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#preVisit(ASTNode)
+ */
+ public void preVisit(ASTNode node) {
+ // copies, then range marker
+
+ CopySourceInfo[] infos= this.eventStore.getNodeCopySources(node);
+ doCopySourcePreVisit(infos, this.sourceCopyEndNodes);
+
+ TextEditGroup editGroup= this.eventStore.getTrackedNodeData(node);
+ if (editGroup != null) {
+ SourceRange range= getExtendedRange(node);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ TextEdit edit= new RangeMarker(offset, length);
+ addEditGroup(editGroup, edit);
+ addEdit(edit);
+ this.currentEdit= edit;
+ }
+
+ ensureSpaceBeforeReplace(node);
+ }
+
+ final void doCopySourcePreVisit(CopySourceInfo[] infos, Stack nodeEndStack) {
+ if (infos != null) {
+ for (int i= 0; i < infos.length; i++) {
+ CopySourceInfo curr= infos[i];
+ TextEdit edit= getCopySourceEdit(curr);
+ addEdit(edit);
+ this.currentEdit= edit;
+ nodeEndStack.push(curr.getNode());
+ }
+ }
+ }
+
+ final void doCopySourcePostVisit(ASTNode node, Stack nodeEndStack) {
+ while (!nodeEndStack.isEmpty() && nodeEndStack.peek() == node) {
+ nodeEndStack.pop();
+ this.currentEdit= this.currentEdit.getParent();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CompilationUnit)
+ */
+ public boolean visit(CompilationUnit node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int startPos= rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE);
+
+ if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) {
+ doTextInsert(0, getLineDelimiter(), getEditGroup(node, CompilationUnit.PACKAGE_PROPERTY));
+ }
+
+ startPos= rewriteParagraphList(node, CompilationUnit.IMPORTS_PROPERTY, startPos, 0, 0, 2);
+ rewriteParagraphList(node, CompilationUnit.TYPES_PROPERTY, startPos, 0, -1, 2);
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeDeclaration)
+ */
+ public boolean visit(TypeDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int apiLevel= node.getAST().apiLevel();
+
+ int pos= rewriteJavadoc(node, TypeDeclaration.JAVADOC_PROPERTY);
+
+ if (apiLevel == JLS2_INTERNAL) {
+ rewriteModifiers(node, TypeDeclaration.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, TypeDeclaration.MODIFIERS2_PROPERTY, pos);
+ }
+
+ boolean isInterface= ((Boolean) getOriginalValue(node, TypeDeclaration.INTERFACE_PROPERTY)).booleanValue();
+ // modifiers & class/interface
+ boolean invertType= isChanged(node, TypeDeclaration.INTERFACE_PROPERTY);
+ if (invertType) {
+ try {
+ int typeToken= isInterface ? TerminalTokens.TokenNameinterface : TerminalTokens.TokenNameclass;
+ getScanner().readToToken(typeToken, node.getStartPosition());
+
+ String str= isInterface ? "class" : "interface"; //$NON-NLS-1$ //$NON-NLS-2$
+ int start= getScanner().getCurrentStartOffset();
+ int end= getScanner().getCurrentEndOffset();
+
+ doTextReplace(start, end - start, str, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
+ } catch (CoreException e) {
+ // ignore
+ }
+ }
+
+ // name
+ pos= rewriteRequiredNode(node, TypeDeclaration.NAME_PROPERTY);
+
+ if (apiLevel >= AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, pos, "", false, true); //$NON-NLS-1$
+ }
+
+ // superclass
+ if (!isInterface || invertType) {
+ ChildPropertyDescriptor superClassProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPERCLASS_PROPERTY : TypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
+
+ RewriteEvent superClassEvent= getEvent(node, superClassProperty);
+
+ int changeKind= superClassEvent != null ? superClassEvent.getChangeKind() : RewriteEvent.UNCHANGED;
+ switch (changeKind) {
+ case RewriteEvent.INSERTED: {
+ doTextInsert(pos, " extends ", getEditGroup(superClassEvent)); //$NON-NLS-1$
+ doTextInsert(pos, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
+ break;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
+ int endPos= getExtendedEnd(superClass);
+ doTextRemoveAndVisit(pos, endPos - pos, superClass, getEditGroup(superClassEvent));
+ pos= endPos;
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
+ SourceRange range= getExtendedRange(superClass);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ doTextRemoveAndVisit(offset, length, superClass, getEditGroup(superClassEvent));
+ doTextInsert(offset, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
+ pos= offset + length;
+ break;
+ }
+ case RewriteEvent.UNCHANGED: {
+ pos= doVisit(node, superClassProperty, pos);
+ }
+ }
+ }
+ // extended interfaces
+ ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPER_INTERFACES_PROPERTY : TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
+
+ RewriteEvent interfaceEvent= getEvent(node, superInterfaceProperty);
+ if (interfaceEvent == null || interfaceEvent.getChangeKind() == RewriteEvent.UNCHANGED) {
+ if (invertType) {
+ List originalNodes= (List) getOriginalValue(node, superInterfaceProperty);
+ if (!originalNodes.isEmpty()) {
+ String keyword= isInterface ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
+ ASTNode firstNode= (ASTNode) originalNodes.get(0);
+ doTextReplace(pos, firstNode.getStartPosition() - pos, keyword, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
+ }
+ }
+ pos= doVisit(node, superInterfaceProperty, pos);
+ } else {
+ String keyword= (isInterface == invertType) ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
+ if (invertType) {
+ List newNodes= (List) interfaceEvent.getNewValue();
+ if (!newNodes.isEmpty()) {
+ List origNodes= (List) interfaceEvent.getOriginalValue();
+ int firstStart= pos;
+ if (!origNodes.isEmpty()) {
+ firstStart= ((ASTNode) origNodes.get(0)).getStartPosition();
+ }
+ doTextReplace(pos, firstStart - pos, keyword, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
+ keyword= ""; //$NON-NLS-1$
+ pos= firstStart;
+ }
+ }
+ pos= rewriteNodeList(node, superInterfaceProperty, pos, keyword, ", "); //$NON-NLS-1$
+ }
+//{ObjectTeams: predicate
+ if (apiLevel == AST.JLS3) {
+ RewriteEvent predicateEvent= getEvent(node, TypeDeclaration.GUARD_PROPERTY);
+ int changeKind = rewriteGuardPredicate(predicateEvent, pos);
+ if (changeKind == RewriteEvent.UNCHANGED)
+ pos= doVisit(node, TypeDeclaration.GUARD_PROPERTY, pos);
+ }
+// SH}
+ // type members
+ // startPos : find position after left brace of type, be aware that bracket might be missing
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ int startPos= getPosAfterLeftBrace(pos);
+ rewriteParagraphList(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
+//{ObjectTeams: precedences:
+ RewriteEvent precedencesEvent = getEvent(node, TypeDeclaration.PRECEDENCE_PROPERTY);
+ if ( precedencesEvent == null
+ || precedencesEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ pos = doVisit(node, TypeDeclaration.PRECEDENCE_PROPERTY, pos);
+ } else {
+ pos = rewriteParagraphList(node,
+ TypeDeclaration.PRECEDENCE_PROPERTY,
+ startPos, startIndent, -1, 2);
+ }
+// SH}
+ return false;
+ }
+
+ private void rewriteReturnType(MethodDeclaration node, boolean isConstructor, boolean isConstructorChange) {
+ ChildPropertyDescriptor property= (node.getAST().apiLevel() == JLS2_INTERNAL) ? MethodDeclaration.RETURN_TYPE_PROPERTY : MethodDeclaration.RETURN_TYPE2_PROPERTY;
+
+ // weakness in the AST: return type can exist, even if missing in source
+ ASTNode originalReturnType= (ASTNode) getOriginalValue(node, property);
+ boolean returnTypeExists= originalReturnType != null && originalReturnType.getStartPosition() != -1;
+ if (!isConstructorChange && returnTypeExists) {
+ rewriteRequiredNode(node, property);
+ return;
+ }
+ // difficult cases: return type insert or remove
+ ASTNode newReturnType= (ASTNode) getNewValue(node, property);
+ if (isConstructorChange || !returnTypeExists && newReturnType != originalReturnType) {
+ // use the start offset of the method name to insert
+ ASTNode originalMethodName= (ASTNode) getOriginalValue(node, MethodDeclaration.NAME_PROPERTY);
+ int nextStart= originalMethodName.getStartPosition(); // see bug 84049: can't use extended offset
+ TextEditGroup editGroup= getEditGroup(node, property);
+ if (isConstructor || !returnTypeExists) { // insert
+ doTextInsert(nextStart, newReturnType, getIndent(nextStart), true, editGroup);
+ doTextInsert(nextStart, " ", editGroup); //$NON-NLS-1$
+ } else { // remove up to the method name
+ int offset= getExtendedOffset(originalReturnType);
+ doTextRemoveAndVisit(offset, nextStart - offset, originalReturnType, editGroup);
+ }
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(MethodDeclaration)
+ */
+ public boolean visit(MethodDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, MethodDeclaration.JAVADOC_PROPERTY);
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, MethodDeclaration.MODIFIERS_PROPERTY, pos);
+ } else {
+ pos= rewriteModifiers2(node, MethodDeclaration.MODIFIERS2_PROPERTY, pos);
+ pos= rewriteOptionalTypeParameters(node, MethodDeclaration.TYPE_PARAMETERS_PROPERTY, pos, " ", true, pos != node.getStartPosition()); //$NON-NLS-1$
+ }
+
+ boolean isConstructorChange= isChanged(node, MethodDeclaration.CONSTRUCTOR_PROPERTY);
+ boolean isConstructor= ((Boolean) getOriginalValue(node, MethodDeclaration.CONSTRUCTOR_PROPERTY)).booleanValue();
+ if (!isConstructor || isConstructorChange) {
+ rewriteReturnType(node, isConstructor, isConstructorChange);
+ }
+ // method name
+ pos= rewriteRequiredNode(node, MethodDeclaration.NAME_PROPERTY);
+
+ // parameters
+ try {
+ if (isChanged(node, MethodDeclaration.PARAMETERS_PROPERTY)) {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ pos= rewriteNodeList(node, MethodDeclaration.PARAMETERS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ pos= doVisit(node, MethodDeclaration.PARAMETERS_PROPERTY, pos);
+ }
+
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+
+ int extraDims= rewriteExtraDimensions(node, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY, pos);
+
+ boolean hasExceptionChanges= isChanged(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
+
+ int bodyChangeKind= getChangeKind(node, MethodDeclaration.BODY_PROPERTY);
+
+ if ((extraDims > 0) && (hasExceptionChanges || bodyChangeKind == RewriteEvent.INSERTED || bodyChangeKind == RewriteEvent.REMOVED)) {
+ int dim= ((Integer) getOriginalValue(node, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY)).intValue();
+ while (dim > 0) {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRBRACKET, pos);
+ dim--;
+ }
+ }
+
+ pos= rewriteNodeList(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY, pos, " throws ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ rewriteMethodBody(node, pos);
+ } catch (CoreException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Block)
+ */
+ public boolean visit(Block node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int startPos;
+ if (isCollapsed(node)) {
+ startPos= node.getStartPosition();
+ } else {
+ startPos= getPosAfterLeftBrace(node.getStartPosition());
+ }
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ rewriteParagraphList(node, Block.STATEMENTS_PROPERTY, startPos, startIndent, 0, 1);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ReturnStatement)
+ */
+ public boolean visit(ReturnStatement node) {
+ try {
+ this.beforeRequiredSpaceIndex = getScanner().getTokenEndOffset(TerminalTokens.TokenNamereturn, node.getStartPosition());
+
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ ensureSpaceBeforeReplace(node);
+
+ rewriteNode(node, ReturnStatement.EXPRESSION_PROPERTY, this.beforeRequiredSpaceIndex, ASTRewriteFormatter.SPACE);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AnonymousClassDeclaration)
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int startPos= getPosAfterLeftBrace(node.getStartPosition());
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ rewriteParagraphList(node, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayAccess)
+ */
+ public boolean visit(ArrayAccess node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, ArrayAccess.ARRAY_PROPERTY);
+ rewriteRequiredNode(node, ArrayAccess.INDEX_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayCreation)
+ */
+ public boolean visit(ArrayCreation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ ArrayType arrayType= (ArrayType) getOriginalValue(node, ArrayCreation.TYPE_PROPERTY);
+ int nOldBrackets= getDimensions(arrayType); // number of total brackets
+ int nNewBrackets= nOldBrackets;
+
+ TextEditGroup editGroup= null;
+ RewriteEvent typeEvent= getEvent(node, ArrayCreation.TYPE_PROPERTY);
+ if (typeEvent != null && typeEvent.getChangeKind() == RewriteEvent.REPLACED) { // changed arraytype can have different dimension or type name
+ ArrayType replacingType= (ArrayType) typeEvent.getNewValue();
+ editGroup= getEditGroup(typeEvent);
+ Type newType= replacingType.getElementType();
+ Type oldType= getElementType(arrayType);
+ if (!newType.equals(oldType)) {
+ SourceRange range= getExtendedRange(oldType);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ doTextRemove(offset, length, editGroup);
+ doTextInsert(offset, newType, 0, false, editGroup);
+ }
+ nNewBrackets= replacingType.getDimensions(); // is replaced type
+ }
+ voidVisit(arrayType);
+
+
+ try {
+ int offset= getScanner().getTokenStartOffset(TerminalTokens.TokenNameLBRACKET, arrayType.getStartPosition());
+ // dimension node with expressions
+ RewriteEvent dimEvent= getEvent(node, ArrayCreation.DIMENSIONS_PROPERTY);
+ boolean hasDimensionChanges= (dimEvent != null && dimEvent.getChangeKind() != RewriteEvent.UNCHANGED);
+ if (hasDimensionChanges) {
+ RewriteEvent[] events= dimEvent.getChildren();
+ // offset on first opening brace
+ for (int i= 0; i < events.length; i++) {
+ RewriteEvent event= events[i];
+ int changeKind= event.getChangeKind();
+ if (changeKind == RewriteEvent.INSERTED) { // insert new dimension
+ editGroup= getEditGroup(event);
+ doTextInsert(offset, "[", editGroup); //$NON-NLS-1$
+ doTextInsert(offset, (ASTNode) event.getNewValue(), 0, false, editGroup);
+ doTextInsert(offset, "]", editGroup); //$NON-NLS-1$
+ nNewBrackets--;
+ } else {
+ ASTNode elem= (ASTNode) event.getOriginalValue();
+ int elemEnd= elem.getStartPosition() + elem.getLength();
+ int endPos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRBRACKET, elemEnd);
+ if (changeKind == RewriteEvent.REMOVED) {
+ editGroup= getEditGroup(event);
+ doTextRemoveAndVisit(offset, endPos - offset, elem, editGroup);
+ } else if (changeKind == RewriteEvent.REPLACED) {
+ editGroup= getEditGroup(event);
+ SourceRange range= getExtendedRange(elem);
+ int elemOffset= range.getStartPosition();
+ int elemLength= range.getLength();
+ doTextRemoveAndVisit(elemOffset, elemLength, elem, editGroup);
+ doTextInsert(elemOffset, (ASTNode) event.getNewValue(), 0, false, editGroup);
+ nNewBrackets--;
+ } else {
+ voidVisit(elem);
+ nNewBrackets--;
+ }
+ offset= endPos;
+ nOldBrackets--;
+ }
+ }
+ } else {
+ offset= doVisit(node, ArrayCreation.DIMENSIONS_PROPERTY, offset);
+ }
+ if (nOldBrackets != nNewBrackets) {
+ if (!hasDimensionChanges) {
+ offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRBRACKET, offset);
+ }
+ rewriteExtraDimensions(nOldBrackets, nNewBrackets, offset, editGroup);
+ }
+
+ int kind= getChangeKind(node, ArrayCreation.INITIALIZER_PROPERTY);
+ if (kind == RewriteEvent.REMOVED) {
+ offset= getScanner().getPreviousTokenEndOffset(TerminalTokens.TokenNameLBRACE, offset);
+ } else {
+ offset= node.getStartPosition() + node.getLength(); // insert pos
+ }
+ rewriteNode(node, ArrayCreation.INITIALIZER_PROPERTY, offset, ASTRewriteFormatter.SPACE);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ private Type getElementType(ArrayType parent) {
+ Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
+ while (t.isArrayType()) {
+ t = (Type) getOriginalValue(t, ArrayType.COMPONENT_TYPE_PROPERTY);
+ }
+ return t;
+ }
+
+ private int getDimensions(ArrayType parent) {
+ Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
+ int dimensions = 1; // always include this array type
+ while (t.isArrayType()) {
+ dimensions++;
+ t = (Type) getOriginalValue(t, ArrayType.COMPONENT_TYPE_PROPERTY);
+ }
+ return dimensions;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayInitializer)
+ */
+ public boolean visit(ArrayInitializer node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int startPos= getPosAfterLeftBrace(node.getStartPosition());
+ rewriteNodeList(node, ArrayInitializer.EXPRESSIONS_PROPERTY, startPos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayType)
+ */
+ public boolean visit(ArrayType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, ArrayType.COMPONENT_TYPE_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AssertStatement)
+ */
+ public boolean visit(AssertStatement node) {
+ try {
+ this.beforeRequiredSpaceIndex = getScanner().getNextEndOffset(node.getStartPosition(), true);
+
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ ensureSpaceBeforeReplace(node);
+
+ int offset= rewriteRequiredNode(node, AssertStatement.EXPRESSION_PROPERTY);
+ rewriteNode(node, AssertStatement.MESSAGE_PROPERTY, offset, ASTRewriteFormatter.ASSERT_COMMENT);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Assignment)
+ */
+ public boolean visit(Assignment node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, Assignment.LEFT_HAND_SIDE_PROPERTY);
+ rewriteOperation(node, Assignment.OPERATOR_PROPERTY, pos);
+ rewriteRequiredNode(node, Assignment.RIGHT_HAND_SIDE_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(BooleanLiteral)
+ */
+ public boolean visit(BooleanLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ Boolean newLiteral= (Boolean) getNewValue(node, BooleanLiteral.BOOLEAN_VALUE_PROPERTY);
+ TextEditGroup group = getEditGroup(node, BooleanLiteral.BOOLEAN_VALUE_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newLiteral.toString(), group);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(BreakStatement)
+ */
+ public boolean visit(BreakStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ try {
+ int offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNamebreak, node.getStartPosition());
+ rewriteNode(node, BreakStatement.LABEL_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between break and label
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CastExpression)
+ */
+ public boolean visit(CastExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, CastExpression.TYPE_PROPERTY);
+ rewriteRequiredNode(node, CastExpression.EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CatchClause)
+ */
+ public boolean visit(CatchClause node) { // catch (Exception) Block
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, CatchClause.EXCEPTION_PROPERTY);
+ rewriteRequiredNode(node, CatchClause.BODY_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CharacterLiteral)
+ */
+ public boolean visit(CharacterLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ String escapedSeq= (String) getNewValue(node, CharacterLiteral.ESCAPED_VALUE_PROPERTY);
+ TextEditGroup group = getEditGroup(node, CharacterLiteral.ESCAPED_VALUE_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), escapedSeq, group);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ClassInstanceCreation)
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteOptionalQualifier(node, ClassInstanceCreation.EXPRESSION_PROPERTY, node.getStartPosition());
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ pos= rewriteRequiredNode(node, ClassInstanceCreation.NAME_PROPERTY);
+ } else {
+ if (isChanged(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY)) {
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNamenew, pos); //after 'new'
+ rewriteOptionalTypeParameters(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, pos, " ", true, true); //$NON-NLS-1$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY);
+ }
+ pos= rewriteRequiredNode(node, ClassInstanceCreation.TYPE_PROPERTY);
+ }
+
+ if (isChanged(node, ClassInstanceCreation.ARGUMENTS_PROPERTY)) {
+ try {
+ int startpos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, ClassInstanceCreation.ARGUMENTS_PROPERTY, startpos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, ClassInstanceCreation.ARGUMENTS_PROPERTY);
+ }
+
+ int kind= getChangeKind(node, ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ if (kind == RewriteEvent.REMOVED) {
+ try {
+ pos= getScanner().getPreviousTokenEndOffset(TerminalTokens.TokenNameLBRACE, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= node.getStartPosition() + node.getLength(); // insert pos
+ }
+ rewriteNode(node, ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY, pos, ASTRewriteFormatter.SPACE);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ConditionalExpression)
+ */
+ public boolean visit(ConditionalExpression node) { // expression ? thenExpression : elseExpression
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, ConditionalExpression.EXPRESSION_PROPERTY);
+ rewriteRequiredNode(node, ConditionalExpression.THEN_EXPRESSION_PROPERTY);
+ rewriteRequiredNode(node, ConditionalExpression.ELSE_EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ConstructorInvocation)
+ */
+ public boolean visit(ConstructorInvocation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= node.getStartPosition();
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, ConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
+ }
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ContinueStatement)
+ */
+ public boolean visit(ContinueStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ try {
+ int offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNamecontinue, node.getStartPosition());
+ rewriteNode(node, ContinueStatement.LABEL_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between continue and label
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(DoStatement)
+ */
+ public boolean visit(DoStatement node) { // do statement while expression
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= node.getStartPosition();
+ try {
+ RewriteEvent event= getEvent(node, DoStatement.BODY_PROPERTY);
+ if (event != null && event.getChangeKind() == RewriteEvent.REPLACED) {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNamedo, pos);
+ ASTNode body= (ASTNode) event.getOriginalValue();
+ int bodyEnd= body.getStartPosition() + body.getLength();
+ int endPos= getScanner().getTokenStartOffset(TerminalTokens.TokenNamewhile, bodyEnd);
+ rewriteBodyNode(node, DoStatement.BODY_PROPERTY, startOffset, endPos, getIndent(node.getStartPosition()), this.formatter.DO_BLOCK); // body
+ } else {
+ voidVisit(node, DoStatement.BODY_PROPERTY);
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+
+ rewriteRequiredNode(node, DoStatement.EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(EmptyStatement)
+ */
+ public boolean visit(EmptyStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ changeNotSupported(node); // no modification possible
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ExpressionStatement)
+ */
+ public boolean visit(ExpressionStatement node) { // expression
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, ExpressionStatement.EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(FieldAccess)
+ */
+ public boolean visit(FieldAccess node) { // expression.name
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, FieldAccess.EXPRESSION_PROPERTY); // expression
+ rewriteRequiredNode(node, FieldAccess.NAME_PROPERTY); // name
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(FieldDeclaration)
+ */
+ public boolean visit(FieldDeclaration node) { //{ Modifier } Type VariableDeclarationFragment { ',' VariableDeclarationFragment } ';'
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, FieldDeclaration.JAVADOC_PROPERTY);
+
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, FieldDeclaration.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, FieldDeclaration.MODIFIERS2_PROPERTY, pos);
+ }
+
+ pos= rewriteRequiredNode(node, FieldDeclaration.TYPE_PROPERTY);
+ rewriteNodeList(node, FieldDeclaration.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ForStatement)
+ */
+ public boolean visit(ForStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ try {
+ int pos= node.getStartPosition();
+
+ if (isChanged(node, ForStatement.INITIALIZERS_PROPERTY)) {
+ // position after opening parent
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ pos= rewriteNodeList(node, ForStatement.INITIALIZERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ pos= doVisit(node, ForStatement.INITIALIZERS_PROPERTY, pos);
+ }
+
+ // position after first semicolon
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameSEMICOLON, pos);
+
+ pos= rewriteNode(node, ForStatement.EXPRESSION_PROPERTY, pos, ASTRewriteFormatter.NONE);
+
+ if (isChanged(node, ForStatement.UPDATERS_PROPERTY)) {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameSEMICOLON, pos);
+ pos= rewriteNodeList(node, ForStatement.UPDATERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ pos= doVisit(node, ForStatement.UPDATERS_PROPERTY, pos);
+ }
+
+ RewriteEvent bodyEvent= getEvent(node, ForStatement.BODY_PROPERTY);
+ if (bodyEvent != null && bodyEvent.getChangeKind() == RewriteEvent.REPLACED) {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+ rewriteBodyNode(node, ForStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.FOR_BLOCK); // body
+ } else {
+ voidVisit(node, ForStatement.BODY_PROPERTY);
+ }
+
+ } catch (CoreException e) {
+ handleException(e);
+ }
+
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(IfStatement)
+ */
+ public boolean visit(IfStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, IfStatement.EXPRESSION_PROPERTY); // statement
+
+ RewriteEvent thenEvent= getEvent(node, IfStatement.THEN_STATEMENT_PROPERTY);
+ int elseChange= getChangeKind(node, IfStatement.ELSE_STATEMENT_PROPERTY);
+
+ if (thenEvent != null && thenEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+ try {
+ int tok= getScanner().readNext(pos, true); // after the closing parent
+ pos= (tok == TerminalTokens.TokenNameRPAREN) ? getScanner().getCurrentEndOffset() : getScanner().getCurrentStartOffset();
+
+ int indent= getIndent(node.getStartPosition());
+
+ int endPos= -1;
+ Object elseStatement= getOriginalValue(node, IfStatement.ELSE_STATEMENT_PROPERTY);
+ if (elseStatement != null) {
+ ASTNode thenStatement = (ASTNode) thenEvent.getOriginalValue();
+ endPos= getScanner().getTokenStartOffset(TerminalTokens.TokenNameelse, thenStatement.getStartPosition() + thenStatement.getLength()); // else keyword
+ }
+ if (elseStatement == null || elseChange != RewriteEvent.UNCHANGED) {
+ pos= rewriteBodyNode(node, IfStatement.THEN_STATEMENT_PROPERTY, pos, endPos, indent, this.formatter.IF_BLOCK_NO_ELSE);
+ } else {
+ pos= rewriteBodyNode(node, IfStatement.THEN_STATEMENT_PROPERTY, pos, endPos, indent, this.formatter.IF_BLOCK_WITH_ELSE);
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= doVisit(node, IfStatement.THEN_STATEMENT_PROPERTY, pos);
+ }
+
+ if (elseChange != RewriteEvent.UNCHANGED) {
+ int indent= getIndent(node.getStartPosition());
+ Object newThen= getNewValue(node, IfStatement.THEN_STATEMENT_PROPERTY);
+ if (newThen instanceof Block) {
+ rewriteBodyNode(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos, -1, indent, this.formatter.ELSE_AFTER_BLOCK);
+ } else {
+ rewriteBodyNode(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos, -1, indent, this.formatter.ELSE_AFTER_STATEMENT);
+ }
+ } else {
+ pos= doVisit(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ImportDeclaration)
+ */
+ public boolean visit(ImportDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ RewriteEvent event= getEvent(node, ImportDeclaration.STATIC_PROPERTY);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ try {
+ int pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameimport, node.getStartPosition());
+ boolean wasStatic= ((Boolean) event.getOriginalValue()).booleanValue();
+ if (wasStatic) {
+ int endPos= getScanner().getTokenEndOffset(TerminalTokens.TokenNamestatic, pos);
+ doTextRemove(pos, endPos - pos, getEditGroup(event));
+ } else {
+ doTextInsert(pos, " static", getEditGroup(event)); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+//{ObjectTeams: base modifier:
+ event= getEvent(node, ImportDeclaration.BASE_PROPERTY);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ try {
+ int pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameimport, node.getStartPosition());
+ boolean wasBase= ((Boolean) event.getOriginalValue()).booleanValue();
+ if (wasBase) {
+ int endPos= getScanner().getTokenEndOffset(TerminalTokens.TokenNamestatic, pos);
+ doTextRemove(pos, endPos - pos, getEditGroup(event));
+ } else {
+ doTextInsert(pos, " base", getEditGroup(event)); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+// SH}
+ }
+
+ int pos= rewriteRequiredNode(node, ImportDeclaration.NAME_PROPERTY);
+
+ RewriteEvent event= getEvent(node, ImportDeclaration.ON_DEMAND_PROPERTY);
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ boolean isOnDemand= ((Boolean) event.getOriginalValue()).booleanValue();
+ if (!isOnDemand) {
+ doTextInsert(pos, ".*", getEditGroup(event)); //$NON-NLS-1$
+ } else {
+ try {
+ int endPos= getScanner().getTokenStartOffset(TerminalTokens.TokenNameSEMICOLON, pos);
+ doTextRemove(pos, endPos - pos, getEditGroup(event));
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+ return false;
+ }
+
+
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(InfixExpression)
+ */
+ public boolean visit(InfixExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, InfixExpression.LEFT_OPERAND_PROPERTY);
+
+ boolean needsNewOperation= isChanged(node, InfixExpression.OPERATOR_PROPERTY);
+ String operation= getNewValue(node, InfixExpression.OPERATOR_PROPERTY).toString();
+ if (needsNewOperation) {
+ replaceOperation(pos, operation, getEditGroup(node, InfixExpression.OPERATOR_PROPERTY));
+ }
+
+ pos= rewriteRequiredNode(node, InfixExpression.RIGHT_OPERAND_PROPERTY);
+
+ RewriteEvent event= getEvent(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
+ String prefixString= ' ' + operation + ' ';
+
+ if (needsNewOperation) {
+ int startPos= pos;
+ TextEditGroup editGroup= getEditGroup(node, InfixExpression.OPERATOR_PROPERTY);
+
+ if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ RewriteEvent[] extendedOperands= event.getChildren();
+ for (int i= 0; i < extendedOperands.length; i++) {
+ RewriteEvent curr= extendedOperands[i];
+ ASTNode elem= (ASTNode) curr.getOriginalValue();
+ if (elem != null) {
+ if (curr.getChangeKind() != RewriteEvent.REPLACED) {
+ replaceOperation(startPos, operation, editGroup);
+ }
+ startPos= elem.getStartPosition() + elem.getLength();
+ }
+ }
+ } else {
+ List extendedOperands= (List) getOriginalValue(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
+ for (int i= 0; i < extendedOperands.size(); i++) {
+ ASTNode elem= (ASTNode) extendedOperands.get(i);
+ replaceOperation(startPos, operation, editGroup);
+ startPos= elem.getStartPosition() + elem.getLength();
+ }
+ }
+ }
+ rewriteNodeList(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY, pos, prefixString, prefixString);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Initializer)
+ */
+ public boolean visit(Initializer node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, Initializer.JAVADOC_PROPERTY);
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, Initializer.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, Initializer.MODIFIERS2_PROPERTY, pos);
+ }
+ rewriteRequiredNode(node, Initializer.BODY_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(InstanceofExpression)
+ */
+ public boolean visit(InstanceofExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, InstanceofExpression.LEFT_OPERAND_PROPERTY);
+ ensureSpaceAfterReplace(node, InstanceofExpression.LEFT_OPERAND_PROPERTY);
+ rewriteRequiredNode(node, InstanceofExpression.RIGHT_OPERAND_PROPERTY);
+ return false;
+ }
+
+ public void ensureSpaceAfterReplace(ASTNode node, ChildPropertyDescriptor desc) {
+ if (getChangeKind(node, desc) == RewriteEvent.REPLACED) {
+ int leftOperandEnd= getExtendedEnd((ASTNode) getOriginalValue(node, desc));
+ try {
+ int offset= getScanner().getNextStartOffset(leftOperandEnd, true); // instanceof
+
+ if (offset == leftOperandEnd) {
+ doTextInsert(offset, String.valueOf(' '), getEditGroup(node, desc));
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ public void ensureSpaceBeforeReplace(ASTNode node) {
+ if (this.beforeRequiredSpaceIndex == -1) return;
+
+ List events = this.eventStore.getChangedPropertieEvents(node);
+
+ for (Iterator iterator = events.iterator(); iterator.hasNext();) {
+ RewriteEvent event = (RewriteEvent) iterator.next();
+ if (event.getChangeKind() == RewriteEvent.REPLACED && event.getOriginalValue() instanceof ASTNode) {
+ if (this.beforeRequiredSpaceIndex == getExtendedOffset((ASTNode) event.getOriginalValue())) {
+ doTextInsert(this.beforeRequiredSpaceIndex , String.valueOf(' '), getEditGroup(event));
+ this.beforeRequiredSpaceIndex = -1;
+ return;
+ }
+ }
+ }
+
+ if (this.beforeRequiredSpaceIndex < getExtendedOffset(node)) {
+ this.beforeRequiredSpaceIndex = -1;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Javadoc)
+ */
+ public boolean visit(Javadoc node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int startPos= node.getStartPosition() + 3;
+ String separator= getLineDelimiter() + getIndentAtOffset(node.getStartPosition()) + " * "; //$NON-NLS-1$
+
+ rewriteNodeList(node, Javadoc.TAGS_PROPERTY, startPos, separator, separator);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(LabeledStatement)
+ */
+ public boolean visit(LabeledStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, LabeledStatement.LABEL_PROPERTY);
+ rewriteRequiredNode(node, LabeledStatement.BODY_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(MethodInvocation)
+ */
+ public boolean visit(MethodInvocation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteOptionalQualifier(node, MethodInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
+ }
+
+ pos= rewriteRequiredNode(node, MethodInvocation.NAME_PROPERTY);
+
+ if (isChanged(node, MethodInvocation.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, MethodInvocation.ARGUMENTS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, MethodInvocation.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(NullLiteral)
+ */
+ public boolean visit(NullLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ changeNotSupported(node); // no modification possible
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(NumberLiteral)
+ */
+ public boolean visit(NumberLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ String newLiteral= (String) getNewValue(node, NumberLiteral.TOKEN_PROPERTY);
+ TextEditGroup group = getEditGroup(node, NumberLiteral.TOKEN_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newLiteral, group);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PackageDeclaration)
+ */
+ public boolean visit(PackageDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ int pos= rewriteJavadoc(node, PackageDeclaration.JAVADOC_PROPERTY);
+ rewriteNodeList(node, PackageDeclaration.ANNOTATIONS_PROPERTY, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ rewriteRequiredNode(node, PackageDeclaration.NAME_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ParenthesizedExpression)
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, ParenthesizedExpression.EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PostfixExpression)
+ */
+ public boolean visit(PostfixExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, PostfixExpression.OPERAND_PROPERTY);
+ rewriteOperation(node, PostfixExpression.OPERATOR_PROPERTY, pos);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PrefixExpression)
+ */
+ public boolean visit(PrefixExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteOperation(node, PrefixExpression.OPERATOR_PROPERTY, node.getStartPosition());
+ rewriteRequiredNode(node, PrefixExpression.OPERAND_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PrimitiveType)
+ */
+ public boolean visit(PrimitiveType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ PrimitiveType.Code newCode= (PrimitiveType.Code) getNewValue(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY);
+ TextEditGroup group = getEditGroup(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newCode.toString(), group);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(QualifiedName)
+ */
+ public boolean visit(QualifiedName node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, QualifiedName.QUALIFIER_PROPERTY);
+ rewriteRequiredNode(node, QualifiedName.NAME_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SimpleName)
+ */
+ public boolean visit(SimpleName node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ String newString= (String) getNewValue(node, SimpleName.IDENTIFIER_PROPERTY);
+ TextEditGroup group = getEditGroup(node, SimpleName.IDENTIFIER_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newString, group);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SimpleType)
+ */
+ public boolean visit(SimpleType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, SimpleType.NAME_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SingleVariableDeclaration)
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= node.getStartPosition();
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, SingleVariableDeclaration.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, pos);
+ }
+ pos= rewriteRequiredNode(node, SingleVariableDeclaration.TYPE_PROPERTY);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (isChanged(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
+ if (getNewValue(node, SingleVariableDeclaration.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
+ doTextInsert(pos, "...", getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY)); //$NON-NLS-1$
+ } else {
+ try {
+ int ellipsisEnd= getScanner().getNextEndOffset(pos, true);
+ doTextRemove(pos, ellipsisEnd - pos, getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY));
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+ }
+
+ pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY);
+ int extraDims= rewriteExtraDimensions(node, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, pos);
+
+ if (extraDims > 0) {
+ int kind= getChangeKind(node, SingleVariableDeclaration.INITIALIZER_PROPERTY);
+ if (kind == RewriteEvent.REMOVED) {
+ try {
+ pos= getScanner().getPreviousTokenEndOffset(TerminalTokens.TokenNameEQUAL, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= node.getStartPosition() + node.getLength(); // insert pos
+ }
+ }
+
+ rewriteNode(node, SingleVariableDeclaration.INITIALIZER_PROPERTY, pos, this.formatter.VAR_INITIALIZER);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(StringLiteral)
+ */
+ public boolean visit(StringLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ String escapedSeq= (String) getNewValue(node, StringLiteral.ESCAPED_VALUE_PROPERTY);
+ TextEditGroup group = getEditGroup(node, StringLiteral.ESCAPED_VALUE_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), escapedSeq, group);
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperConstructorInvocation)
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteOptionalQualifier(node, SuperConstructorInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
+
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, SuperConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
+ }
+
+ if (isChanged(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperFieldAccess)
+ */
+ public boolean visit(SuperFieldAccess node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteOptionalQualifier(node, SuperFieldAccess.QUALIFIER_PROPERTY, node.getStartPosition());
+ rewriteRequiredNode(node, SuperFieldAccess.NAME_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperMethodInvocation)
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteOptionalQualifier(node, SuperMethodInvocation.QUALIFIER_PROPERTY, node.getStartPosition());
+
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (isChanged(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY)) {
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos);
+ rewriteOptionalTypeParameters(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ pos= rewriteRequiredNode(node, SuperMethodInvocation.NAME_PROPERTY);
+
+ if (isChanged(node, SuperMethodInvocation.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, SuperMethodInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, SuperMethodInvocation.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SwitchCase)
+ */
+ public boolean visit(SwitchCase node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // dont allow switching from case to default or back. New statements should be created.
+ rewriteRequiredNode(node, SwitchCase.EXPRESSION_PROPERTY);
+ return false;
+ }
+
+ class SwitchListRewriter extends ParagraphListRewriter {
+
+ private boolean indentSwitchStatementsCompareToCases;
+
+ public SwitchListRewriter(int initialIndent) {
+ super(initialIndent, 0);
+ this.indentSwitchStatementsCompareToCases =
+ DefaultCodeFormatterConstants.TRUE.equals(ASTRewriteAnalyzer.this.options.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES));
+ }
+
+ protected int getNodeIndent(int nodeIndex) {
+ int indent= getInitialIndent();
+
+ if (this.indentSwitchStatementsCompareToCases) {
+ RewriteEvent event = this.list[nodeIndex];
+ int changeKind = event.getChangeKind();
+
+ ASTNode node;
+ if (changeKind == RewriteEvent.INSERTED || changeKind == RewriteEvent.REPLACED) {
+ node= (ASTNode)event.getNewValue();
+ } else {
+ node= (ASTNode)event.getOriginalValue();
+ }
+
+ if (node.getNodeType() != ASTNode.SWITCH_CASE) {
+ indent++;
+ }
+ }
+ return indent;
+ }
+
+ protected String getSeparatorString(int nodeIndex) {
+ int total = this.list.length;
+
+ int nextNodeIndex = nodeIndex + 1;
+ while (nextNodeIndex < total && this.list[nextNodeIndex].getChangeKind() == RewriteEvent.REMOVED) {
+ nextNodeIndex++;
+ }
+ if (nextNodeIndex == total) {
+ return super.getSeparatorString(nodeIndex);
+ }
+ return getSeparatorString(nodeIndex, nextNodeIndex);
+ }
+
+ protected void updateIndent(int prevMark, int originalOffset, int nodeIndex, TextEditGroup editGroup) {
+ if (prevMark != RewriteEvent.UNCHANGED && prevMark != RewriteEvent.REPLACED) return;
+
+ // Do not change indent if the previous non removed node is on the same line
+ int previousNonRemovedNodeIndex = nodeIndex - 1;
+ while (previousNonRemovedNodeIndex >= 0 && this.list[previousNonRemovedNodeIndex].getChangeKind() == RewriteEvent.REMOVED) {
+ previousNonRemovedNodeIndex--;
+ }
+
+ if (previousNonRemovedNodeIndex > -1) {
+ LineInformation lineInformation = getLineInformation();
+
+ RewriteEvent prevEvent = this.list[previousNonRemovedNodeIndex];
+ int prevKind = prevEvent.getChangeKind();
+ if (prevKind == RewriteEvent.UNCHANGED || prevKind == RewriteEvent.REPLACED) {
+ ASTNode prevNode = (ASTNode) this.list[previousNonRemovedNodeIndex].getOriginalValue();
+ int prevEndPosition = prevNode.getStartPosition() + prevNode.getLength();
+ int prevLine = lineInformation.getLineOfOffset(prevEndPosition);
+ int line = lineInformation.getLineOfOffset(originalOffset);
+
+ if (prevLine == line) {
+ return;
+ }
+ }
+ }
+
+ int total = this.list.length;
+ while (nodeIndex < total && this.list[nodeIndex].getChangeKind() == RewriteEvent.REMOVED) {
+ nodeIndex++;
+ }
+
+ int originalIndent = getIndent(originalOffset);
+ int newIndent = getNodeIndent(nodeIndex);
+
+ if (originalIndent != newIndent) {
+
+ int line= getLineInformation().getLineOfOffset(originalOffset);
+ if (line >= 0) {
+ int lineStart= getLineInformation().getLineOffset(line);
+
+ doTextRemove(lineStart, originalOffset - lineStart, editGroup); // remove previous indentation
+ doTextInsert(lineStart, createIndentString(newIndent), editGroup); // add new indentation
+ }
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SwitchStatement)
+ */
+ public boolean visit(SwitchStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, SwitchStatement.EXPRESSION_PROPERTY);
+
+ ChildListPropertyDescriptor property= SwitchStatement.STATEMENTS_PROPERTY;
+ if (getChangeKind(node, property) != RewriteEvent.UNCHANGED) {
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLBRACE, pos);
+ int insertIndent= getIndent(node.getStartPosition());
+ if (DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH))) {
+ insertIndent++;
+ }
+
+ ParagraphListRewriter listRewriter= new SwitchListRewriter(insertIndent);
+ StringBuffer leadString= new StringBuffer();
+ leadString.append(getLineDelimiter());
+ leadString.append(createIndentString(insertIndent));
+ listRewriter.rewriteList(node, property, pos, leadString.toString());
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, SwitchStatement.STATEMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SynchronizedStatement)
+ */
+ public boolean visit(SynchronizedStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, SynchronizedStatement.EXPRESSION_PROPERTY);
+ rewriteRequiredNode(node, SynchronizedStatement.BODY_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ThisExpression)
+ */
+ public boolean visit(ThisExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteOptionalQualifier(node, ThisExpression.QUALIFIER_PROPERTY, node.getStartPosition());
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ThrowStatement)
+ */
+ public boolean visit(ThrowStatement node) {
+ try {
+ this.beforeRequiredSpaceIndex = getScanner().getTokenEndOffset(TerminalTokens.TokenNamethrow, node.getStartPosition());
+
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ ensureSpaceBeforeReplace(node);
+
+ rewriteRequiredNode(node, ThrowStatement.EXPRESSION_PROPERTY);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TryStatement)
+ */
+ public boolean visit(TryStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, TryStatement.BODY_PROPERTY);
+
+ if (isChanged(node, TryStatement.CATCH_CLAUSES_PROPERTY)) {
+ int indent= getIndent(node.getStartPosition());
+ String prefix= this.formatter.CATCH_BLOCK.getPrefix(indent);
+ pos= rewriteNodeList(node, TryStatement.CATCH_CLAUSES_PROPERTY, pos, prefix, prefix);
+ } else {
+ pos= doVisit(node, TryStatement.CATCH_CLAUSES_PROPERTY, pos);
+ }
+ rewriteNode(node, TryStatement.FINALLY_PROPERTY, pos, this.formatter.FINALLY_BLOCK);
+ return false;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeDeclarationStatement)
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteRequiredNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY);
+ } else {
+ rewriteRequiredNode(node, TypeDeclarationStatement.DECLARATION_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeLiteral)
+ */
+ public boolean visit(TypeLiteral node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, TypeLiteral.TYPE_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationExpression)
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // same code as FieldDeclaration
+ int pos= node.getStartPosition();
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, VariableDeclarationExpression.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, VariableDeclarationExpression.MODIFIERS2_PROPERTY, pos);
+ }
+ pos= rewriteRequiredNode(node, VariableDeclarationExpression.TYPE_PROPERTY);
+ rewriteNodeList(node, VariableDeclarationExpression.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationFragment)
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, VariableDeclarationFragment.NAME_PROPERTY);
+
+ int extraDims= rewriteExtraDimensions(node, VariableDeclarationFragment.EXTRA_DIMENSIONS_PROPERTY, pos);
+
+ if (extraDims > 0) {
+ int kind= getChangeKind(node, VariableDeclarationFragment.INITIALIZER_PROPERTY);
+ if (kind == RewriteEvent.REMOVED) {
+ try {
+ pos= getScanner().getPreviousTokenEndOffset(TerminalTokens.TokenNameEQUAL, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= node.getStartPosition() + node.getLength(); // insert pos
+ }
+ }
+ rewriteNode(node, VariableDeclarationFragment.INITIALIZER_PROPERTY, pos, this.formatter.VAR_INITIALIZER);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationStatement)
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // same code as FieldDeclaration
+ int pos= node.getStartPosition();
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ rewriteModifiers(node, VariableDeclarationStatement.MODIFIERS_PROPERTY, pos);
+ } else {
+ rewriteModifiers2(node, VariableDeclarationStatement.MODIFIERS2_PROPERTY, pos);
+ }
+ pos= rewriteRequiredNode(node, VariableDeclarationStatement.TYPE_PROPERTY);
+
+ rewriteNodeList(node, VariableDeclarationStatement.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(WhileStatement)
+ */
+ public boolean visit(WhileStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, WhileStatement.EXPRESSION_PROPERTY);
+
+ try {
+ if (isChanged(node, WhileStatement.BODY_PROPERTY)) {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+ rewriteBodyNode(node, WhileStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.WHILE_BLOCK); // body
+ } else {
+ voidVisit(node, WhileStatement.BODY_PROPERTY);
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
+ */
+ public boolean visit(MemberRef node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteNode(node, MemberRef.QUALIFIER_PROPERTY, node.getStartPosition(), ASTRewriteFormatter.NONE);
+
+ rewriteRequiredNode(node, MemberRef.NAME_PROPERTY);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
+ */
+ public boolean visit(MethodRef node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteNode(node, MethodRef.QUALIFIER_PROPERTY, node.getStartPosition(), ASTRewriteFormatter.NONE);
+
+ int pos= rewriteRequiredNode(node, MethodRef.NAME_PROPERTY);
+
+ if (isChanged(node, MethodRef.PARAMETERS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, MethodRef.PARAMETERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, MethodRef.PARAMETERS_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
+ */
+ public boolean visit(MethodRefParameter node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteRequiredNode(node, MethodRefParameter.TYPE_PROPERTY);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (isChanged(node, MethodRefParameter.VARARGS_PROPERTY)) {
+ if (getNewValue(node, MethodRefParameter.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
+ doTextInsert(pos, "...", getEditGroup(node, MethodRefParameter.VARARGS_PROPERTY)); //$NON-NLS-1$
+ } else {
+ try {
+ int ellipsisEnd= getScanner().getNextEndOffset(pos, true);
+ doTextRemove(pos, ellipsisEnd - pos, getEditGroup(node, MethodRefParameter.VARARGS_PROPERTY));
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ }
+ }
+ rewriteNode(node, MethodRefParameter.NAME_PROPERTY, pos, ASTRewriteFormatter.SPACE);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
+ */
+ public boolean visit(TagElement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int changeKind= getChangeKind(node, TagElement.TAG_NAME_PROPERTY);
+ switch (changeKind) {
+ case RewriteEvent.INSERTED: {
+ String newTagName= (String) getNewValue(node, TagElement.TAG_NAME_PROPERTY);
+ doTextInsert(node.getStartPosition(), newTagName, getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
+ break;
+ }
+ case RewriteEvent.REMOVED: {
+ doTextRemove(node.getStartPosition(), findTagNameEnd(node) - node.getStartPosition(), getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ String newTagName= (String) getNewValue(node, TagElement.TAG_NAME_PROPERTY);
+ doTextReplace(node.getStartPosition(), findTagNameEnd(node) - node.getStartPosition(), newTagName, getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
+ break;
+ }
+ }
+
+ if (isChanged(node, TagElement.FRAGMENTS_PROPERTY)) {
+ // eval position after name
+ int endOffset= findTagNameEnd(node);
+ rewriteNodeList(node, TagElement.FRAGMENTS_PROPERTY, endOffset, " ", " "); //$NON-NLS-1$//$NON-NLS-2$
+ } else {
+ voidVisit(node, TagElement.FRAGMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ private int findTagNameEnd(TagElement tagNode) {
+ if (tagNode.getTagName() != null) {
+ char[] cont= getContent();
+ int len= cont.length;
+ int i= tagNode.getStartPosition();
+ while (i < len && !IndentManipulation.isIndentChar(cont[i])) {
+ i++;
+ }
+ return i;
+ }
+ return tagNode.getStartPosition();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
+ */
+ public boolean visit(TextElement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ String newText= (String) getNewValue(node, TextElement.TEXT_PROPERTY);
+ TextEditGroup group = getEditGroup(node, TextElement.TEXT_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newText, group);
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
+ */
+ public boolean visit(AnnotationTypeDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, AnnotationTypeDeclaration.JAVADOC_PROPERTY);
+ rewriteModifiers2(node, AnnotationTypeDeclaration.MODIFIERS2_PROPERTY, pos);
+ pos= rewriteRequiredNode(node, AnnotationTypeDeclaration.NAME_PROPERTY);
+
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ int startPos= getPosAfterLeftBrace(pos);
+ rewriteParagraphList(node, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
+ */
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, AnnotationTypeMemberDeclaration.JAVADOC_PROPERTY);
+ rewriteModifiers2(node, AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY, pos);
+ rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.TYPE_PROPERTY);
+ pos= rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.NAME_PROPERTY);
+
+ try {
+ int changeKind= getChangeKind(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY);
+ if (changeKind == RewriteEvent.INSERTED || changeKind == RewriteEvent.REMOVED) {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+ }
+ rewriteNode(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY, pos, this.formatter.ANNOT_MEMBER_DEFAULT);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
+ */
+ public boolean visit(EnhancedForStatement node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteRequiredNode(node, EnhancedForStatement.PARAMETER_PROPERTY);
+ int pos= rewriteRequiredNode(node, EnhancedForStatement.EXPRESSION_PROPERTY);
+
+ RewriteEvent bodyEvent= getEvent(node, EnhancedForStatement.BODY_PROPERTY);
+ if (bodyEvent != null && bodyEvent.getChangeKind() == RewriteEvent.REPLACED) {
+ int startOffset;
+ try {
+ startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+ rewriteBodyNode(node, EnhancedForStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.FOR_BLOCK); // body
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, EnhancedForStatement.BODY_PROPERTY);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+ */
+ public boolean visit(EnumConstantDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, EnumConstantDeclaration.JAVADOC_PROPERTY);
+ rewriteModifiers2(node, EnumConstantDeclaration.MODIFIERS2_PROPERTY, pos);
+ pos= rewriteRequiredNode(node, EnumConstantDeclaration.NAME_PROPERTY);
+ RewriteEvent argsEvent= getEvent(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY);
+ if (argsEvent != null && argsEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+ RewriteEvent[] children= argsEvent.getChildren();
+ try {
+ int nextTok= getScanner().readNext(pos, true);
+ boolean hasParents= (nextTok == TerminalTokens.TokenNameLPAREN);
+ boolean isAllRemoved= hasParents && isAllOfKind(children, RewriteEvent.REMOVED);
+ String prefix= ""; //$NON-NLS-1$
+ if (!hasParents) {
+ prefix= "("; //$NON-NLS-1$
+ } else if (!isAllRemoved) {
+ pos= getScanner().getCurrentEndOffset();
+ }
+ pos= rewriteNodeList(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, pos, prefix, ", "); //$NON-NLS-1$
+
+ if (!hasParents) {
+ doTextInsert(pos, ")", getEditGroup(children[children.length - 1])); //$NON-NLS-1$
+ } else if (isAllRemoved) {
+ int afterClosing= getScanner().getNextEndOffset(pos, true);
+ doTextRemove(pos, afterClosing - pos, getEditGroup(children[children.length - 1]));
+ pos= afterClosing;
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= doVisit(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, pos);
+ }
+
+ if (isChanged(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY)) {
+ int kind= getChangeKind(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ if (kind == RewriteEvent.REMOVED) {
+ try {
+ // 'pos' can be before brace
+ pos= getScanner().getPreviousTokenEndOffset(TerminalTokens.TokenNameLBRACE, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ pos= node.getStartPosition() + node.getLength(); // insert pos
+ }
+ rewriteNode(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY, pos, ASTRewriteFormatter.SPACE);
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
+ */
+ public boolean visit(EnumDeclaration node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteJavadoc(node, EnumDeclaration.JAVADOC_PROPERTY);
+ rewriteModifiers2(node, EnumDeclaration.MODIFIERS2_PROPERTY, pos);
+ pos= rewriteRequiredNode(node, EnumDeclaration.NAME_PROPERTY);
+ pos= rewriteNodeList(node, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, pos, " implements ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pos= getPosAfterLeftBrace(pos);
+
+ String leadString= ""; //$NON-NLS-1$
+ RewriteEvent constEvent= getEvent(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY);
+
+ if (constEvent != null && constEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+ RewriteEvent[] events= constEvent.getChildren();
+ if (isAllOfKind(events, RewriteEvent.INSERTED)) {
+ leadString= this.formatter.FIRST_ENUM_CONST.getPrefix(getIndent(node.getStartPosition()));
+ }
+ }
+ pos= rewriteNodeList(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY, pos, leadString, ", "); //$NON-NLS-1$
+
+ RewriteEvent bodyEvent= getEvent(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY);
+ int indent= 0;
+ if (bodyEvent != null && bodyEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
+ boolean hasConstants= !((List) getNewValue(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY)).isEmpty();
+
+ RewriteEvent[] children= bodyEvent.getChildren();
+ try {
+ if (hasConstants) {
+ indent= getIndent(pos);
+ } else {
+ indent= getIndent(node.getStartPosition()) + 1;
+ }
+ int token= getScanner().readNext(pos, true);
+ boolean hasSemicolon= token == TerminalTokens.TokenNameSEMICOLON;
+ if (!hasSemicolon && isAllOfKind(children, RewriteEvent.INSERTED)) {
+ if (!hasConstants) {
+ String str= this.formatter.FIRST_ENUM_CONST.getPrefix(indent - 1);
+ doTextInsert(pos, str, getEditGroup(children[0]));
+ }
+ doTextInsert(pos, ";", getEditGroup(children[0])); //$NON-NLS-1$
+ } else if (hasSemicolon) {
+ int endPos= getScanner().getCurrentEndOffset();
+ if (isAllOfKind(children, RewriteEvent.REMOVED)) {
+ doTextRemove(pos, endPos - pos, getEditGroup(children[0]));
+ }
+ pos= endPos;
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ }
+ rewriteParagraphList(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY, pos, indent, -1, 2);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
+ */
+ public boolean visit(MarkerAnnotation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteRequiredNode(node, MarkerAnnotation.TYPE_NAME_PROPERTY);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
+ */
+ public boolean visit(MemberValuePair node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteRequiredNode(node, MemberValuePair.NAME_PROPERTY);
+ rewriteRequiredNode(node, MemberValuePair.VALUE_PROPERTY);
+
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
+ */
+ public boolean visit(Modifier node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ String newText= getNewValue(node, Modifier.KEYWORD_PROPERTY).toString(); // type Modifier.ModifierKeyword
+ TextEditGroup group = getEditGroup(node, Modifier.KEYWORD_PROPERTY);
+ doTextReplace(node.getStartPosition(), node.getLength(), newText, group);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
+ */
+ public boolean visit(NormalAnnotation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteRequiredNode(node, NormalAnnotation.TYPE_NAME_PROPERTY);
+ if (isChanged(node, NormalAnnotation.VALUES_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, NormalAnnotation.VALUES_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, NormalAnnotation.VALUES_PROPERTY);
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
+ */
+ public boolean visit(ParameterizedType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteRequiredNode(node, ParameterizedType.TYPE_PROPERTY);
+ if (isChanged(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLESS, pos);
+ rewriteNodeList(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
+ */
+ public boolean visit(QualifiedType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY);
+ rewriteRequiredNode(node, QualifiedType.NAME_PROPERTY);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
+ */
+ public boolean visit(SingleMemberAnnotation node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ rewriteRequiredNode(node, SingleMemberAnnotation.TYPE_NAME_PROPERTY);
+ rewriteRequiredNode(node, SingleMemberAnnotation.VALUE_PROPERTY);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
+ */
+ public boolean visit(TypeParameter node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= rewriteRequiredNode(node, TypeParameter.NAME_PROPERTY);
+ if (isChanged(node, TypeParameter.TYPE_BOUNDS_PROPERTY)) {
+//{ObjectTeams: <B base R>:
+ if (node.hasBaseBound())
+ rewriteNodeList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, pos, " base ", " & "); //$NON-NLS-1$ //$NON-NLS-2$
+ else
+// SH}
+ rewriteNodeList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, pos, " extends ", " & "); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ voidVisit(node, TypeParameter.TYPE_BOUNDS_PROPERTY);
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
+ */
+ public boolean visit(WildcardType node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ try {
+ int pos= getScanner().getNextEndOffset(node.getStartPosition(), true); // pos after question mark
+
+ Prefix prefix;
+ if (Boolean.TRUE.equals(getNewValue(node, WildcardType.UPPER_BOUND_PROPERTY))) {
+ prefix= this.formatter.WILDCARD_EXTENDS;
+ } else {
+ prefix= this.formatter.WILDCARD_SUPER;
+ }
+
+ int boundKindChange= getChangeKind(node, WildcardType.UPPER_BOUND_PROPERTY);
+ if (boundKindChange != RewriteEvent.UNCHANGED) {
+ int boundTypeChange= getChangeKind(node, WildcardType.BOUND_PROPERTY);
+ if (boundTypeChange != RewriteEvent.INSERTED && boundTypeChange != RewriteEvent.REMOVED) {
+ ASTNode type= (ASTNode) getOriginalValue(node, WildcardType.BOUND_PROPERTY);
+ String str= prefix.getPrefix(0);
+ doTextReplace(pos, type.getStartPosition() - pos, str, getEditGroup(node, WildcardType.BOUND_PROPERTY));
+ }
+ }
+ rewriteNode(node, WildcardType.BOUND_PROPERTY, pos, prefix);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ final void handleException(Throwable e) {
+ IllegalArgumentException runtimeException= new IllegalArgumentException("Document does not match the AST"); //$NON-NLS-1$
+ runtimeException.initCause(e);
+ throw runtimeException;
+ }
+// {ObjectTeams: visit methods for analyzing OT nodes
+ public boolean visit(RoleTypeDeclaration node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int apiLevel= node.getAST().apiLevel();
+
+ // javadoc
+ int pos = rewriteJavadoc(node, RoleTypeDeclaration.JAVADOC_PROPERTY);
+
+ // modifier
+ if(apiLevel == AST.JLS3)
+ pos = rewriteModifiers2(node, RoleTypeDeclaration.MODIFIERS2_PROPERTY, pos);
+ else
+ rewriteModifiers(node, RoleTypeDeclaration.MODIFIERS_PROPERTY, pos);
+
+ boolean isTeam = ((Boolean) getOriginalValue(node, RoleTypeDeclaration.TEAM_PROPERTY)).booleanValue();
+ // modifiers & team
+ boolean invertTeam = isChanged(node, RoleTypeDeclaration.TEAM_PROPERTY);
+ if (invertTeam) {
+ if (isTeam) {
+ try {
+ getScanner().readToToken(TerminalTokens.TokenNameteam, node.getStartPosition());
+ int start= getScanner().getCurrentStartOffset();
+ int end= getScanner().getCurrentEndOffset();
+ doTextRemove(start, end-start+1, getEditGroup(node, RoleTypeDeclaration.TEAM_PROPERTY));
+ } catch (CoreException e) {
+ // ignore
+ }
+ } else {
+ doTextInsert(pos, " team", getEditGroup(node, RoleTypeDeclaration.TEAM_PROPERTY)); //$NON-NLS-1$
+ }
+ }
+
+ boolean isInterface= ((Boolean) getOriginalValue(node, RoleTypeDeclaration.INTERFACE_PROPERTY)).booleanValue();
+ // modifiers & class/interface
+ boolean invertType= isChanged(node, RoleTypeDeclaration.INTERFACE_PROPERTY);
+ if (invertType) {
+ try {
+ int typeToken= isInterface ? TerminalTokens.TokenNameinterface : TerminalTokens.TokenNameclass;
+ getScanner().readToToken(typeToken, node.getStartPosition());
+
+ String str= isInterface ? "class" : "interface"; //$NON-NLS-1$ //$NON-NLS-2$
+ int start= getScanner().getCurrentStartOffset();
+ int end= getScanner().getCurrentEndOffset();
+
+ doTextReplace(start, end - start, str, getEditGroup(node, RoleTypeDeclaration.INTERFACE_PROPERTY));
+ } catch (CoreException e) {
+ // ignore
+ }
+ }
+
+ // name
+ pos = rewriteRequiredNode(node, RoleTypeDeclaration.NAME_PROPERTY);
+
+ if (apiLevel >= AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, RoleTypeDeclaration.TYPE_PARAMETERS_PROPERTY, pos, "", false, true); //$NON-NLS-1$
+ }
+
+ // superclass
+ if (!isInterface || invertType) {
+ ChildPropertyDescriptor superClassProperty= (apiLevel == JLS2_INTERNAL) ? RoleTypeDeclaration.SUPERCLASS_PROPERTY : RoleTypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
+
+ RewriteEvent superClassEvent= getEvent(node, superClassProperty);
+
+ int changeKind= superClassEvent != null ? superClassEvent.getChangeKind() : RewriteEvent.UNCHANGED;
+ switch (changeKind) {
+ case RewriteEvent.INSERTED: {
+ doTextInsert(pos, " extends ", getEditGroup(superClassEvent)); //$NON-NLS-1$
+ doTextInsert(pos, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
+ break;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
+ int endPos= getExtendedEnd(superClass);
+ doTextRemoveAndVisit(pos, endPos - pos, superClass, getEditGroup(superClassEvent));
+ pos= endPos;
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
+ SourceRange range= getExtendedRange(superClass);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ doTextRemoveAndVisit(offset, length, superClass, getEditGroup(superClassEvent));
+ doTextInsert(offset, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
+ pos= offset + length;
+ break;
+ }
+ case RewriteEvent.UNCHANGED: {
+ pos= doVisit(node, superClassProperty, pos);
+ }
+ }
+ }
+
+ // extended interfaces
+ ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == JLS2_INTERNAL) ? RoleTypeDeclaration.SUPER_INTERFACES_PROPERTY : RoleTypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
+
+ RewriteEvent interfaceEvent= getEvent(node, superInterfaceProperty);
+ if (interfaceEvent == null || interfaceEvent.getChangeKind() == RewriteEvent.UNCHANGED) {
+ if (invertType) {
+ List originalNodes= (List) getOriginalValue(node, superInterfaceProperty);
+ if (!originalNodes.isEmpty()) {
+ String keyword= isInterface ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
+ ASTNode firstNode= (ASTNode) originalNodes.get(0);
+ doTextReplace(pos, firstNode.getStartPosition() - pos, keyword, getEditGroup(node, RoleTypeDeclaration.INTERFACE_PROPERTY));
+ }
+ }
+ pos= doVisit(node, superInterfaceProperty, pos);
+ } else {
+ String keyword= (isInterface == invertType) ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
+ if (invertType) {
+ List newNodes= (List) interfaceEvent.getNewValue();
+ if (!newNodes.isEmpty()) {
+ List origNodes= (List) interfaceEvent.getOriginalValue();
+ int firstStart= pos;
+ if (!origNodes.isEmpty()) {
+ firstStart= ((ASTNode) origNodes.get(0)).getStartPosition();
+ }
+ doTextReplace(pos, firstStart - pos, keyword, getEditGroup(node, RoleTypeDeclaration.INTERFACE_PROPERTY));
+ keyword= ""; //$NON-NLS-1$
+ pos= firstStart;
+ }
+ }
+ pos= rewriteNodeList(node, superInterfaceProperty, pos, keyword, ", "); //$NON-NLS-1$
+ }
+
+
+ // baseclass
+ ChildPropertyDescriptor baseClassProperty = (apiLevel == JLS2_INTERNAL)? RoleTypeDeclaration.BASECLASS_PROPERTY : RoleTypeDeclaration.BASECLASS_TYPE_PROPERTY;
+ RewriteEvent baseClassEvent= getEvent(node, baseClassProperty);
+
+ int changeKind= baseClassEvent != null ? baseClassEvent.getChangeKind() : RewriteEvent.UNCHANGED;
+ switch (changeKind) {
+ case RewriteEvent.INSERTED: {
+ doTextInsert(pos, " playedBy ", getEditGroup(baseClassEvent)); //$NON-NLS-1$
+ doTextInsert(pos, (ASTNode) baseClassEvent.getNewValue(), 0, false, getEditGroup(baseClassEvent));
+ break;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode superClass= (ASTNode) baseClassEvent.getOriginalValue();
+ int endPos= getExtendedEnd(superClass);
+ doTextRemoveAndVisit(pos, endPos - pos, superClass, getEditGroup(baseClassEvent));
+ pos= endPos;
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode superClass= (ASTNode) baseClassEvent.getOriginalValue();
+ SourceRange range= getExtendedRange(superClass);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ doTextRemoveAndVisit(offset, length, superClass, getEditGroup(baseClassEvent));
+ doTextInsert(offset, (ASTNode) baseClassEvent.getNewValue(), 0, false, getEditGroup(baseClassEvent));
+ pos= offset + length;
+ break;
+ }
+ case RewriteEvent.UNCHANGED: {
+ pos= doVisit(node, baseClassProperty, pos);
+ }
+ }
+
+ // predicate
+ if (apiLevel == AST.JLS3) {
+ RewriteEvent predicateEvent= getEvent(node, RoleTypeDeclaration.GUARD_PROPERTY);
+ changeKind = rewriteGuardPredicate(predicateEvent, pos);
+ if (changeKind == RewriteEvent.UNCHANGED)
+ pos= doVisit(node, RoleTypeDeclaration.GUARD_PROPERTY, pos);
+ }
+
+ // type members
+ // startPos : find position after left brace of type, be aware that bracket might be missing
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ int startPos= getPosAfterLeftBrace(pos);
+ pos = rewriteParagraphList(node, RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
+
+ // rewrite precedences
+ RewriteEvent precedencesEvent = getEvent(node, RoleTypeDeclaration.PRECEDENCE_PROPERTY);
+ if ( precedencesEvent == null
+ || precedencesEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ pos = doVisit(node, RoleTypeDeclaration.PRECEDENCE_PROPERTY, pos);
+ } else {
+ pos = rewriteParagraphList(node,
+ RoleTypeDeclaration.PRECEDENCE_PROPERTY,
+ pos, startIndent, -1, 2);
+ }
+
+ return false;
+ }
+ private int rewriteGuardPredicate(RewriteEvent predicateEvent, int pos) {
+ int changeKind= predicateEvent != null ? predicateEvent.getChangeKind() : RewriteEvent.UNCHANGED;
+ switch (changeKind) {
+ case RewriteEvent.INSERTED: {
+ GuardPredicateDeclaration newGuard = (GuardPredicateDeclaration) predicateEvent.getNewValue();
+ int indent = getIndent(pos);
+ doTextInsert(pos, getLineDelimiter(), getEditGroup(predicateEvent));
+ doTextInsert(pos, newGuard, indent+1, false, getEditGroup(predicateEvent));
+ //doTextInsert(pos, getLineDelimiter(), getEditGroup(predicateEvent));
+ break;
+ }
+ case RewriteEvent.REMOVED: {
+ ASTNode predicate = (ASTNode) predicateEvent.getOriginalValue();
+ int endPos= getExtendedEnd(predicate);
+ doTextRemoveAndVisit(pos, endPos - pos, predicate, getEditGroup(predicateEvent));
+ pos= endPos;
+ break;
+ }
+ case RewriteEvent.REPLACED: {
+ ASTNode predicate = (ASTNode) predicateEvent.getOriginalValue();
+ SourceRange range= getExtendedRange(predicate);
+ int offset= range.getStartPosition();
+ int length= range.getLength();
+ doTextRemoveAndVisit(offset, length, predicate, getEditGroup(predicateEvent));
+ doTextInsert(offset, (ASTNode) predicateEvent.getNewValue(), 0, false, getEditGroup(predicateEvent));
+ pos= offset + length;
+ break;
+ }
+ }
+ return changeKind;
+ }
+ @Override
+ public boolean visit(GuardPredicateDeclaration node) {
+ int pos = node.getStartPosition();
+ boolean isBase = ((Boolean) getOriginalValue(node, GuardPredicateDeclaration.BASE_PROPERTY)).booleanValue();
+ boolean invertBase = isChanged(node, GuardPredicateDeclaration.BASE_PROPERTY);
+ if (invertBase) {
+ if (isBase) {
+ try {
+ getScanner().readToToken(TerminalTokens.TokenNamebase, node.getStartPosition());
+ int start= getScanner().getCurrentStartOffset();
+ int end= getScanner().getCurrentEndOffset();
+ doTextRemove(start, end-start+1, getEditGroup(node, GuardPredicateDeclaration.BASE_PROPERTY));
+ } catch (CoreException e) {
+ // ignore
+ }
+ } else {
+ doTextInsert(pos, "base ", getEditGroup(node, GuardPredicateDeclaration.BASE_PROPERTY)); //$NON-NLS-1$
+ }
+ }
+
+ pos = rewriteRequiredNode(node, GuardPredicateDeclaration.EXPRESSION_PROPERTY);
+
+ return false;
+ }
+
+ @Override
+ public boolean visit(PrecedenceDeclaration node) {
+ RewriteEvent precedencesEvent = getEvent(node, PrecedenceDeclaration.ELEMENTS_PROPERTY);
+ if ( precedencesEvent == null
+ || precedencesEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ doVisit(node, PrecedenceDeclaration.ELEMENTS_PROPERTY, 0);
+ }
+ else
+ {
+ rewriteNodeList(node,
+ PrecedenceDeclaration.ELEMENTS_PROPERTY,
+ 0, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ return false;
+ }
+
+ public boolean visit(CalloutMappingDeclaration node)
+ {
+ if (!hasChildrenChanges(node) && !hasChildrenChanges(node.bindingOperator())) { // bindingOperator is treated as inline
+// System.out.println("visit CalloutMappingDeclaration unchanged");
+ return doVisitUnchangedChildren(node);
+ }
+
+ // javadoc
+ int pos = rewriteJavadoc(node, CalloutMappingDeclaration.JAVADOC_PROPERTY);
+
+ int posAfterJavadoc = pos;
+
+ // annotations?
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("OT/J support for JLS2 is incomplete"); //$NON-NLS-1$
+ } else {
+ pos= rewriteModifiers2(node, CalloutMappingDeclaration.MODIFIERS2_PROPERTY, pos);
+ }
+
+ // left methodSpec
+ pos = rewriteRequiredNode(node, CalloutMappingDeclaration.ROLE_MAPPING_ELEMENT_PROPERTY);
+
+ // callout kind
+ MethodBindingOperator bindingOp = node.bindingOperator();
+ int oldBindingKind= ((Integer) getOriginalValue(bindingOp, MethodBindingOperator.BINDING_KIND_PROPERTY)).intValue();
+ boolean isCalloutOverride = (oldBindingKind == MethodBindingOperator.KIND_CALLOUT_OVERRIDE);
+ int typeToken= isCalloutOverride ? TerminalTokens.TokenNameCALLOUT_OVERRIDE : TerminalTokens.TokenNameBINDOUT;
+ try {
+ getScanner().readToToken(typeToken, node.getStartPosition());
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ pos= getScanner().getCurrentEndOffset();
+
+ boolean invertCalloutKind= isChanged(bindingOp, MethodBindingOperator.BINDING_KIND_PROPERTY);
+ if (invertCalloutKind) {
+ // TODO(jsv) replace with OT constants
+ String str= isCalloutOverride ? "->" : "=>"; //$NON-NLS-1$ //$NON-NLS-2$
+ int start= getScanner().getCurrentStartOffset();
+ int end= getScanner().getCurrentEndOffset();
+
+ doTextReplace(start, end - start, str, getEditGroup(bindingOp, MethodBindingOperator.BINDING_KIND_PROPERTY));
+ }
+
+ // right methodSpec
+ pos = rewriteNode(node, CalloutMappingDeclaration.BASE_MAPPING_ELEMENT_PROPERTY, pos, ASTRewriteFormatter.SPACE);
+
+ // rewrite event
+ RewriteEvent mappingEvent= getEvent(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+
+ // no changes in parameter mappings
+ if (mappingEvent == null || mappingEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ pos = doVisit(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY, pos);
+ if (node.getParameterMappings().isEmpty()) {
+ boolean haveMappings= false;
+ try {
+ if (getScanner().readNext(pos, true) == TerminalTokens.TokenNameSEMICOLON)
+ haveMappings= true; // EMPTY_MAPPINGS ;-)
+ } catch (CoreException e) { /* fall through with haveMappings unset: */ }
+ if (!haveMappings) // ';' not found, insert now:
+ doTextInsert(pos, ";", getEditGroup(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY)); //$NON-NLS-1$
+ }
+ }
+ // changes in parameter mappings
+ else
+ {
+ List newNodes = (List) getNewValue(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+ List origNodes = (List) getOriginalValue(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+
+ if (!newNodes.isEmpty() && origNodes.isEmpty())
+ {
+ // TODO(jsv) format only the with-block with new parameter mapping(s) and not the whole mapping
+ doTextRemove(
+ posAfterJavadoc,
+ (pos-posAfterJavadoc)+1,
+ getEditGroup(node.getParent(),RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY)
+ );
+
+ doTextInsert(
+ posAfterJavadoc,
+ node,
+ getIndent(node.getParent().getStartPosition()) + 1,
+ true,
+ getEditGroup(node.getParent(),RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY)
+ );
+
+ return false;
+ }
+
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ StringBuffer separatorString= new StringBuffer();
+ separatorString.append(',');
+ separatorString.append(getLineDelimiter());
+ separatorString.append(createIndentString(startIndent));
+ pos = rewriteNodeList(
+ node,
+ CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY,
+ pos,
+ "",//$NON-NLS-1$
+ separatorString.toString()
+ );
+
+ // mappings -> no mappings
+ if (newNodes.isEmpty() && !origNodes.isEmpty())
+ {
+ try {
+ getScanner().readToToken(TerminalTokens.TokenNameRBRACE, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+
+ int end = getScanner().getCurrentEndOffset();
+
+ doTextReplace(
+ pos,
+ end - pos,
+ ";", //$NON-NLS-1$
+ getEditGroup(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY)
+ );
+ }
+ }
+
+// System.out.println("visit CalloutMappingDeclaration changed");
+ return false;
+ }
+
+
+ public boolean visit(ParameterMapping node)
+ {
+ if (!hasChildrenChanges(node)) {
+// System.out.println("visit ParameterMapping unchanged");
+ return doVisitUnchangedChildren(node);
+ }
+ @SuppressWarnings("unused")
+ int pos;
+
+
+ if (node.getDirection().equals("->")) //$NON-NLS-1$
+ {
+ pos = rewriteRequiredNode(node, ParameterMapping.EXPRESSION_PROPERTY);
+ pos = rewriteRequiredNode(node, ParameterMapping.IDENTIFIER_PROPERTY);
+ }
+ else
+ {
+ pos = rewriteRequiredNode(node, ParameterMapping.IDENTIFIER_PROPERTY);
+ pos = rewriteRequiredNode(node, ParameterMapping.EXPRESSION_PROPERTY);
+ }
+
+// System.out.println("visit ParameterMapping changed");
+ return false;
+ }
+
+
+ public boolean visit(CallinMappingDeclaration node)
+ {
+ if (!hasChildrenChanges(node) && !hasChildrenChanges(node.bindingOperator())) { // bindingOperator is treated as inline
+ return doVisitUnchangedChildren(node);
+ }
+
+ // javadoc
+ int pos = rewriteJavadoc(node, CallinMappingDeclaration.JAVADOC_PROPERTY);
+ int posAfterJavadoc = pos;
+
+ // annotations?
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("OT/J support for JLS2 is incomplete"); //$NON-NLS-1$
+ } else {
+ pos= rewriteModifiers2(node, CallinMappingDeclaration.MODIFIERS2_PROPERTY, pos);
+ }
+
+ // callin name
+ RewriteEvent event= getEvent(node, CallinMappingDeclaration.NAME_PROPERTY);
+ if (event != null) {
+ boolean inserting = event.getChangeKind() == RewriteEvent.INSERTED;
+ // update pos
+ try {
+ pos= getScanner().getNextStartOffset(pos, false);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ pos= rewriteNode(node, CallinMappingDeclaration.NAME_PROPERTY, pos, ASTRewriteFormatter.NONE);
+ if (inserting)
+ doTextInsert(pos, ": ", getEditGroup(node, CallinMappingDeclaration.NAME_PROPERTY)); //$NON-NLS-1$
+ }
+
+ // role methodSpec
+ pos = rewriteRequiredNode(node, CallinMappingDeclaration.ROLE_MAPPING_ELEMENT_PROPERTY);
+
+ // callin modifier (MISSING_KEYWORD if no valid modifier is given).
+ pos = rewriteRequiredNode(node.bindingOperator(), MethodBindingOperator.BINDING_MODIFIER_PROPERTY);
+
+ // rewrite base method specs
+ RewriteEvent baseMethodSpecsEvent = getEvent(node,
+ CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY);
+ if (baseMethodSpecsEvent == null
+ || baseMethodSpecsEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ pos = doVisit(node,
+ CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY,
+ pos);
+ }
+ else
+ {
+ pos = rewriteNodeList(node,
+ CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY,
+ pos, " ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // optional guard predicate:
+ pos = rewriteNode(node, CallinMappingDeclaration.GUARD_PROPERTY, pos, ASTRewriteFormatter.SPACE);
+
+ // rewrite event
+ RewriteEvent mappingEvent= getEvent(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+
+ // no changes in parameter mappings
+ if (mappingEvent == null || mappingEvent.getChangeKind() == RewriteEvent.UNCHANGED)
+ {
+ pos = doVisit(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY, pos);
+ if (node.getParameterMappings().isEmpty()) {
+ boolean haveMappings= false;
+ try {
+ if (getScanner().readNext(pos, true) == TerminalTokens.TokenNameSEMICOLON)
+ haveMappings= true; // EMPTY_MAPPINGS ;-)
+ } catch (CoreException e) { /* fall through with haveMappings unset: */ }
+ if (!haveMappings) // ';' not found, insert now:
+ doTextInsert(pos, ";", getEditGroup(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY)); //$NON-NLS-1$
+ }
+ }
+ // changes in parameter mappings
+ else
+ {
+ List newNodes = (List) getNewValue(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+ List origNodes = (List) getOriginalValue(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY);
+
+ if (!newNodes.isEmpty() && origNodes.isEmpty())
+ {
+ // TODO(jsv) format only the with-block with new parameter mapping(s) and not the whole mapping
+ doTextRemove(
+ posAfterJavadoc,
+ (pos-posAfterJavadoc)+1,
+ getEditGroup(node.getParent(),RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY)
+ );
+
+ doTextInsert(
+ posAfterJavadoc,
+ node,
+ getIndent(node.getParent().getStartPosition()) + 1,
+ true,
+ getEditGroup(node.getParent(),RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY)
+ );
+
+ return false;
+ }
+
+ int startIndent= getIndent(node.getStartPosition()) + 1;
+ StringBuffer separatorString= new StringBuffer();
+ separatorString.append(',');
+ separatorString.append(getLineDelimiter());
+ separatorString.append(createIndentString(startIndent));
+ pos = rewriteNodeList(
+ node,
+ CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY,
+ pos,
+ "",//$NON-NLS-1$
+ separatorString.toString()
+ );
+
+ // mappings -> no mappings
+ if (newNodes.isEmpty() && !origNodes.isEmpty())
+ {
+ int rBraceToken= TerminalTokens.TokenNameRBRACE;
+ try {
+ getScanner().readToToken(rBraceToken, pos);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+
+ int end = getScanner().getCurrentEndOffset();
+
+ doTextReplace(
+ pos,
+ end - pos,
+ ";", //$NON-NLS-1$
+ getEditGroup(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY)
+ );
+ }
+ }
+
+ return false;
+ }
+
+ public boolean visit(MethodBindingOperator node) {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ boolean changedBindingKind= isChanged(node, MethodBindingOperator.BINDING_KIND_PROPERTY);
+ int pos = node.getStartPosition();
+ if (changedBindingKind) {
+ String str = "";
+ switch ((Integer)this.eventStore.getNewValue(node, MethodBindingOperator.BINDING_KIND_PROPERTY)) {
+ case MethodBindingOperator.KIND_CALLIN : str = CallinMappingDeclaration.CALLIN; break;
+ case MethodBindingOperator.KIND_CALLOUT : str = CalloutMappingDeclaration.CALLOUT; break;
+ case MethodBindingOperator.KIND_CALLOUT_OVERRIDE : str = CalloutMappingDeclaration.CALLOUT_OVERRIDE; break;
+ }
+ doTextReplace(pos, 2, str, getEditGroup(node, MethodBindingOperator.BINDING_KIND_PROPERTY));
+ }
+ if (node.bindingModifier() != null)
+ pos = node.bindingModifier().getStartPosition();
+ else
+ pos+=2;
+ rewriteNode(node, MethodBindingOperator.BINDING_MODIFIER_PROPERTY, pos, ASTRewriteFormatter.NONE);
+ return false;
+ }
+
+ public boolean visit(MethodSpec node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+ int pos= node.getStartPosition();
+ // type parameters
+ if (node.getAST().apiLevel() == AST.JLS3) {
+ pos= rewriteOptionalTypeParameters(node, MethodSpec.TYPE_PARAMETERS_PROPERTY, pos, " ", true, false); //$NON-NLS-1$
+ }
+ // return type
+ rewriteRequiredNode(node, MethodSpec.RETURN_TYPE2_PROPERTY);
+ // method name
+ pos= rewriteRequiredNode(node, MethodSpec.NAME_PROPERTY);
+
+ // parameters
+ try {
+ if (isChanged(node, MethodSpec.PARAMETERS_PROPERTY)) {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ pos= rewriteNodeList(node, MethodSpec.PARAMETERS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ pos= doVisit(node, MethodSpec.PARAMETERS_PROPERTY, pos);
+ }
+ } catch (CoreException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ //FIXME(SH): XXX COMPLETE THESE!!!
+
+ public boolean visit(FieldAccessSpec node)
+ {
+ if (!hasChildrenChanges(node)) {
+// System.out.println("visit FieldAccessSpec unchanged");
+ return doVisitUnchangedChildren(node);
+ }
+// System.out.println("visit FieldAccessSpec changed");
+ return true;
+ }
+
+ public boolean visit(LiftingType node)
+ {
+ if (!hasChildrenChanges(node)) {
+// System.out.println("visit LiftingType unchanged");
+ return doVisitUnchangedChildren(node);
+ }
+// System.out.println("visit LiftingType changed");
+ return true;
+ }
+
+ // FIXME(SH): test these:
+
+ public boolean visit(TypeAnchor node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ rewriteRequiredNode(node, TypeAnchor.PATH_PROPERTY);
+ return false;
+ }
+
+ //  copied from structurally equivalent WhileStatement:
+ public boolean visit(WithinStatement node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteRequiredNode(node, WithinStatement.TEAM_EXPRESSION_PROPERTY);
+
+ try {
+ if (isChanged(node, WithinStatement.BODY_PROPERTY)) {
+ int startOffset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
+ rewriteBodyNode(node, WithinStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.WHILE_BLOCK); // body // FIXME(SH): WITHIN_BLOCK?
+ } else {
+ voidVisit(node, WithinStatement.BODY_PROPERTY);
+ }
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ return false;
+ }
+
+ // copied from structurally equivalent SuperMethodInvocation
+ public boolean visit(TSuperMessageSend node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ int pos= rewriteOptionalQualifier(node, TSuperMessageSend.QUALIFIER_PROPERTY, node.getStartPosition());
+
+ // no type arguments
+
+ pos= rewriteRequiredNode(node, TSuperMessageSend.NAME_PROPERTY);
+
+ if (isChanged(node, TSuperMessageSend.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, TSuperMessageSend.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, TSuperMessageSend.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ // copied from structurally equivalent SuperConstructorInvocation
+ public boolean visit(TSuperConstructorInvocation node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // no qualifying expression
+
+ // no type arguments
+
+ // added for OT:
+ int pos= node.getStartPosition();
+
+ if (isChanged(node, TSuperConstructorInvocation.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, TSuperConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, TSuperConstructorInvocation.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ // copied from structurally equivalent SuperMethodInvocation
+ public boolean visit(BaseCallMessageSend node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // no qualifier
+ int pos= node.getStartPosition();
+
+ // no type arguments
+
+ pos= rewriteRequiredNode(node, BaseCallMessageSend.NAME_PROPERTY);
+
+ if (isChanged(node, BaseCallMessageSend.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, BaseCallMessageSend.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, BaseCallMessageSend.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+
+ // cf. TSuperConstructorInvocation:
+ public boolean visit(BaseConstructorInvocation node)
+ {
+ if (!hasChildrenChanges(node)) {
+ return doVisitUnchangedChildren(node);
+ }
+
+ // no qualifying expression
+
+ // no type arguments
+
+ // added for OT:
+ int pos= node.getStartPosition();
+
+ if (isChanged(node, BaseConstructorInvocation.ARGUMENTS_PROPERTY)) {
+ // eval position after opening parent
+ try {
+ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos);
+ rewriteNodeList(node, BaseConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ } else {
+ voidVisit(node, BaseConstructorInvocation.ARGUMENTS_PROPERTY);
+ }
+ return false;
+ }
+//jsv}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
new file mode 100644
index 000000000..1f6d9a06f
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
@@ -0,0 +1,1754 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTRewriteFlattener.java 23214 2010-01-07 19:51:00Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ASTRewriteFlattener extends ASTVisitor {
+
+ /**
+ * Internal synonynm for deprecated constant AST.JSL2
+ * to alleviate deprecation warnings.
+ * @deprecated
+ */
+ /*package*/ static final int JLS2_INTERNAL = AST.JLS2;
+
+ public static String asString(ASTNode node, RewriteEventStore store) {
+ ASTRewriteFlattener flattener= new ASTRewriteFlattener(store);
+ node.accept(flattener);
+ return flattener.getResult();
+ }
+
+ protected StringBuffer result;
+ private RewriteEventStore store;
+
+ public ASTRewriteFlattener(RewriteEventStore store) {
+ this.store= store;
+ this.result= new StringBuffer();
+ }
+
+ /**
+ * Returns the string accumulated in the visit.
+ *
+ * @return the serialized
+ */
+ public String getResult() {
+ // convert to a string, but lose any extra space in the string buffer by copying
+ return new String(this.result.toString());
+ }
+
+ /**
+ * Resets this printer so that it can be used again.
+ */
+ public void reset() {
+ this.result.setLength(0);
+ }
+
+ /**
+ * Appends the text representation of the given modifier flags, followed by a single space.
+ *
+ * @param modifiers the modifiers
+ * @param buf The <code>StringBuffer</code> to write the result to.
+ */
+ public static void printModifiers(int modifiers, StringBuffer buf) {
+ if (Modifier.isPublic(modifiers)) {
+ buf.append("public "); //$NON-NLS-1$
+ }
+ if (Modifier.isProtected(modifiers)) {
+ buf.append("protected "); //$NON-NLS-1$
+ }
+ if (Modifier.isPrivate(modifiers)) {
+ buf.append("private "); //$NON-NLS-1$
+ }
+ if (Modifier.isStatic(modifiers)) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+ if (Modifier.isAbstract(modifiers)) {
+ buf.append("abstract "); //$NON-NLS-1$
+ }
+ if (Modifier.isFinal(modifiers)) {
+ buf.append("final "); //$NON-NLS-1$
+ }
+ if (Modifier.isSynchronized(modifiers)) {
+ buf.append("synchronized "); //$NON-NLS-1$
+ }
+ if (Modifier.isVolatile(modifiers)) {
+ buf.append("volatile "); //$NON-NLS-1$
+ }
+ if (Modifier.isNative(modifiers)) {
+ buf.append("native "); //$NON-NLS-1$
+ }
+ if (Modifier.isStrictfp(modifiers)) {
+ buf.append("strictfp "); //$NON-NLS-1$
+ }
+ if (Modifier.isTransient(modifiers)) {
+ buf.append("transient "); //$NON-NLS-1$
+ }
+
+//{ObjectTeams: printModifier for OT-specific modifiers
+ if (Modifier.isReplace(modifiers))
+ {
+ buf.append("replace "); //$NON-NLS-1$
+ }
+ if (Modifier.isBefore(modifiers))
+ {
+ buf.append("before "); //$NON-NLS-1$
+ }
+ if (Modifier.isAfter(modifiers))
+ {
+ buf.append("after "); //$NON-NLS-1$
+ }
+ if (Modifier.isGet(modifiers))
+ {
+ buf.append("get "); //$NON-NLS-1$
+ }
+ if (Modifier.isSet(modifiers))
+ {
+ buf.append("set "); //$NON-NLS-1$
+ }
+ if (Modifier.isTeam(modifiers))
+ {
+ buf.append("team "); //$NON-NLS-1$
+ }
+ if (Modifier.isCallin(modifiers))
+ {
+ buf.append("callin "); //$NON-NLS-1$
+ }
+// jsv}
+
+ }
+
+ protected List getChildList(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ return (List) getAttribute(parent, childProperty);
+ }
+
+ protected ASTNode getChildNode(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ return (ASTNode) getAttribute(parent, childProperty);
+ }
+
+ protected int getIntAttribute(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ return ((Integer) getAttribute(parent, childProperty)).intValue();
+ }
+
+ protected boolean getBooleanAttribute(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ return ((Boolean) getAttribute(parent, childProperty)).booleanValue();
+ }
+
+ protected Object getAttribute(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ return this.store.getNewValue(parent, childProperty);
+ }
+
+ protected void visitList(ASTNode parent, StructuralPropertyDescriptor childProperty, String separator) {
+ List list= getChildList(parent, childProperty);
+ for (int i= 0; i < list.size(); i++) {
+ if (separator != null && i > 0) {
+ this.result.append(separator);
+ }
+ ((ASTNode) list.get(i)).accept(this);
+ }
+ }
+
+ protected void visitList(ASTNode parent, StructuralPropertyDescriptor childProperty, String separator, String lead, String post) {
+ List list= getChildList(parent, childProperty);
+ if (!list.isEmpty()) {
+ this.result.append(lead);
+ for (int i= 0; i < list.size(); i++) {
+ if (separator != null && i > 0) {
+ this.result.append(separator);
+ }
+ ((ASTNode) list.get(i)).accept(this);
+ }
+ this.result.append(post);
+ }
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(AnonymousClassDeclaration)
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ this.result.append('{');
+ visitList(node, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY, null);
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayAccess)
+ */
+ public boolean visit(ArrayAccess node) {
+ getChildNode(node, ArrayAccess.ARRAY_PROPERTY).accept(this);
+ this.result.append('[');
+ getChildNode(node, ArrayAccess.INDEX_PROPERTY).accept(this);
+ this.result.append(']');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayCreation)
+ */
+ public boolean visit(ArrayCreation node) {
+ this.result.append("new "); //$NON-NLS-1$
+ ArrayType arrayType= (ArrayType) getChildNode(node, ArrayCreation.TYPE_PROPERTY);
+
+ // get the element type and count dimensions
+ Type elementType= (Type) getChildNode(arrayType, ArrayType.COMPONENT_TYPE_PROPERTY);
+ int dimensions= 1; // always include this array type
+ while (elementType.isArrayType()) {
+ dimensions++;
+ elementType = (Type) getChildNode(elementType, ArrayType.COMPONENT_TYPE_PROPERTY);
+ }
+
+ elementType.accept(this);
+
+ List list= getChildList(node, ArrayCreation.DIMENSIONS_PROPERTY);
+ for (int i= 0; i < list.size(); i++) {
+ this.result.append('[');
+ ((ASTNode) list.get(i)).accept(this);
+ this.result.append(']');
+ dimensions--;
+ }
+
+ // add empty "[]" for each extra array dimension
+ for (int i= 0; i < dimensions; i++) {
+ this.result.append("[]"); //$NON-NLS-1$
+ }
+ ASTNode initializer= getChildNode(node, ArrayCreation.INITIALIZER_PROPERTY);
+ if (initializer != null) {
+ getChildNode(node, ArrayCreation.INITIALIZER_PROPERTY).accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayInitializer)
+ */
+ public boolean visit(ArrayInitializer node) {
+ this.result.append('{');
+ visitList(node, ArrayInitializer.EXPRESSIONS_PROPERTY, String.valueOf(','));
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayType)
+ */
+ public boolean visit(ArrayType node) {
+ getChildNode(node, ArrayType.COMPONENT_TYPE_PROPERTY).accept(this);
+ this.result.append("[]"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(AssertStatement)
+ */
+ public boolean visit(AssertStatement node) {
+ this.result.append("assert "); //$NON-NLS-1$
+ getChildNode(node, AssertStatement.EXPRESSION_PROPERTY).accept(this);
+
+ ASTNode message= getChildNode(node, AssertStatement.MESSAGE_PROPERTY);
+ if (message != null) {
+ this.result.append(':');
+ message.accept(this);
+ }
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Assignment)
+ */
+ public boolean visit(Assignment node) {
+ getChildNode(node, Assignment.LEFT_HAND_SIDE_PROPERTY).accept(this);
+ this.result.append(getAttribute(node, Assignment.OPERATOR_PROPERTY).toString());
+ getChildNode(node, Assignment.RIGHT_HAND_SIDE_PROPERTY).accept(this);
+ return false;
+ }
+
+
+
+ /*
+ * @see ASTVisitor#visit(Block)
+ */
+ public boolean visit(Block node) {
+ this.result.append('{');
+ visitList(node, Block.STATEMENTS_PROPERTY, null);
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BooleanLiteral)
+ */
+ public boolean visit(BooleanLiteral node) {
+ if (node.booleanValue() == true) {
+ this.result.append("true"); //$NON-NLS-1$
+ } else {
+ this.result.append("false"); //$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BreakStatement)
+ */
+ public boolean visit(BreakStatement node) {
+ this.result.append("break"); //$NON-NLS-1$
+ ASTNode label= getChildNode(node, BreakStatement.LABEL_PROPERTY);
+ if (label != null) {
+ this.result.append(' ');
+ label.accept(this);
+ }
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CastExpression)
+ */
+ public boolean visit(CastExpression node) {
+ this.result.append('(');
+ getChildNode(node, CastExpression.TYPE_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, CastExpression.EXPRESSION_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CatchClause)
+ */
+ public boolean visit(CatchClause node) {
+ this.result.append("catch ("); //$NON-NLS-1$
+ getChildNode(node, CatchClause.EXCEPTION_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, CatchClause.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CharacterLiteral)
+ */
+ public boolean visit(CharacterLiteral node) {
+ this.result.append(getAttribute(node, CharacterLiteral.ESCAPED_VALUE_PROPERTY));
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ClassInstanceCreation)
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ ASTNode expression= getChildNode(node, ClassInstanceCreation.EXPRESSION_PROPERTY);
+ if (expression != null) {
+ expression.accept(this);
+ this.result.append('.');
+ }
+ this.result.append("new ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ getChildNode(node, ClassInstanceCreation.NAME_PROPERTY).accept(this);
+ } else {
+ visitList(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ getChildNode(node, ClassInstanceCreation.TYPE_PROPERTY).accept(this);
+ }
+
+ this.result.append('(');
+ visitList(node, ClassInstanceCreation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ ASTNode decl= getChildNode(node, ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ if (decl != null) {
+ decl.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CompilationUnit)
+ */
+ public boolean visit(CompilationUnit node) {
+ ASTNode pack= getChildNode(node, CompilationUnit.PACKAGE_PROPERTY);
+ if (pack != null) {
+ pack.accept(this);
+ }
+ visitList(node, CompilationUnit.IMPORTS_PROPERTY, null);
+ visitList(node, CompilationUnit.TYPES_PROPERTY, null);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConditionalExpression)
+ */
+ public boolean visit(ConditionalExpression node) {
+ getChildNode(node, ConditionalExpression.EXPRESSION_PROPERTY).accept(this);
+ this.result.append('?');
+ getChildNode(node, ConditionalExpression.THEN_EXPRESSION_PROPERTY).accept(this);
+ this.result.append(':');
+ getChildNode(node, ConditionalExpression.ELSE_EXPRESSION_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConstructorInvocation)
+ */
+ public boolean visit(ConstructorInvocation node) {
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ visitList(node, ConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+ this.result.append("this("); //$NON-NLS-1$
+ visitList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(");"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ContinueStatement)
+ */
+ public boolean visit(ContinueStatement node) {
+ this.result.append("continue"); //$NON-NLS-1$
+ ASTNode label= getChildNode(node, ContinueStatement.LABEL_PROPERTY);
+ if (label != null) {
+ this.result.append(' ');
+ label.accept(this);
+ }
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(DoStatement)
+ */
+ public boolean visit(DoStatement node) {
+ this.result.append("do "); //$NON-NLS-1$
+ getChildNode(node, DoStatement.BODY_PROPERTY).accept(this);
+ this.result.append(" while ("); //$NON-NLS-1$
+ getChildNode(node, DoStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(");"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EmptyStatement)
+ */
+ public boolean visit(EmptyStatement node) {
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ExpressionStatement)
+ */
+ public boolean visit(ExpressionStatement node) {
+ getChildNode(node, ExpressionStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldAccess)
+ */
+ public boolean visit(FieldAccess node) {
+ getChildNode(node, FieldAccess.EXPRESSION_PROPERTY).accept(this);
+ this.result.append('.');
+ getChildNode(node, FieldAccess.NAME_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldDeclaration)
+ */
+ public boolean visit(FieldDeclaration node) {
+ ASTNode javadoc= getChildNode(node, FieldDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, FieldDeclaration.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, FieldDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ getChildNode(node, FieldDeclaration.TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ visitList(node, FieldDeclaration.FRAGMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ForStatement)
+ */
+ public boolean visit(ForStatement node) {
+ this.result.append("for ("); //$NON-NLS-1$
+ visitList(node, ForStatement.INITIALIZERS_PROPERTY, String.valueOf(','));
+ this.result.append(';');
+ ASTNode expression= getChildNode(node, ForStatement.EXPRESSION_PROPERTY);
+ if (expression != null) {
+ expression.accept(this);
+ }
+ this.result.append(';');
+ visitList(node, ForStatement.UPDATERS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ getChildNode(node, ForStatement.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(IfStatement)
+ */
+ public boolean visit(IfStatement node) {
+ this.result.append("if ("); //$NON-NLS-1$
+ getChildNode(node, IfStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, IfStatement.THEN_STATEMENT_PROPERTY).accept(this);
+ ASTNode elseStatement= getChildNode(node, IfStatement.ELSE_STATEMENT_PROPERTY);
+ if (elseStatement != null) {
+ this.result.append(" else "); //$NON-NLS-1$
+ elseStatement.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ImportDeclaration)
+ */
+ public boolean visit(ImportDeclaration node) {
+ this.result.append("import "); //$NON-NLS-1$
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (getBooleanAttribute(node, ImportDeclaration.STATIC_PROPERTY)) {
+ this.result.append("static ");//$NON-NLS-1$
+ }
+//{ObjectTeams: one more modifier:
+ if (getBooleanAttribute(node, ImportDeclaration.BASE_PROPERTY)) {
+ this.result.append("base ");//$NON-NLS-1$
+ }
+// SH}
+ }
+ getChildNode(node, ImportDeclaration.NAME_PROPERTY).accept(this);
+ if (getBooleanAttribute(node, ImportDeclaration.ON_DEMAND_PROPERTY)) {
+ this.result.append(".*"); //$NON-NLS-1$
+ }
+ this.result.append(';');
+ return false;
+ }
+
+
+
+ /*
+ * @see ASTVisitor#visit(InfixExpression)
+ */
+ public boolean visit(InfixExpression node) {
+ getChildNode(node, InfixExpression.LEFT_OPERAND_PROPERTY).accept(this);
+ this.result.append(' ');
+ String operator= getAttribute(node, InfixExpression.OPERATOR_PROPERTY).toString();
+
+ this.result.append(operator);
+ this.result.append(' ');
+ getChildNode(node, InfixExpression.RIGHT_OPERAND_PROPERTY).accept(this);
+
+ List list= getChildList(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
+ for (int i= 0; i < list.size(); i++) {
+ this.result.append(operator);
+ ((ASTNode) list.get(i)).accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(InstanceofExpression)
+ */
+ public boolean visit(InstanceofExpression node) {
+ getChildNode(node, InstanceofExpression.LEFT_OPERAND_PROPERTY).accept(this);
+ this.result.append(" instanceof "); //$NON-NLS-1$
+ getChildNode(node, InstanceofExpression.RIGHT_OPERAND_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Initializer)
+ */
+ public boolean visit(Initializer node) {
+ ASTNode javadoc= getChildNode(node, Initializer.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, Initializer.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, Initializer.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ getChildNode(node, Initializer.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Javadoc)
+ */
+ public boolean visit(Javadoc node) {
+ this.result.append("/**"); //$NON-NLS-1$
+ List list= getChildList(node, Javadoc.TAGS_PROPERTY);
+ for (int i= 0; i < list.size(); i++) {
+ this.result.append("\n * "); //$NON-NLS-1$
+ ((ASTNode) list.get(i)).accept(this);
+ }
+ this.result.append("\n */"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LabeledStatement)
+ */
+ public boolean visit(LabeledStatement node) {
+ getChildNode(node, LabeledStatement.LABEL_PROPERTY).accept(this);
+ this.result.append(": "); //$NON-NLS-1$
+ getChildNode(node, LabeledStatement.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodDeclaration)
+ */
+ public boolean visit(MethodDeclaration node) {
+ ASTNode javadoc= getChildNode(node, MethodDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, MethodDeclaration.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, MethodDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ visitList(node, MethodDeclaration.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+
+ if (!getBooleanAttribute(node, MethodDeclaration.CONSTRUCTOR_PROPERTY)) {
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ getChildNode(node, MethodDeclaration.RETURN_TYPE_PROPERTY).accept(this);
+ } else {
+ ASTNode returnType = getChildNode(node, MethodDeclaration.RETURN_TYPE2_PROPERTY);
+ if (returnType != null) {
+ returnType.accept(this);
+ } else {
+ // methods really ought to have a return type
+ this.result.append("void");//$NON-NLS-1$
+ }
+ }
+ this.result.append(' ');
+ }
+ getChildNode(node, MethodDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, MethodDeclaration.PARAMETERS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ int extraDims= getIntAttribute(node, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY);
+ for (int i = 0; i < extraDims; i++) {
+ this.result.append("[]"); //$NON-NLS-1$
+ }
+ visitList(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY, String.valueOf(','), " throws ", Util.EMPTY_STRING); //$NON-NLS-1$
+//{ObjectTeams: predicate
+ ASTNode guardPredicate = getChildNode(node, MethodDeclaration.GUARD_PROPERTY);
+ if (guardPredicate != null) {
+ guardPredicate.accept(this);
+ this.result.append(' ');
+ }
+// SH}
+ ASTNode body= getChildNode(node, MethodDeclaration.BODY_PROPERTY);
+ if (body == null) {
+ this.result.append(';');
+ } else {
+ body.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MethodInvocation)
+ */
+ public boolean visit(MethodInvocation node) {
+ ASTNode expression= getChildNode(node, MethodInvocation.EXPRESSION_PROPERTY);
+ if (expression != null) {
+ expression.accept(this);
+ this.result.append('.');
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ visitList(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+
+ getChildNode(node, MethodInvocation.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, MethodInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NullLiteral)
+ */
+ public boolean visit(NullLiteral node) {
+ this.result.append("null"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NumberLiteral)
+ */
+ public boolean visit(NumberLiteral node) {
+ this.result.append(getAttribute(node, NumberLiteral.TOKEN_PROPERTY).toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PackageDeclaration)
+ */
+ public boolean visit(PackageDeclaration node) {
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ ASTNode javadoc = getChildNode(node, PackageDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ visitList(node, PackageDeclaration.ANNOTATIONS_PROPERTY, String.valueOf(' '));
+ }
+ this.result.append("package "); //$NON-NLS-1$
+ getChildNode(node, PackageDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ParenthesizedExpression)
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ this.result.append('(');
+ getChildNode(node, ParenthesizedExpression.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PostfixExpression)
+ */
+ public boolean visit(PostfixExpression node) {
+ getChildNode(node, PostfixExpression.OPERAND_PROPERTY).accept(this);
+ this.result.append(getAttribute(node, PostfixExpression.OPERATOR_PROPERTY).toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrefixExpression)
+ */
+ public boolean visit(PrefixExpression node) {
+ this.result.append(getAttribute(node, PrefixExpression.OPERATOR_PROPERTY).toString());
+ getChildNode(node, PrefixExpression.OPERAND_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrimitiveType)
+ */
+ public boolean visit(PrimitiveType node) {
+ this.result.append(getAttribute(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY).toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedName)
+ */
+ public boolean visit(QualifiedName node) {
+ getChildNode(node, QualifiedName.QUALIFIER_PROPERTY).accept(this);
+ this.result.append('.');
+ getChildNode(node, QualifiedName.NAME_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ReturnStatement)
+ */
+ public boolean visit(ReturnStatement node) {
+ this.result.append("return"); //$NON-NLS-1$
+ ASTNode expression= getChildNode(node, ReturnStatement.EXPRESSION_PROPERTY);
+ if (expression != null) {
+ this.result.append(' ');
+ expression.accept(this);
+ }
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleName)
+ */
+ public boolean visit(SimpleName node) {
+ this.result.append(getAttribute(node, SimpleName.IDENTIFIER_PROPERTY));
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleType)
+ */
+ public boolean visit(SimpleType node) {
+ return true;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SingleVariableDeclaration)
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, SingleVariableDeclaration.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ getChildNode(node, SingleVariableDeclaration.TYPE_PROPERTY).accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (getBooleanAttribute(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
+ this.result.append("...");//$NON-NLS-1$
+ }
+ }
+ this.result.append(' ');
+ getChildNode(node, SingleVariableDeclaration.NAME_PROPERTY).accept(this);
+ int extraDimensions= getIntAttribute(node, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY);
+ for (int i = 0; i < extraDimensions; i++) {
+ this.result.append("[]"); //$NON-NLS-1$
+ }
+ ASTNode initializer= getChildNode(node, SingleVariableDeclaration.INITIALIZER_PROPERTY);
+ if (initializer != null) {
+ this.result.append('=');
+ initializer.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(StringLiteral)
+ */
+ public boolean visit(StringLiteral node) {
+ this.result.append(getAttribute(node, StringLiteral.ESCAPED_VALUE_PROPERTY));
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperConstructorInvocation)
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ ASTNode expression= getChildNode(node, SuperConstructorInvocation.EXPRESSION_PROPERTY);
+ if (expression != null) {
+ expression.accept(this);
+ this.result.append('.');
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ visitList(node, SuperConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+ this.result.append("super("); //$NON-NLS-1$
+ visitList(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(");"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperFieldAccess)
+ */
+ public boolean visit(SuperFieldAccess node) {
+ ASTNode qualifier= getChildNode(node, SuperFieldAccess.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ this.result.append('.');
+ }
+ this.result.append("super."); //$NON-NLS-1$
+ getChildNode(node, SuperFieldAccess.NAME_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperMethodInvocation)
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ ASTNode qualifier= getChildNode(node, SuperMethodInvocation.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ this.result.append('.');
+ }
+ this.result.append("super."); //$NON-NLS-1$
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ visitList(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+ getChildNode(node, SuperMethodInvocation.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, SuperMethodInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchCase)
+ */
+ public boolean visit(SwitchCase node) {
+ ASTNode expression= getChildNode(node, SwitchCase.EXPRESSION_PROPERTY);
+ if (expression == null) {
+ this.result.append("default"); //$NON-NLS-1$
+ } else {
+ this.result.append("case "); //$NON-NLS-1$
+ expression.accept(this);
+ }
+ this.result.append(':');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchStatement)
+ */
+ public boolean visit(SwitchStatement node) {
+ this.result.append("switch ("); //$NON-NLS-1$
+ getChildNode(node, SwitchStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ this.result.append('{');
+ visitList(node, SwitchStatement.STATEMENTS_PROPERTY, null);
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SynchronizedStatement)
+ */
+ public boolean visit(SynchronizedStatement node) {
+ this.result.append("synchronized ("); //$NON-NLS-1$
+ getChildNode(node, SynchronizedStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, SynchronizedStatement.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThisExpression)
+ */
+ public boolean visit(ThisExpression node) {
+ ASTNode qualifier= getChildNode(node, ThisExpression.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ this.result.append('.');
+ }
+ this.result.append("this"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThrowStatement)
+ */
+ public boolean visit(ThrowStatement node) {
+ this.result.append("throw "); //$NON-NLS-1$
+ getChildNode(node, ThrowStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TryStatement)
+ */
+ public boolean visit(TryStatement node) {
+ this.result.append("try "); //$NON-NLS-1$
+ getChildNode(node, TryStatement.BODY_PROPERTY).accept(this);
+ this.result.append(' ');
+ visitList(node, TryStatement.CATCH_CLAUSES_PROPERTY, null);
+ ASTNode finallyClause= getChildNode(node, TryStatement.FINALLY_PROPERTY);
+ if (finallyClause != null) {
+ this.result.append(" finally "); //$NON-NLS-1$
+ finallyClause.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclaration)
+ */
+ public boolean visit(TypeDeclaration node) {
+ int apiLevel= node.getAST().apiLevel();
+
+ ASTNode javadoc= getChildNode(node, TypeDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+
+ if (apiLevel == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, TypeDeclaration.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, TypeDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+
+ boolean isInterface= getBooleanAttribute(node, TypeDeclaration.INTERFACE_PROPERTY);
+ this.result.append(isInterface ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+ getChildNode(node, TypeDeclaration.NAME_PROPERTY).accept(this);
+ if (apiLevel >= AST.JLS3) {
+ visitList(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>'));
+ }
+
+ this.result.append(' ');
+
+ ChildPropertyDescriptor superClassProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPERCLASS_PROPERTY : TypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
+ ASTNode superclass= getChildNode(node, superClassProperty);
+ if (superclass != null) {
+ this.result.append("extends "); //$NON-NLS-1$
+ superclass.accept(this);
+ this.result.append(' ');
+ }
+
+ ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPER_INTERFACES_PROPERTY : TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
+ String lead= isInterface ? "extends " : "implements "; //$NON-NLS-1$//$NON-NLS-2$
+ visitList(node, superInterfaceProperty, String.valueOf(','), lead, Util.EMPTY_STRING);
+//{ObjectTeams: predicate
+ ASTNode guardPredicate = getChildNode(node, TypeDeclaration.GUARD_PROPERTY);
+ if (guardPredicate != null) {
+ guardPredicate.accept(this);
+ this.result.append(' ');
+ }
+// SH}
+ this.result.append('{');
+ visitList(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY, null);
+//{ObjectTeams: precedence
+ visitList(node, TypeDeclaration.PRECEDENCE_PROPERTY, null);
+// SH}
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclarationStatement)
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ getChildNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY).accept(this);
+ } else {
+ getChildNode(node, TypeDeclarationStatement.DECLARATION_PROPERTY).accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeLiteral)
+ */
+ public boolean visit(TypeLiteral node) {
+ getChildNode(node, TypeLiteral.TYPE_PROPERTY).accept(this);
+ this.result.append(".class"); //$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationExpression)
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, VariableDeclarationExpression.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, VariableDeclarationExpression.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ getChildNode(node, VariableDeclarationExpression.TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ visitList(node, VariableDeclarationExpression.FRAGMENTS_PROPERTY, String.valueOf(','));
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationFragment)
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ getChildNode(node, VariableDeclarationFragment.NAME_PROPERTY).accept(this);
+ int extraDimensions= getIntAttribute(node, VariableDeclarationFragment.EXTRA_DIMENSIONS_PROPERTY);
+ for (int i = 0; i < extraDimensions; i++) {
+ this.result.append("[]"); //$NON-NLS-1$
+ }
+ ASTNode initializer= getChildNode(node, VariableDeclarationFragment.INITIALIZER_PROPERTY);
+ if (initializer != null) {
+ this.result.append('=');
+ initializer.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationStatement)
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, VariableDeclarationStatement.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, VariableDeclarationStatement.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ getChildNode(node, VariableDeclarationStatement.TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ visitList(node, VariableDeclarationStatement.FRAGMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(WhileStatement)
+ */
+ public boolean visit(WhileStatement node) {
+ this.result.append("while ("); //$NON-NLS-1$
+ getChildNode(node, WhileStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, WhileStatement.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BlockComment)
+ */
+ public boolean visit(BlockComment node) {
+ return false; // cant flatten, needs source
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LineComment)
+ */
+ public boolean visit(LineComment node) {
+ return false; // cant flatten, needs source
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
+ */
+ public boolean visit(MemberRef node) {
+ ASTNode qualifier= getChildNode(node, MemberRef.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ }
+ this.result.append('#');
+ getChildNode(node, MemberRef.NAME_PROPERTY).accept(this);
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
+ */
+ public boolean visit(MethodRef node) {
+ ASTNode qualifier= getChildNode(node, MethodRef.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ }
+ this.result.append('#');
+ getChildNode(node, MethodRef.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, MethodRef.PARAMETERS_PROPERTY, ","); //$NON-NLS-1$
+ this.result.append(')');
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
+ */
+ public boolean visit(MethodRefParameter node) {
+ getChildNode(node, MethodRefParameter.TYPE_PROPERTY).accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (getBooleanAttribute(node, MethodRefParameter.VARARGS_PROPERTY)) {
+ this.result.append("..."); //$NON-NLS-1$
+ }
+ }
+ ASTNode name= getChildNode(node, MethodRefParameter.NAME_PROPERTY);
+ if (name != null) {
+ this.result.append(' ');
+ name.accept(this);
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
+ */
+ public boolean visit(TagElement node) {
+ Object tagName= getAttribute(node, TagElement.TAG_NAME_PROPERTY);
+ if (tagName != null) {
+ this.result.append((String) tagName);
+ }
+ List list= getChildList(node, TagElement.FRAGMENTS_PROPERTY);
+ for (int i= 0; i < list.size(); i++) {
+ if (i > 0 || tagName != null) {
+ this.result.append(' ');
+ }
+ ASTNode curr= (ASTNode) list.get(i);
+ if (curr instanceof TagElement) {
+ this.result.append('{');
+ curr.accept(this);
+ this.result.append('}');
+ } else {
+ curr.accept(this);
+ }
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
+ */
+ public boolean visit(TextElement node) {
+ this.result.append(getAttribute(node, TextElement.TEXT_PROPERTY));
+ return false;
+ }
+ /*
+ * @see ASTVisitor#visit(AnnotationTypeDeclaration)
+ * @since 3.0
+ */
+ public boolean visit(AnnotationTypeDeclaration node) {
+ ASTNode javadoc= getChildNode(node, AnnotationTypeDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ visitList(node, AnnotationTypeDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ this.result.append("@interface ");//$NON-NLS-1$
+ getChildNode(node, AnnotationTypeDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append('{');
+ visitList(node, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY, Util.EMPTY_STRING);
+ this.result.append('}');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(AnnotationTypeMemberDeclaration)
+ * @since 3.0
+ */
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ ASTNode javadoc= getChildNode(node, AnnotationTypeMemberDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ visitList(node, AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ getChildNode(node, AnnotationTypeMemberDeclaration.TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ getChildNode(node, AnnotationTypeMemberDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append("()");//$NON-NLS-1$
+ ASTNode def= getChildNode(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY);
+ if (def != null) {
+ this.result.append(" default ");//$NON-NLS-1$
+ def.accept(this);
+ }
+ this.result.append(';');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnhancedForStatement)
+ * @since 3.0
+ */
+ public boolean visit(EnhancedForStatement node) {
+ this.result.append("for (");//$NON-NLS-1$
+ getChildNode(node, EnhancedForStatement.PARAMETER_PROPERTY).accept(this);
+ this.result.append(':');
+ getChildNode(node, EnhancedForStatement.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(')');
+ getChildNode(node, EnhancedForStatement.BODY_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnumConstantDeclaration)
+ * @since 3.0
+ */
+ public boolean visit(EnumConstantDeclaration node) {
+ ASTNode javadoc= getChildNode(node, EnumConstantDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ visitList(node, EnumConstantDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ getChildNode(node, EnumConstantDeclaration.NAME_PROPERTY).accept(this);
+ visitList(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, String.valueOf(','), String.valueOf('('), String.valueOf(')'));
+ ASTNode classDecl= getChildNode(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ if (classDecl != null) {
+ classDecl.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnumDeclaration)
+ * @since 3.0
+ */
+ public boolean visit(EnumDeclaration node) {
+ ASTNode javadoc= getChildNode(node, EnumDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+ visitList(node, EnumDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ this.result.append("enum ");//$NON-NLS-1$
+ getChildNode(node, EnumDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append(' ');
+ visitList(node, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, String.valueOf(','), "implements ", Util.EMPTY_STRING); //$NON-NLS-1$
+
+ this.result.append('{');
+ visitList(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY, String.valueOf(','), Util.EMPTY_STRING, Util.EMPTY_STRING);
+ visitList(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY, Util.EMPTY_STRING, String.valueOf(';'), Util.EMPTY_STRING);
+ this.result.append('}');
+ return false;
+ }
+ /*
+ * @see ASTVisitor#visit(MarkerAnnotation)
+ * @since 3.0
+ */
+ public boolean visit(MarkerAnnotation node) {
+ this.result.append('@');
+ getChildNode(node, MarkerAnnotation.TYPE_NAME_PROPERTY).accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MemberValuePair)
+ * @since 3.0
+ */
+ public boolean visit(MemberValuePair node) {
+ getChildNode(node, MemberValuePair.NAME_PROPERTY).accept(this);
+ this.result.append('=');
+ getChildNode(node, MemberValuePair.VALUE_PROPERTY).accept(this);
+ return false;
+ }
+ /*
+ * @see ASTVisitor#visit(Modifier)
+ * @since 3.0
+ */
+ public boolean visit(Modifier node) {
+ this.result.append(getAttribute(node, Modifier.KEYWORD_PROPERTY).toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NormalAnnotation)
+ * @since 3.0
+ */
+ public boolean visit(NormalAnnotation node) {
+ this.result.append('@');
+ getChildNode(node, NormalAnnotation.TYPE_NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, NormalAnnotation.VALUES_PROPERTY, ", "); //$NON-NLS-1$
+ this.result.append(')');
+ return false;
+ }
+ /*
+ * @see ASTVisitor#visit(ParameterizedType)
+ * @since 3.0
+ */
+ public boolean visit(ParameterizedType node) {
+ getChildNode(node, ParameterizedType.TYPE_PROPERTY).accept(this);
+ this.result.append('<');
+ visitList(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, ", "); //$NON-NLS-1$
+ this.result.append('>');
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedType)
+ * @since 3.0
+ */
+ public boolean visit(QualifiedType node) {
+ getChildNode(node, QualifiedType.QUALIFIER_PROPERTY).accept(this);
+ this.result.append('.');
+ getChildNode(node, QualifiedType.NAME_PROPERTY).accept(this);
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
+ */
+ public boolean visit(SingleMemberAnnotation node) {
+ this.result.append('@');
+ getChildNode(node, SingleMemberAnnotation.TYPE_NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ getChildNode(node, SingleMemberAnnotation.VALUE_PROPERTY).accept(this);
+ this.result.append(')');
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
+ */
+ public boolean visit(TypeParameter node) {
+ getChildNode(node, TypeParameter.NAME_PROPERTY).accept(this);
+//{ObjectTeams: <B base R>:
+ if (node.hasBaseBound())
+ visitList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, " & ", " base ", Util.EMPTY_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ else
+// SH}
+ visitList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, " & ", " extends ", Util.EMPTY_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
+ */
+ public boolean visit(WildcardType node) {
+ this.result.append('?');
+ ASTNode bound = getChildNode(node, WildcardType.BOUND_PROPERTY);
+ if (bound != null) {
+ if (getBooleanAttribute(node, WildcardType.UPPER_BOUND_PROPERTY)) {
+ this.result.append(" extends ");//$NON-NLS-1$
+ } else {
+ this.result.append(" super ");//$NON-NLS-1$
+ }
+ bound.accept(this);
+ }
+ return false;
+ }
+//{ObjectTeams: visit methods for OT-specific types
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldAccessSpec)
+ */
+ public boolean visit(FieldAccessSpec node)
+ {
+ if (node.hasSignature())
+ {
+ getChildNode(node, FieldAccessSpec.FIELD_TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ }
+
+ getChildNode(node, FieldAccessSpec.NAME_PROPERTY).accept(this);
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodSpec)
+ */
+ public boolean visit(MethodSpec node)
+ {
+ if (node.hasSignature())
+ {
+ if(node.getAST().apiLevel() == AST.JLS3) {
+ visitList(node, MethodSpec.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), " >"); //$NON-NLS-1$
+ getChildNode(node, MethodSpec.RETURN_TYPE2_PROPERTY).accept(this);
+ } else {
+ getChildNode(node, MethodSpec.RETURN_TYPE_PROPERTY).accept(this);
+ }
+ if (getBooleanAttribute(node, MethodSpec.COVARIANT_RETURN_PROPERTY))
+ this.result.append('+');
+ this.result.append(' ');
+ }
+
+ getChildNode(node, MethodSpec.NAME_PROPERTY).accept(this);
+
+ if (node.hasSignature())
+ {
+ this.result.append('(');
+ visitList(node, MethodSpec.PARAMETERS_PROPERTY, ", "); //$NON-NLS-1$
+ this.result.append(')');
+ }
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CalloutMappingDeclaration)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(CalloutMappingDeclaration node)
+ {
+ ASTNode javadoc= getChildNode(node, CalloutMappingDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+
+ visitList(node, CalloutMappingDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+
+ ASTNode roleMappingElement = getChildNode(node, CalloutMappingDeclaration.ROLE_MAPPING_ELEMENT_PROPERTY);
+ ASTNode baseMappingElement = getChildNode(node, CalloutMappingDeclaration.BASE_MAPPING_ELEMENT_PROPERTY);
+
+ if (roleMappingElement != null
+ && baseMappingElement != null)
+ {
+ roleMappingElement.accept(this);
+ this.result.append(' ');
+ node.bindingOperator().accept(this);
+ this.result.append(' ');
+ baseMappingElement.accept(this);
+ }
+ else
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+
+ if (!node.getParameterMappings().isEmpty())
+ {
+ this.result.append(" with {\n ");
+ visitList(node, CalloutMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY, ",\n ");
+ this.result.append("\n}");
+ }
+ else
+ {
+ this.result.append(';');
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CallinMappingDeclaration)
+ */
+ @SuppressWarnings({ "nls", "rawtypes" })
+ public boolean visit(CallinMappingDeclaration node)
+ {
+ ASTNode javadoc = getChildNode(node, CallinMappingDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null) {
+ javadoc.accept(this);
+ }
+
+ ASTNode roleMappingElement = getChildNode(node, CallinMappingDeclaration.ROLE_MAPPING_ELEMENT_PROPERTY);
+ List baseMappingElement = getChildList(node, CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY);
+
+ if ( roleMappingElement != null
+ && baseMappingElement != null)
+ {
+ SimpleName nameNode = (SimpleName)getChildNode(node, CallinMappingDeclaration.NAME_PROPERTY);
+ if (nameNode != null && nameNode.getIdentifier().charAt(0) != '<') {
+ nameNode.accept(this);
+ this.result.append(": ");
+ }
+ roleMappingElement.accept(this);
+ this.result.append(' ');
+ MethodBindingOperator bindingOperator = (MethodBindingOperator)getAttribute(node, CallinMappingDeclaration.BINDING_OPERATOR_PROPERTY);
+ bindingOperator.accept(this);
+ this.result.append(' ');
+
+ visitList(node, CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY, String.valueOf(','));
+ }
+ else
+ {
+ node.setFlags(ASTNode.MALFORMED);
+ }
+
+ ASTNode guardPredicate = getChildNode(node, CallinMappingDeclaration.GUARD_PROPERTY);
+ if (guardPredicate != null) {
+ this.result.append(' ');
+ guardPredicate.accept(this);
+ }
+
+ if (!node.getParameterMappings().isEmpty())
+ {
+ this.result.append(" with {\n ");
+ visitList(node, CallinMappingDeclaration.PARAMETER_MAPPINGS_PROPERTY, ",\n ");
+ this.result.append("\n}");
+ }
+ else
+ {
+ this.result.append(';');
+ }
+
+ return false;
+ }
+
+ public boolean visit(MethodBindingOperator node) {
+ switch(node.getBindingKind()) {
+ case MethodBindingOperator.KIND_CALLIN: this.result.append(CallinMappingDeclaration.CALLIN); break;
+ case MethodBindingOperator.KIND_CALLOUT: this.result.append(CalloutMappingDeclaration.CALLOUT); break;
+ case MethodBindingOperator.KIND_CALLOUT_OVERRIDE: this.result.append(CalloutMappingDeclaration.CALLOUT_OVERRIDE); break;
+ }
+ Modifier modifier = node.bindingModifier();
+ if (modifier != null) {
+ this.result.append(' ');
+ modifier.accept(this);
+ } else if (node.getBindingKind() == MethodBindingOperator.KIND_CALLIN) {
+ this.result.append("<missing callin modifier>"); //$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LiftingType)
+ */
+ public boolean visit(LiftingType node)
+ {
+ getChildNode(node, LiftingType.BASE_TYPE_PROPERTY).accept(this);
+ this.result.append(' ');
+ this.result.append("as"); //$NON-NLS-1$
+ this.result.append(' ');
+ getChildNode(node, LiftingType.ROLE_TYPE_PROPERTY).accept(this);
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeAnchor)
+ */
+ public boolean visit(TypeAnchor node)
+ {
+ this.result.append('@');
+ getChildNode(node, TypeAnchor.PATH_PROPERTY).accept(this);
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WithinStatement)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(WithinStatement node)
+ {
+ this.result.append("within(");
+ getChildNode(node, WithinStatement.TEAM_EXPRESSION_PROPERTY).accept(this);
+ this.result.append(") ");
+ getChildNode(node, WithinStatement.BODY_PROPERTY).accept(this);
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TSuperMessageSend)
+ */
+ public boolean visit(TSuperMessageSend node)
+ {
+ ASTNode qualifier = getChildNode(node, TSuperMessageSend.QUALIFIER_PROPERTY);
+ if (qualifier != null) {
+ qualifier.accept(this);
+ this.result.append('.');
+ }
+ this.result.append("tsuper."); //$NON-NLS-1$
+ getChildNode(node, TSuperMessageSend.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, TSuperMessageSend.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ this.result.append(';');
+
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TSuperConstructorInvocation)
+ */
+ public boolean visit(TSuperConstructorInvocation node)
+ {
+ this.result.append("tsuper"); //$NON-NLS-1$
+ this.result.append('(');
+ visitList(node, TSuperConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ this.result.append(';');
+
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BaseCallMessageSend)
+ */
+ public boolean visit(BaseCallMessageSend node)
+ {
+ this.result.append("base."); //$NON-NLS-1$
+ getChildNode(node, BaseCallMessageSend.NAME_PROPERTY).accept(this);
+ this.result.append('(');
+ visitList(node, BaseCallMessageSend.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BaseConstructorMessageSend)
+ */
+ public boolean visit(BaseConstructorInvocation node)
+ {
+ this.result.append("base"); //$NON-NLS-1$
+ this.result.append('(');
+ visitList(node, BaseConstructorInvocation.ARGUMENTS_PROPERTY, String.valueOf(','));
+ this.result.append(')');
+ this.result.append(';');
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterMapping)
+ */
+ @SuppressWarnings("nls")
+ public boolean visit(ParameterMapping node)
+ {
+ if (node.getExpression() != null)
+ {
+ if (node.getDirection().equals("->"))
+ {
+ getChildNode(node, ParameterMapping.EXPRESSION_PROPERTY).accept(this);
+ this.result.append(" ");
+ this.result.append(node.getDirection());
+ this.result.append(" ");
+ this.result.append(node.getIdentifier());
+ }
+ if (node.getDirection().equals("<-"))
+ {
+ this.result.append(node.getIdentifier());
+ this.result.append(" ");
+ this.result.append(node.getDirection());
+ this.result.append(" ");
+ getChildNode(node, ParameterMapping.EXPRESSION_PROPERTY).accept(this);
+ }
+ }
+ return false;
+ }
+ /*
+ * @see ASTVisitor#visit(RoleTypeDeclaration)
+ */
+ public boolean visit(RoleTypeDeclaration node)
+ {
+ ASTNode javadoc= getChildNode(node, RoleTypeDeclaration.JAVADOC_PROPERTY);
+ if (javadoc != null)
+ {
+ javadoc.accept(this);
+ }
+ if (node.getAST().apiLevel() == JLS2_INTERNAL) {
+ printModifiers(getIntAttribute(node, RoleTypeDeclaration.MODIFIERS_PROPERTY), this.result);
+ } else {
+ visitList(node, RoleTypeDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+
+ this.result.append("class "); //$NON-NLS-1$
+ getChildNode(node, RoleTypeDeclaration.NAME_PROPERTY).accept(this);
+ this.result.append(' ');
+
+ ASTNode superclass = getChildNode(node, RoleTypeDeclaration.SUPERCLASS_TYPE_PROPERTY);
+ if (superclass != null)
+ {
+ this.result.append("extends "); //$NON-NLS-1$
+ superclass.accept(this);
+ this.result.append(' ');
+ }
+
+ String lead= "implements "; //$NON-NLS-1$
+ visitList(node, RoleTypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, String.valueOf(','), lead, Util.EMPTY_STRING);
+
+ ASTNode baseClass = getChildNode(node, RoleTypeDeclaration.BASECLASS_TYPE_PROPERTY);
+ if (baseClass != null)
+ {
+ this.result.append("playedBy "); //$NON-NLS-1$
+ baseClass.accept(this);
+ this.result.append(' ');
+ }
+ ASTNode guardPredicate = getChildNode(node, RoleTypeDeclaration.GUARD_PROPERTY);
+ if (guardPredicate != null) {
+ guardPredicate.accept(this);
+ this.result.append(' ');
+ }
+
+ this.result.append('{');
+ visitList(node, RoleTypeDeclaration.BODY_DECLARATIONS_PROPERTY, null);
+ visitList(node, RoleTypeDeclaration.PRECEDENCE_PROPERTY, null);
+ this.result.append('}');
+ return false;
+ }
+ @SuppressWarnings("nls")
+ @Override
+ public boolean visit(GuardPredicateDeclaration guard) {
+ if (guard.isBase())
+ this.result.append("base ");
+ this.result.append("when (");
+ guard.getExpression().accept(this);
+ this.result.append(')');
+ return false;
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public boolean visit(PrecedenceDeclaration node) {
+ this.result.append("precedence ");
+ String sep = "";
+ for (Object element: node.elements()) {
+ this.result.append(sep);
+ ((ASTNode)element).accept(this);
+ sep = ", ";
+ }
+ this.result.append(';');
+ return false;
+ }
+// jsv+SH}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
new file mode 100644
index 000000000..b5e6b72ae
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: ASTRewriteFormatter.java 22741 2009-10-13 22:23:05Z stephan $
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Fraunhofer FIRST - extended API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jdt.core.formatter.IndentManipulation;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.Position;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+/* package */ final class ASTRewriteFormatter {
+
+ public static class NodeMarker extends Position {
+ public Object data;
+ }
+
+ private class ExtendedFlattener extends ASTRewriteFlattener {
+
+ private ArrayList positions;
+
+ public ExtendedFlattener(RewriteEventStore store) {
+ super(store);
+ this.positions= new ArrayList();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#preVisit(ASTNode)
+ */
+ public void preVisit(ASTNode node) {
+ Object trackData= getEventStore().getTrackedNodeData(node);
+ if (trackData != null) {
+ addMarker(trackData, this.result.length(), 0);
+ }
+ Object placeholderData= getPlaceholders().getPlaceholderData(node);
+ if (placeholderData != null) {
+ addMarker(placeholderData, this.result.length(), 0);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#postVisit(ASTNode)
+ */
+ public void postVisit(ASTNode node) {
+ Object placeholderData= getPlaceholders().getPlaceholderData(node);
+ if (placeholderData != null) {
+ fixupLength(placeholderData, this.result.length());
+ }
+ Object trackData= getEventStore().getTrackedNodeData(node);
+ if (trackData != null) {
+ fixupLength(trackData, this.result.length());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.ASTRewriteFlattener#visit(org.eclipse.jdt.core.dom.Block)
+ */
+ public boolean visit(Block node) {
+ if (getPlaceholders().isCollapsed(node)) {
+ visitList(node, Block.STATEMENTS_PROPERTY, null);
+ return false;
+ }
+ return super.visit(node);
+ }
+
+ private NodeMarker addMarker(Object annotation, int startOffset, int length) {
+ NodeMarker marker= new NodeMarker();
+ marker.offset= startOffset;
+ marker.length= length;
+ marker.data= annotation;
+ this.positions.add(marker);
+ return marker;
+ }
+
+ private void fixupLength(Object data, int endOffset) {
+ for (int i= this.positions.size()-1; i >= 0 ; i--) {
+ NodeMarker marker= (NodeMarker) this.positions.get(i);
+ if (marker.data == data) {
+ marker.length= endOffset - marker.offset;
+ return;
+ }
+ }
+ }
+
+ public NodeMarker[] getMarkers() {
+ return (NodeMarker[]) this.positions.toArray(new NodeMarker[this.positions.size()]);
+ }
+ }
+
+ private final String lineDelimiter;
+ private final int tabWidth;
+ private final int indentWidth;
+
+ private final NodeInfoStore placeholders;
+ private final RewriteEventStore eventStore;
+
+ private final Map options;
+
+
+ public ASTRewriteFormatter(NodeInfoStore placeholders, RewriteEventStore eventStore, Map options, String lineDelimiter) {
+ this.placeholders= placeholders;
+ this.eventStore= eventStore;
+
+ this.options= options;
+ this.lineDelimiter= lineDelimiter;
+
+ this.tabWidth= IndentManipulation.getTabWidth(options);
+ this.indentWidth= IndentManipulation.getIndentWidth(options);
+ }
+
+
+
+ public NodeInfoStore getPlaceholders() {
+ return this.placeholders;
+ }
+
+ public RewriteEventStore getEventStore() {
+ return this.eventStore;
+ }
+
+ public int getTabWidth() {
+ return this.tabWidth;
+ }
+
+ public int getIndentWidth() {
+ return this.indentWidth;
+ }
+
+ public String getLineDelimiter() {
+ return this.lineDelimiter;
+ }
+
+ /**
+ * Returns the string accumulated in the visit formatted using the default formatter.
+ * Updates the existing node's positions.
+ *
+ * @param node The node to flatten.
+ * @param initialIndentationLevel The initial indentation level.
+ * @param resultingMarkers Resulting the updated NodeMarkers.
+ * @return Returns the serialized and formatted code.
+ */
+ public String getFormattedResult(ASTNode node, int initialIndentationLevel, Collection resultingMarkers) {
+
+ ExtendedFlattener flattener= new ExtendedFlattener(this.eventStore);
+ node.accept(flattener);
+
+ NodeMarker[] markers= flattener.getMarkers();
+ for (int i= 0; i < markers.length; i++) {
+ resultingMarkers.add(markers[i]); // add to result
+ }
+
+ String unformatted= flattener.getResult();
+ TextEdit edit= formatNode(node, unformatted, initialIndentationLevel);
+ if (edit == null) {
+ if (initialIndentationLevel > 0) {
+ // at least correct the indent
+ String indentString = createIndentString(initialIndentationLevel);
+ ReplaceEdit[] edits = IndentManipulation.getChangeIndentEdits(unformatted, 0, this.tabWidth, this.indentWidth, indentString);
+ edit= new MultiTextEdit();
+ edit.addChild(new InsertEdit(0, indentString));
+ edit.addChildren(edits);
+ } else {
+ return unformatted;
+ }
+ }
+ return evaluateFormatterEdit(unformatted, edit, markers);
+ }
+
+ public String createIndentString(int indentationUnits) {
+ return ToolFactory.createCodeFormatter(this.options).createIndentationString(indentationUnits);
+ }
+
+ public String getIndentString(String currentLine) {
+ return IndentManipulation.extractIndentString(currentLine, this.tabWidth, this.indentWidth);
+ }
+
+ public String changeIndent(String code, int codeIndentLevel, String newIndent) {
+ return IndentManipulation.changeIndent(code, codeIndentLevel, this.tabWidth, this.indentWidth, newIndent, this.lineDelimiter);
+ }
+
+ public int computeIndentUnits(String line) {
+ return IndentManipulation.measureIndentUnits(line, this.tabWidth, this.indentWidth);
+ }
+
+ /**
+ * Evaluates the edit on the given string.
+ * @param string The string to format
+ * @param edit The edit resulted from the code formatter
+ * @param positions Positions to update or <code>null</code>.
+ * @return The formatted string
+ * @throws IllegalArgumentException If the positions are not inside the string, a
+ * IllegalArgumentException is thrown.
+ */
+ public static String evaluateFormatterEdit(String string, TextEdit edit, Position[] positions) {
+ try {
+ Document doc= createDocument(string, positions);
+ edit.apply(doc, 0);
+ if (positions != null) {
+ for (int i= 0; i < positions.length; i++) {
+ Assert.isTrue(!positions[i].isDeleted, "Position got deleted"); //$NON-NLS-1$
+ }
+ }
+ return doc.get();
+ } catch (BadLocationException e) {
+ //JavaPlugin.log(e); // bug in the formatter
+ Assert.isTrue(false, "Fromatter created edits with wrong positions: " + e.getMessage()); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ public TextEdit formatString(int kind, String string, int offset, int length, int indentationLevel) {
+ return ToolFactory.createCodeFormatter(this.options).format(kind, string, offset, length, indentationLevel, this.lineDelimiter);
+ }
+
+ /**
+ * Creates edits that describe how to format the given string. Returns <code>null</code> if the code could not be formatted for the given kind.
+ * @param node Node describing the type of the string
+ * @param str The unformatted string
+ * @param indentationLevel
+ * @return Returns the edit representing the result of the formatter
+ * @throws IllegalArgumentException If the offset and length are not inside the string, a
+ * IllegalArgumentException is thrown.
+ */
+ private TextEdit formatNode(ASTNode node, String str, int indentationLevel) {
+ int code;
+ String prefix= ""; //$NON-NLS-1$
+ String suffix= ""; //$NON-NLS-1$
+//{ObjectTeams: check code flavour:
+ this.options.put(CompilerOptions.OPTION_AllowScopedKeywords, isOTJCode(node)?CompilerOptions.DISABLED:CompilerOptions.ENABLED);
+ // FIXME(SH): if not recognizable as OTJCode set OPTION_PureJavaOnly to ENABLED??
+// SH}
+ if (node instanceof Statement) {
+ code= CodeFormatter.K_STATEMENTS;
+ if (node.getNodeType() == ASTNode.SWITCH_CASE) {
+ prefix= "switch(1) {"; //$NON-NLS-1$
+ suffix= "}"; //$NON-NLS-1$
+ code= CodeFormatter.K_STATEMENTS;
+ }
+ } else if (node instanceof Expression && node.getNodeType() != ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
+//{ObjectTeams: tells the formatter to format a single parameter mapping. It is not handled by the formatExpression method !!
+ if (node.getNodeType() == ASTNode.PARAMETER_MAPPING) {
+ code = CodeFormatter.K_PARAMETER_MAPPING;
+ } else
+//jsv}
+ if (node instanceof Annotation) {
+ suffix= "\nclass A {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ } else {
+ code= CodeFormatter.K_EXPRESSION;
+ }
+ } else if (node instanceof BodyDeclaration) {
+ code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
+ } else {
+ switch (node.getNodeType()) {
+ case ASTNode.ARRAY_TYPE:
+ case ASTNode.PARAMETERIZED_TYPE:
+ case ASTNode.PRIMITIVE_TYPE:
+ case ASTNode.QUALIFIED_TYPE:
+ case ASTNode.SIMPLE_TYPE:
+ suffix= " x;"; //$NON-NLS-1$
+ code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
+ break;
+ case ASTNode.WILDCARD_TYPE:
+ prefix= "A<"; //$NON-NLS-1$
+ suffix= "> x;"; //$NON-NLS-1$
+ code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
+ break;
+ case ASTNode.COMPILATION_UNIT:
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
+ case ASTNode.SINGLE_VARIABLE_DECLARATION:
+ suffix= ";"; //$NON-NLS-1$
+ code= CodeFormatter.K_STATEMENTS;
+ break;
+ case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
+ prefix= "A "; //$NON-NLS-1$
+ suffix= ";"; //$NON-NLS-1$
+ code= CodeFormatter.K_STATEMENTS;
+ break;
+ case ASTNode.PACKAGE_DECLARATION:
+ case ASTNode.IMPORT_DECLARATION:
+ suffix= "\nclass A {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.JAVADOC:
+ suffix= "\nclass A {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.CATCH_CLAUSE:
+ prefix= "try {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_STATEMENTS;
+ break;
+ case ASTNode.ANONYMOUS_CLASS_DECLARATION:
+ prefix= "new A()"; //$NON-NLS-1$
+ suffix= ";"; //$NON-NLS-1$
+ code= CodeFormatter.K_STATEMENTS;
+ break;
+ case ASTNode.MEMBER_VALUE_PAIR:
+ prefix= "@Author("; //$NON-NLS-1$
+ suffix= ") class x {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.MODIFIER:
+ suffix= " class x {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.TYPE_PARAMETER:
+ prefix= "class X<"; //$NON-NLS-1$
+ suffix= "> {}"; //$NON-NLS-1$
+ code= CodeFormatter.K_COMPILATION_UNIT;
+ break;
+ case ASTNode.MEMBER_REF:
+ case ASTNode.METHOD_REF:
+ case ASTNode.METHOD_REF_PARAMETER:
+ case ASTNode.TAG_ELEMENT:
+ case ASTNode.TEXT_ELEMENT:
+ // javadoc formatting disabled due to bug 93644
+ return null;
+
+// wiat for bug 93644
+// case ASTNode.MEMBER_REF:
+// case ASTNode.METHOD_REF:
+// prefix= "/**\n * @see ";
+// suffix= "\n*/";
+// code= CodeFormatter.K_JAVA_DOC;
+// break;
+// case ASTNode.METHOD_REF_PARAMETER:
+// prefix= "/**\n * @see A#foo(";
+// suffix= ")\n*/";
+// code= CodeFormatter.K_JAVA_DOC;
+// break;
+// case ASTNode.TAG_ELEMENT:
+// case ASTNode.TEXT_ELEMENT:
+// prefix= "/**\n * ";
+// suffix= "\n*/";
+// code= CodeFormatter.K_JAVA_DOC;
+// break;
+ default:
+ //Assert.isTrue(false, "Node type not covered: " + node.getClass().getName());
+ return null;
+ }
+ }
+
+ String concatStr= prefix + str + suffix;
+ TextEdit edit= formatString(code, concatStr, prefix.length(), str.length(), indentationLevel);
+
+ if (prefix.length() > 0) {
+ edit= shifEdit(edit, prefix.length());
+ }
+ return edit;
+ }
+
+//{ObjectTeams: needed to configure the scanner:
+ private boolean isOTJCode(ASTNode node) {
+ while (node != null && node.getNodeType() != ASTNode.TYPE_DECLARATION) {
+ switch (node.getNodeType()) {
+ case ASTNode.ROLE_TYPE_DECLARATION:
+ case ASTNode.CALLOUT_MAPPING_DECLARATION:
+ case ASTNode.CALLIN_MAPPING_DECLARATION:
+ case ASTNode.PARAMETER_MAPPING:
+ return true;
+ case ASTNode.METHOD_DECLARATION:
+ if ((((MethodDeclaration)node).getModifiers() & ExtraCompilerModifiers.AccCallin) != 0)
+ return true;
+ }
+ node= node.getParent();
+ }
+ if (node != null) {
+ TypeDeclaration type = (TypeDeclaration)node;
+ return type.isRole() || type.isTeam();
+ }
+ return false;
+ }
+// SH}
+
+ private static TextEdit shifEdit(TextEdit oldEdit, int diff) {
+ TextEdit newEdit;
+ if (oldEdit instanceof ReplaceEdit) {
+ ReplaceEdit edit= (ReplaceEdit) oldEdit;
+ newEdit= new ReplaceEdit(edit.getOffset() - diff, edit.getLength(), edit.getText());
+ } else if (oldEdit instanceof InsertEdit) {
+ InsertEdit edit= (InsertEdit) oldEdit;
+ newEdit= new InsertEdit(edit.getOffset() - diff, edit.getText());
+ } else if (oldEdit instanceof DeleteEdit) {
+ DeleteEdit edit= (DeleteEdit) oldEdit;
+ newEdit= new DeleteEdit(edit.getOffset() - diff, edit.getLength());
+ } else if (oldEdit instanceof MultiTextEdit) {
+ newEdit= new MultiTextEdit();
+ } else {
+ return null; // not supported
+ }
+ TextEdit[] children= oldEdit.getChildren();
+ for (int i= 0; i < children.length; i++) {
+ TextEdit shifted= shifEdit(children[i], diff);
+ if (shifted != null) {
+ newEdit.addChild(shifted);
+ }
+ }
+ return newEdit;
+ }
+
+ private static Document createDocument(String string, Position[] positions) throws IllegalArgumentException {
+ Document doc= new Document(string);
+ try {
+ if (positions != null) {
+ final String POS_CATEGORY= "myCategory"; //$NON-NLS-1$
+
+ doc.addPositionCategory(POS_CATEGORY);
+ doc.addPositionUpdater(new DefaultPositionUpdater(POS_CATEGORY) {
+ protected boolean notDeleted() {
+ int start= this.fOffset;
+ int end= start + this.fLength;
+ if (start < this.fPosition.offset && (this.fPosition.offset + this.fPosition.length < end)) {
+ this.fPosition.offset= end; // deleted positions: set to end of remove
+ return false;
+ }
+ return true;
+ }
+ });
+ for (int i= 0; i < positions.length; i++) {
+ try {
+ doc.addPosition(POS_CATEGORY, positions[i]);
+ } catch (BadLocationException e) {
+ throw new IllegalArgumentException("Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ }
+ }
+ }
+ } catch (BadPositionCategoryException cannotHappen) {
+ // can not happen: category is correctly set up
+ }
+ return doc;
+ }
+
+
+
+ public static interface Prefix {
+ String getPrefix(int indent);
+ }
+
+ public static interface BlockContext {
+ String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events);
+ }
+
+ public static class ConstPrefix implements Prefix {
+ private String prefix;
+
+ public ConstPrefix(String prefix) {
+ this.prefix= prefix;
+ }
+
+ public String getPrefix(int indent) {
+ return this.prefix;
+ }
+ }
+
+ private class FormattingPrefix implements Prefix {
+ private int kind;
+ private String string;
+ private int start;
+ private int length;
+
+ public FormattingPrefix(String string, String sub, int kind) {
+ this.start= string.indexOf(sub);
+ this.length= sub.length();
+ this.string= string;
+ this.kind= kind;
+ }
+
+ public String getPrefix(int indent) {
+ Position pos= new Position(this.start, this.length);
+ String str= this.string;
+ TextEdit res= formatString(this.kind, str, 0, str.length(), indent);
+ if (res != null) {
+ str= evaluateFormatterEdit(str, res, new Position[] { pos });
+ }
+ return str.substring(pos.offset + 1, pos.offset + pos.length - 1);
+ }
+ }
+
+ private class BlockFormattingPrefix implements BlockContext {
+ private String prefix;
+ private int start;
+
+ public BlockFormattingPrefix(String prefix, int start) {
+ this.start= start;
+ this.prefix= prefix;
+ }
+
+ public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
+ String nodeString= ASTRewriteFlattener.asString(node, events);
+ String str= this.prefix + nodeString;
+ Position pos= new Position(this.start, this.prefix.length() + 1 - this.start);
+
+ TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
+ if (res != null) {
+ str= evaluateFormatterEdit(str, res, new Position[] { pos });
+ }
+ return new String[] { str.substring(pos.offset + 1, pos.offset + pos.length - 1), ""}; //$NON-NLS-1$
+ }
+ }
+
+ private class BlockFormattingPrefixSuffix implements BlockContext {
+ private String prefix;
+ private String suffix;
+ private int start;
+
+ public BlockFormattingPrefixSuffix(String prefix, String suffix, int start) {
+ this.start= start;
+ this.suffix= suffix;
+ this.prefix= prefix;
+ }
+
+ public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
+ String nodeString= ASTRewriteFlattener.asString(node, events);
+ int nodeStart= this.prefix.length();
+ int nodeEnd= nodeStart + nodeString.length() - 1;
+
+ String str= this.prefix + nodeString + this.suffix;
+
+ Position pos1= new Position(this.start, nodeStart + 1 - this.start);
+ Position pos2= new Position(nodeEnd, 2);
+
+ TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
+ if (res != null) {
+ str= evaluateFormatterEdit(str, res, new Position[] { pos1, pos2 });
+ }
+ return new String[] {
+ str.substring(pos1.offset + 1, pos1.offset + pos1.length - 1),
+ str.substring(pos2.offset + 1, pos2.offset + pos2.length - 1)
+ };
+ }
+ }
+
+ public final static Prefix NONE= new ConstPrefix(""); //$NON-NLS-1$
+ public final static Prefix SPACE= new ConstPrefix(" "); //$NON-NLS-1$
+ public final static Prefix ASSERT_COMMENT= new ConstPrefix(" : "); //$NON-NLS-1$
+
+ public final Prefix VAR_INITIALIZER= new FormattingPrefix("A a={};", "a={" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix METHOD_BODY= new FormattingPrefix("void a() {}", ") {" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix FINALLY_BLOCK= new FormattingPrefix("try {} finally {}", "} finally {", CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix CATCH_BLOCK= new FormattingPrefix("try {} catch(Exception e) {}", "} c" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix ANNOT_MEMBER_DEFAULT= new FormattingPrefix("String value() default 1;", ") default 1" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix ENUM_BODY_START= new FormattingPrefix("enum E { A(){void foo(){}} }", "){v" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix ENUM_BODY_END= new FormattingPrefix("enum E { A(){void foo(){ }}, B}", "}}," , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix WILDCARD_EXTENDS= new FormattingPrefix("A<? extends B> a;", "? extends B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix WILDCARD_SUPER= new FormattingPrefix("A<? super B> a;", "? super B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+
+ public final Prefix FIRST_ENUM_CONST= new FormattingPrefix("enum E { X;}", "{ X" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix ANNOTATION_SEPARATION= new FormattingPrefix("@A @B class C {}", "A @" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
+ public final Prefix PARAM_ANNOTATION_SEPARATION= new FormattingPrefix("void foo(@A @B p) { }", "A @" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
+
+ public final BlockContext IF_BLOCK_WITH_ELSE= new BlockFormattingPrefixSuffix("if (true)", "else{}", 8); //$NON-NLS-1$ //$NON-NLS-2$
+ public final BlockContext IF_BLOCK_NO_ELSE= new BlockFormattingPrefix("if (true)", 8); //$NON-NLS-1$
+ public final BlockContext ELSE_AFTER_STATEMENT= new BlockFormattingPrefix("if (true) foo(); else ", 15); //$NON-NLS-1$
+ public final BlockContext ELSE_AFTER_BLOCK= new BlockFormattingPrefix("if (true) {} else ", 11); //$NON-NLS-1$
+
+ public final BlockContext FOR_BLOCK= new BlockFormattingPrefix("for (;;) ", 7); //$NON-NLS-1$
+ public final BlockContext WHILE_BLOCK= new BlockFormattingPrefix("while (true)", 11); //$NON-NLS-1$
+ public final BlockContext DO_BLOCK= new BlockFormattingPrefixSuffix("do ", "while (true);", 1); //$NON-NLS-1$ //$NON-NLS-2$
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java
new file mode 100644
index 000000000..923de4bef
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java
@@ -0,0 +1,1189 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IBuffer;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.TypeNameRequestor;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+
+@SuppressWarnings("unchecked")
+public final class ImportRewriteAnalyzer {
+
+ private final ICompilationUnit compilationUnit;
+ private final ArrayList packageEntries;
+
+ private final List importsCreated;
+ private final List staticImportsCreated;
+
+ private final IRegion replaceRange;
+
+ private final int importOnDemandThreshold;
+ private final int staticImportOnDemandThreshold;
+
+ private boolean filterImplicitImports;
+ private boolean findAmbiguousImports;
+
+ private int flags= 0;
+
+ private static final int F_NEEDS_LEADING_DELIM= 2;
+ private static final int F_NEEDS_TRAILING_DELIM= 4;
+
+ private static final String JAVA_LANG= "java.lang"; //$NON-NLS-1$
+
+ public ImportRewriteAnalyzer(ICompilationUnit cu, CompilationUnit root, String[] importOrder, int threshold, int staticThreshold, boolean restoreExistingImports) {
+ this.compilationUnit= cu;
+ this.importOnDemandThreshold= threshold;
+ this.staticImportOnDemandThreshold= staticThreshold;
+
+ this.filterImplicitImports= true;
+ this.findAmbiguousImports= true; //!restoreExistingImports;
+
+ this.packageEntries= new ArrayList(20);
+ this.importsCreated= new ArrayList();
+ this.staticImportsCreated= new ArrayList();
+ this.flags= 0;
+
+ this.replaceRange= evaluateReplaceRange(root);
+ if (restoreExistingImports) {
+ addExistingImports(root);
+ }
+
+ PackageEntry[] order= new PackageEntry[importOrder.length];
+ for (int i= 0; i < order.length; i++) {
+ String curr= importOrder[i];
+ if (curr.length() > 0 && curr.charAt(0) == '#') {
+ curr= curr.substring(1);
+ order[i]= new PackageEntry(curr, curr, true); // static import group
+ } else {
+ order[i]= new PackageEntry(curr, curr, false); // normal import group
+ }
+ }
+
+ addPreferenceOrderHolders(order);
+ }
+
+ private int getSpacesBetweenImportGroups() {
+ try {
+ int num= Integer.parseInt(this.compilationUnit.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS, true));
+ if (num >= 0)
+ return num;
+ } catch (NumberFormatException e) {
+ // fall through
+ }
+ return 1;
+ }
+
+ private boolean insertSpaceBeforeSemicolon() {
+ return JavaCore.INSERT.equals(this.compilationUnit.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON, true));
+ }
+
+ private void addPreferenceOrderHolders(PackageEntry[] preferenceOrder) {
+ if (this.packageEntries.isEmpty()) {
+ // all new: copy the elements
+ for (int i= 0; i < preferenceOrder.length; i++) {
+ this.packageEntries.add(preferenceOrder[i]);
+ }
+ } else {
+ // match the preference order entries to existing imports
+ // entries not found are appended after the last successfully matched entry
+
+ PackageEntry[] lastAssigned= new PackageEntry[preferenceOrder.length];
+
+ // find an existing package entry that matches most
+ for (int k= 0; k < this.packageEntries.size(); k++) {
+ PackageEntry entry= (PackageEntry) this.packageEntries.get(k);
+ if (!entry.isComment()) {
+ String currName= entry.getName();
+ int currNameLen= currName.length();
+ int bestGroupIndex= -1;
+ int bestGroupLen= -1;
+ for (int i= 0; i < preferenceOrder.length; i++) {
+ boolean currPrevStatic= preferenceOrder[i].isStatic();
+ if (currPrevStatic == entry.isStatic()) {
+ String currPrefEntry= preferenceOrder[i].getName();
+ int currPrefLen= currPrefEntry.length();
+ if (currName.startsWith(currPrefEntry) && currPrefLen >= bestGroupLen) {
+ if (currPrefLen == currNameLen || currName.charAt(currPrefLen) == '.') {
+ if (bestGroupIndex == -1 || currPrefLen > bestGroupLen) {
+ bestGroupLen= currPrefLen;
+ bestGroupIndex= i;
+ }
+ }
+ }
+ }
+ }
+ if (bestGroupIndex != -1) {
+ entry.setGroupID(preferenceOrder[bestGroupIndex].getName());
+ lastAssigned[bestGroupIndex]= entry; // remember last entry
+ }
+ }
+ }
+ // fill in not-assigned categories, keep partial order
+ int currAppendIndex= 0;
+ for (int i= 0; i < lastAssigned.length; i++) {
+ PackageEntry entry= lastAssigned[i];
+ if (entry == null) {
+ PackageEntry newEntry= preferenceOrder[i];
+ if (currAppendIndex == 0 && !newEntry.isStatic()) {
+ currAppendIndex= getIndexAfterStatics();
+ }
+ this.packageEntries.add(currAppendIndex, newEntry);
+ currAppendIndex++;
+ } else {
+ currAppendIndex= this.packageEntries.indexOf(entry) + 1;
+ }
+ }
+ }
+ }
+
+ private static String getQualifier(ImportDeclaration decl) {
+ String name= decl.getName().getFullyQualifiedName();
+ return decl.isOnDemand() ? name : Signature.getQualifier(name);
+ }
+
+ private static String getFullName(ImportDeclaration decl) {
+ String name= decl.getName().getFullyQualifiedName();
+ return decl.isOnDemand() ? name + ".*": name; //$NON-NLS-1$
+ }
+
+ private void addExistingImports(CompilationUnit root) {
+ List/*ImportDeclaration*/ decls= root.imports();
+ if (decls.isEmpty()) {
+ return;
+ }
+ PackageEntry currPackage= null;
+
+ ImportDeclaration curr= (ImportDeclaration) decls.get(0);
+ int currOffset= curr.getStartPosition();
+ int currLength= curr.getLength();
+ int currEndLine= root.getLineNumber(currOffset + currLength);
+
+ for (int i= 1; i < decls.size(); i++) {
+ boolean isStatic= curr.isStatic();
+ String name= getFullName(curr);
+ String packName= getQualifier(curr);
+//{ObjectTeams: added 'isBase()' (two occurrences):
+ boolean isBase= curr.isBase();
+ if (currPackage == null || currPackage.compareTo(packName, isStatic, isBase) != 0) {
+ currPackage= new PackageEntry(packName, null, isStatic, isBase);
+// SH}
+ this.packageEntries.add(currPackage);
+ }
+
+ ImportDeclaration next= (ImportDeclaration) decls.get(i);
+ int nextOffset= next.getStartPosition();
+ int nextLength= next.getLength();
+ int nextOffsetLine= root.getLineNumber(nextOffset);
+
+ // if next import is on a different line, modify the end position to the next line begin offset
+ if (currEndLine < nextOffsetLine) {
+ currEndLine++;
+ nextOffset= root.getPosition(currEndLine, 0);
+ }
+ currPackage.add(new ImportDeclEntry(name, isStatic, new Region(currOffset, nextOffset - currOffset)));
+//{ObjectTeams: base import
+ if (isBase)
+ currPackage.getLast().setIsBase(true);
+// SH}
+ currOffset= nextOffset;
+ curr= next;
+
+ // add a comment entry for spacing between imports
+ if (currEndLine < nextOffsetLine) {
+ nextOffset= root.getPosition(nextOffsetLine, 0);
+
+ currPackage= new PackageEntry(); // create a comment package entry for this
+ this.packageEntries.add(currPackage);
+ currPackage.add(new ImportDeclEntry(null, false, new Region(currOffset, nextOffset - currOffset)));
+
+ currOffset= nextOffset;
+ }
+ currEndLine= root.getLineNumber(nextOffset + nextLength);
+ }
+
+ boolean isStatic= curr.isStatic();
+ String name= getFullName(curr);
+ String packName= getQualifier(curr);
+//{ObjectTeams: added 'isBase'
+ boolean isBase= curr.isBase();
+/* orig:
+ if (currPackage == null || currPackage.compareTo(packName, isStatic) != 0) {
+ currPackage= new PackageEntry(packName, null, isStatic);
+ :giro */
+ if (currPackage == null || currPackage.compareTo(packName, isStatic, isBase) != 0) {
+ currPackage= new PackageEntry(packName, null, isStatic, curr.isBase());
+// SH}
+ this.packageEntries.add(currPackage);
+ }
+ int length= this.replaceRange.getOffset() + this.replaceRange.getLength() - curr.getStartPosition();
+ currPackage.add(new ImportDeclEntry(name, isStatic, new Region(curr.getStartPosition(), length)));
+//{ObjectTeams: base import
+ if (isBase)
+ currPackage.getLast().setIsBase(true);
+//SH}
+ }
+
+ /**
+ * Sets that implicit imports (types in default package, CU- package and
+ * 'java.lang') should not be created. Note that this is a heuristic filter and can
+ * lead to missing imports, e.g. in cases where a type is forced to be specified
+ * due to a name conflict.
+ * By default, the filter is enabled.
+ * @param filterImplicitImports The filterImplicitImports to set
+ */
+ public void setFilterImplicitImports(boolean filterImplicitImports) {
+ this.filterImplicitImports= filterImplicitImports;
+ }
+
+ /**
+ * When set searches for imports that can not be folded into on-demand
+ * imports but must be specified explicitly
+ * @param findAmbiguousImports The new value
+ */
+ public void setFindAmbiguousImports(boolean findAmbiguousImports) {
+ this.findAmbiguousImports= findAmbiguousImports;
+ }
+
+ private static class PackageMatcher {
+ private String newName;
+ private String bestName;
+ private int bestMatchLen;
+
+ public PackageMatcher() {
+ // initialization in 'initialize'
+ }
+
+ public void initialize(String newImportName, String bestImportName) {
+ this.newName= newImportName;
+ this.bestName= bestImportName;
+ this.bestMatchLen= getCommonPrefixLength(bestImportName, newImportName);
+ }
+
+ public boolean isBetterMatch(String currName, boolean preferCurr) {
+ boolean isBetter;
+ int currMatchLen= getCommonPrefixLength(currName, this.newName);
+ int matchDiff= currMatchLen - this.bestMatchLen;
+ if (matchDiff == 0) {
+ if (currMatchLen == this.newName.length() && currMatchLen == currName.length() && currMatchLen == this.bestName.length()) {
+ // duplicate entry and complete match
+ isBetter= preferCurr;
+ } else {
+ isBetter= sameMatchLenTest(currName);
+ }
+ } else {
+ isBetter= (matchDiff > 0); // curr has longer match
+ }
+ if (isBetter) {
+ this.bestName= currName;
+ this.bestMatchLen= currMatchLen;
+ }
+ return isBetter;
+ }
+
+ private boolean sameMatchLenTest(String currName) {
+ int matchLen= this.bestMatchLen;
+ // known: bestName and currName differ from newName at position 'matchLen'
+ // currName and bestName don't have to differ at position 'matchLen'
+
+ // determine the order and return true if currName is closer to newName
+ char newChar= getCharAt(this.newName, matchLen);
+ char currChar= getCharAt(currName, matchLen);
+ char bestChar= getCharAt(this.bestName, matchLen);
+
+ if (newChar < currChar) {
+ if (bestChar < newChar) { // b < n < c
+ return (currChar - newChar) < (newChar - bestChar); // -> (c - n) < (n - b)
+ } else { // n < b && n < c
+ if (currChar == bestChar) { // longer match between curr and best
+ return false; // keep curr and best together, new should be before both
+ } else {
+ return currChar < bestChar; // -> (c < b)
+ }
+ }
+ } else {
+ if (bestChar > newChar) { // c < n < b
+ return (newChar - currChar) < (bestChar - newChar); // -> (n - c) < (b - n)
+ } else { // n > b && n > c
+ if (currChar == bestChar) { // longer match between curr and best
+ return true; // keep curr and best together, new should be ahead of both
+ } else {
+ return currChar > bestChar; // -> (c > b)
+ }
+ }
+ }
+ }
+ }
+
+ /* package */ static int getCommonPrefixLength(String s, String t) {
+ int len= Math.min(s.length(), t.length());
+ for (int i= 0; i < len; i++) {
+ if (s.charAt(i) != t.charAt(i)) {
+ return i;
+ }
+ }
+ return len;
+ }
+
+ /* package */ static char getCharAt(String str, int index) {
+ if (str.length() > index) {
+ return str.charAt(index);
+ }
+ return 0;
+ }
+
+//{ObjectTeams: added: 'isBase':
+ private PackageEntry findBestMatch(String newName, boolean isStatic, boolean isBase) {
+// SH}
+ if (this.packageEntries.isEmpty()) {
+ return null;
+ }
+ String groupId= null;
+ int longestPrefix= -1;
+ // find the matching group
+ for (int i= 0; i < this.packageEntries.size(); i++) {
+ PackageEntry curr= (PackageEntry) this.packageEntries.get(i);
+//{ObjectTeams: new check:
+/* orig:
+ if (isStatic == curr.isStatic()) {
+ :giro */
+ if (isStatic == curr.isStatic() && isBase == curr.isBase()) {
+// SH}
+ String currGroup= curr.getGroupID();
+ if (currGroup != null && newName.startsWith(currGroup)) {
+ int prefixLen= currGroup.length();
+ if (prefixLen == newName.length()) {
+ return curr; // perfect fit, use entry
+ }
+ if ((newName.charAt(prefixLen) == '.' || prefixLen == 0) && prefixLen > longestPrefix) {
+ longestPrefix= prefixLen;
+ groupId= currGroup;
+ }
+ }
+ }
+ }
+ PackageEntry bestMatch= null;
+ PackageMatcher matcher= new PackageMatcher();
+ matcher.initialize(newName, ""); //$NON-NLS-1$
+ for (int i= 0; i < this.packageEntries.size(); i++) { // find the best match with the same group
+ PackageEntry curr= (PackageEntry) this.packageEntries.get(i);
+ if (!curr.isComment() && curr.isStatic() == isStatic
+//{ObjectTeams: new check:
+ && isBase == curr.isBase())
+ {
+// SH}
+ if (groupId == null || groupId.equals(curr.getGroupID())) {
+ boolean preferrCurr= (bestMatch == null) || (curr.getNumberOfImports() > bestMatch.getNumberOfImports());
+ if (matcher.isBetterMatch(curr.getName(), preferrCurr)) {
+ bestMatch= curr;
+ }
+ }
+ }
+ }
+ return bestMatch;
+ }
+
+ private static boolean isImplicitImport(String qualifier, ICompilationUnit cu) {
+ if (JAVA_LANG.equals(qualifier)) {
+ return true;
+ }
+ String packageName= cu.getParent().getElementName();
+ if (qualifier.equals(packageName)) {
+ return true;
+ }
+ String mainTypeName= JavaCore.removeJavaLikeExtension(cu.getElementName());
+ if (packageName.length() == 0) {
+ return qualifier.equals(mainTypeName);
+ }
+ return qualifier.equals(packageName +'.' + mainTypeName);
+ }
+
+//{ObjectTeams: added param 'isBase':
+ public void addImport(String fullTypeName, boolean isStatic, boolean isBase) {
+ String typeContainerName= Signature.getQualifier(fullTypeName);
+ ImportDeclEntry decl= new ImportDeclEntry(fullTypeName, isStatic, null);
+ sortIn(typeContainerName, decl, isStatic, isBase);
+ }
+// SH}
+//{ObjectTeams: added isBase:
+/* orig:
+ public boolean removeImport(String qualifiedName, boolean isStatic) {
+ :giro */
+ public boolean removeImport(String qualifiedName, boolean isStatic, boolean isBase) {
+// orig:
+ String containerName= Signature.getQualifier(qualifiedName);
+
+ int nPackages= this.packageEntries.size();
+ for (int i= 0; i < nPackages; i++) {
+ PackageEntry entry= (PackageEntry) this.packageEntries.get(i);
+/*
+ if (entry.compareTo(containerName, isStatic) == 0) {
+ :giro */
+ if (entry.compareTo(containerName, isStatic, isBase) == 0) {
+// SH}
+ if (entry.remove(qualifiedName, isStatic)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+//{ObjectTeams: base import:
+ public void addBaseImport(String fullTypeName) {
+ String typeContainerName= Signature.getQualifier(fullTypeName);
+ ImportDeclEntry decl= new ImportDeclEntry(fullTypeName, false, null);
+ decl.setIsBase(true);
+ sortIn(typeContainerName, decl, false, true);
+ }
+ // set flag.
+ public boolean setBase(String fullTypeName) {
+ String containerName= Signature.getQualifier(fullTypeName);
+ int nPackages= this.packageEntries.size();
+ for (int i= 0; i < nPackages; i++) {
+ PackageEntry entry= (PackageEntry) this.packageEntries.get(i);
+ if (entry.compareTo(containerName, /*isStatic*/false, /*isBase*/false) == 0) {
+ ImportDeclEntry importEntry = entry.find(Signature.getSimpleName(fullTypeName));
+ importEntry.setIsBase(true);
+ return true;
+ }
+ }
+ return false;
+ }
+// SH}
+
+ private int getIndexAfterStatics() {
+ for (int i= 0; i < this.packageEntries.size(); i++) {
+ if (!((PackageEntry) this.packageEntries.get(i)).isStatic()) {
+ return i;
+ }
+ }
+ return this.packageEntries.size();
+ }
+
+//{ObjectTeams:
+/* orig:
+ private void sortIn(String typeContainerName, ImportDeclEntry decl, boolean isStatic) {
+ PackageEntry bestMatch= findBestMatch(typeContainerName, isStatic);
+ :giro */
+ private void sortIn(String typeContainerName, ImportDeclEntry decl, boolean isStatic, boolean isBase) {
+ PackageEntry bestMatch= findBestMatch(typeContainerName, isStatic, isBase);
+// SH}
+ if (bestMatch == null) {
+//{ObjectTeams: isBase:
+/* orig:
+ PackageEntry packEntry= new PackageEntry(typeContainerName, null, isStatic);
+ :giro */
+ PackageEntry packEntry= new PackageEntry(typeContainerName, null, isStatic, isBase);
+// SH}
+ packEntry.add(decl);
+ int insertPos= packEntry.isStatic() ? 0 : getIndexAfterStatics();
+//{ObjectTeams:
+ if (isBase) insertPos = getIndexAfterRegular();
+// SH}
+ this.packageEntries.add(insertPos, packEntry);
+ } else {
+ int cmp= typeContainerName.compareTo(bestMatch.getName());
+ if (cmp == 0) {
+ bestMatch.sortIn(decl);
+ } else {
+ // create a new package entry
+ String group= bestMatch.getGroupID();
+ if (group != null) {
+ if (!typeContainerName.startsWith(group)) {
+ group= null;
+ }
+ }
+//{ObjectTeams: isBase:
+/* orig:
+ PackageEntry packEntry= new PackageEntry(typeContainerName, group, isStatic);
+ :giro */
+ PackageEntry packEntry= new PackageEntry(typeContainerName, group, isStatic, isBase);
+// SH}
+ packEntry.add(decl);
+ int index= this.packageEntries.indexOf(bestMatch);
+ if (cmp < 0) { // insert ahead of best match
+ this.packageEntries.add(index, packEntry);
+ } else { // insert after best match
+ this.packageEntries.add(index + 1, packEntry);
+ }
+ }
+ }
+ }
+//{ObjectTeams: similar to getIndexAfterStatics:
+ private int getIndexAfterRegular() {
+ for (int i= 0; i < this.packageEntries.size(); i++) {
+ if (((PackageEntry) this.packageEntries.get(i)).isBase()) {
+ return i;
+ }
+ }
+ return this.packageEntries.size();
+ }
+// SH}
+
+ private IRegion evaluateReplaceRange(CompilationUnit root) {
+ List imports= root.imports();
+ if (!imports.isEmpty()) {
+ ImportDeclaration first= (ImportDeclaration) imports.get(0);
+ ImportDeclaration last= (ImportDeclaration) imports.get(imports.size() - 1);
+
+ int startPos= first.getStartPosition(); // no extended range for first: bug 121428
+ int endPos= root.getExtendedStartPosition(last) + root.getExtendedLength(last);
+ int endLine= root.getLineNumber(endPos);
+ if (endLine > 0) {
+ int nextLinePos= root.getPosition(endLine + 1, 0);
+ if (nextLinePos >= 0) {
+ int firstTypePos= getFirstTypeBeginPos(root);
+ if (firstTypePos != -1 && firstTypePos < nextLinePos) {
+ endPos= firstTypePos;
+ } else {
+ endPos= nextLinePos;
+ }
+ }
+ }
+ return new Region(startPos, endPos - startPos);
+ } else {
+ int start= getPackageStatementEndPos(root);
+ return new Region(start, 0);
+ }
+ }
+
+ public MultiTextEdit getResultingEdits(IProgressMonitor monitor) throws JavaModelException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+ try {
+ int importsStart= this.replaceRange.getOffset();
+ int importsLen= this.replaceRange.getLength();
+
+ String lineDelim= this.compilationUnit.findRecommendedLineSeparator();
+ IBuffer buffer= this.compilationUnit.getBuffer();
+
+ int currPos= importsStart;
+ MultiTextEdit resEdit= new MultiTextEdit();
+
+ if ((this.flags & F_NEEDS_LEADING_DELIM) != 0) {
+ // new import container
+ resEdit.addChild(new InsertEdit(currPos, lineDelim));
+ }
+
+ PackageEntry lastPackage= null;
+
+ Set onDemandConflicts= null;
+ if (this.findAmbiguousImports) {
+ onDemandConflicts= evaluateStarImportConflicts(monitor);
+ }
+
+ int spacesBetweenGroups= getSpacesBetweenImportGroups();
+
+ ArrayList stringsToInsert= new ArrayList();
+
+ int nPackageEntries= this.packageEntries.size();
+ for (int i= 0; i < nPackageEntries; i++) {
+ PackageEntry pack= (PackageEntry) this.packageEntries.get(i);
+ int nImports= pack.getNumberOfImports();
+
+ if (this.filterImplicitImports && !pack.isStatic() && isImplicitImport(pack.getName(), this.compilationUnit)) {
+ pack.removeAllNew(onDemandConflicts);
+ nImports= pack.getNumberOfImports();
+ }
+ if (nImports == 0) {
+ continue;
+ }
+
+
+ if (spacesBetweenGroups > 0) {
+ // add a space between two different groups by looking at the two adjacent imports
+ if (lastPackage != null && !pack.isComment() && !pack.isSameGroup(lastPackage)) {
+ ImportDeclEntry last= lastPackage.getImportAt(lastPackage.getNumberOfImports() - 1);
+ ImportDeclEntry first= pack.getImportAt(0);
+ if (!lastPackage.isComment() && (last.isNew() || first.isNew())) {
+ for (int k= spacesBetweenGroups; k > 0; k--) {
+ stringsToInsert.add(lineDelim);
+ }
+ }
+ }
+ }
+ lastPackage= pack;
+
+ boolean isStatic= pack.isStatic();
+ int threshold= isStatic ? this.staticImportOnDemandThreshold : this.importOnDemandThreshold;
+
+ boolean doStarImport= pack.hasStarImport(threshold, onDemandConflicts);
+ if (doStarImport && (pack.find("*") == null)) { //$NON-NLS-1$
+ String starImportString= pack.getName() + ".*"; //$NON-NLS-1$
+//{ObjectTeams: new 3. param:
+ String str= getNewImportString(starImportString, isStatic, false, lineDelim);
+// SH}
+ stringsToInsert.add(str);
+ }
+
+ for (int k= 0; k < nImports; k++) {
+ ImportDeclEntry currDecl= pack.getImportAt(k);
+ IRegion region= currDecl.getSourceRange();
+
+ if (region == null) { // new entry
+ if (!doStarImport || currDecl.isOnDemand() || (onDemandConflicts != null && onDemandConflicts.contains(currDecl.getSimpleName()))) {
+//{ObjectTeams: new 3. param:
+ String str= getNewImportString(currDecl.getElementName(), isStatic, currDecl.isBase(), lineDelim);
+// SH}
+ stringsToInsert.add(str);
+ }
+ } else {
+ if (!doStarImport || currDecl.isOnDemand() || onDemandConflicts == null || onDemandConflicts.contains(currDecl.getSimpleName())) {
+ int offset= region.getOffset();
+ removeAndInsertNew(buffer, currPos, offset, stringsToInsert, resEdit);
+ stringsToInsert.clear();
+//{ObjectTeams:
+ if (currDecl.isBase()) {
+ int endPos = offset+region.getLength();
+ int importPos = findInBuffer(buffer, "import", offset, endPos); //$NON-NLS-1$
+ int basePos = findInBuffer(buffer, "base", importPos, endPos); //$NON-NLS-1$
+ if (basePos == -1) // "base" not yet set
+ resEdit.addChild(new InsertEdit(importPos+"import ".length(), "base ")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+// SH}
+ currPos= offset + region.getLength();
+ }
+ }
+ }
+ }
+
+ int end= importsStart + importsLen;
+ removeAndInsertNew(buffer, currPos, end, stringsToInsert, resEdit);
+
+ if (importsLen == 0) {
+ if (!this.importsCreated.isEmpty() || !this.staticImportsCreated.isEmpty()) { // new import container
+ if ((this.flags & F_NEEDS_TRAILING_DELIM) != 0) {
+ resEdit.addChild(new InsertEdit(currPos, lineDelim));
+ }
+ } else {
+ return new MultiTextEdit(); // no changes
+ }
+ }
+ return resEdit;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private void removeAndInsertNew(IBuffer buffer, int contentOffset, int contentEnd, ArrayList stringsToInsert, MultiTextEdit resEdit) {
+ int pos= contentOffset;
+ for (int i= 0; i < stringsToInsert.size(); i++) {
+ String curr= (String) stringsToInsert.get(i);
+ int idx= findInBuffer(buffer, curr, pos, contentEnd);
+ if (idx != -1) {
+ if (idx != pos) {
+ resEdit.addChild(new DeleteEdit(pos, idx - pos));
+ }
+ pos= idx + curr.length();
+ } else {
+ resEdit.addChild(new InsertEdit(pos, curr));
+ }
+ }
+ if (pos < contentEnd) {
+ resEdit.addChild(new DeleteEdit(pos, contentEnd - pos));
+ }
+ }
+
+ private int findInBuffer(IBuffer buffer, String str, int start, int end) {
+ int pos= start;
+ int len= str.length();
+ if (pos + len > end || str.length() == 0) {
+ return -1;
+ }
+ char first= str.charAt(0);
+ int step= str.indexOf(first, 1);
+ if (step == -1) {
+ step= len;
+ }
+ while (pos + len <= end) {
+ if (buffer.getChar(pos) == first) {
+ int k= 1;
+ while (k < len && buffer.getChar(pos + k) == str.charAt(k)) {
+ k++;
+ }
+ if (k == len) {
+ return pos; // found
+ }
+ if (k < step) {
+ pos+= k;
+ } else {
+ pos+= step;
+ }
+ } else {
+ pos++;
+ }
+ }
+ return -1;
+ }
+
+ private Set evaluateStarImportConflicts(IProgressMonitor monitor) throws JavaModelException {
+ //long start= System.currentTimeMillis();
+
+ final HashSet/*String*/ onDemandConflicts= new HashSet();
+
+ IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { this.compilationUnit.getJavaProject() });
+
+ ArrayList/*<char[][]>*/ starImportPackages= new ArrayList();
+ ArrayList/*<char[][]>*/ simpleTypeNames= new ArrayList();
+ int nPackageEntries= this.packageEntries.size();
+ for (int i= 0; i < nPackageEntries; i++) {
+ PackageEntry pack= (PackageEntry) this.packageEntries.get(i);
+ if (!pack.isStatic() && pack.hasStarImport(this.importOnDemandThreshold, null)) {
+ starImportPackages.add(pack.getName().toCharArray());
+ for (int k= 0; k < pack.getNumberOfImports(); k++) {
+ ImportDeclEntry curr= pack.getImportAt(k);
+ if (!curr.isOnDemand() && !curr.isComment()) {
+ simpleTypeNames.add(curr.getSimpleName().toCharArray());
+ }
+ }
+ }
+ }
+ if (starImportPackages.isEmpty()) {
+ return null;
+ }
+
+ starImportPackages.add(this.compilationUnit.getParent().getElementName().toCharArray());
+ starImportPackages.add(JAVA_LANG.toCharArray());
+
+ char[][] allPackages= (char[][]) starImportPackages.toArray(new char[starImportPackages.size()][]);
+ char[][] allTypes= (char[][]) simpleTypeNames.toArray(new char[simpleTypeNames.size()][]);
+
+ TypeNameRequestor requestor= new TypeNameRequestor() {
+ HashMap foundTypes= new HashMap();
+
+ private String getTypeContainerName(char[] packageName, char[][] enclosingTypeNames) {
+ StringBuffer buf= new StringBuffer();
+ buf.append(packageName);
+ for (int i= 0; i < enclosingTypeNames.length; i++) {
+ if (buf.length() > 0)
+ buf.append('.');
+ buf.append(enclosingTypeNames[i]);
+ }
+ return buf.toString();
+ }
+
+ public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
+ String name= new String(simpleTypeName);
+ String containerName= getTypeContainerName(packageName, enclosingTypeNames);
+
+ String oldContainer= (String) this.foundTypes.put(name, containerName);
+ if (oldContainer != null && !oldContainer.equals(containerName)) {
+ onDemandConflicts.add(name);
+ }
+ }
+ };
+ new SearchEngine().searchAllTypeNames(allPackages, allTypes, scope, requestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
+ return onDemandConflicts;
+ }
+
+//{ObjectTeams: added 3. parameter
+ private String getNewImportString(String importName, boolean isStatic, boolean isBase, String lineDelim) {
+// SH}
+ StringBuffer buf= new StringBuffer();
+ buf.append("import "); //$NON-NLS-1$
+ if (isStatic) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+//{ObjectTeams: base import:
+ else if (isBase)
+ buf.append("base "); //$NON-NLS-1$
+// SH}
+
+ buf.append(importName);
+ if (insertSpaceBeforeSemicolon()) buf.append(' ');
+ buf.append(';');
+ buf.append(lineDelim);
+
+ if (isStatic) {
+ this.staticImportsCreated.add(importName);
+ } else {
+ this.importsCreated.add(importName);
+ }
+ return buf.toString();
+ }
+
+ private static int getFirstTypeBeginPos(CompilationUnit root) {
+ List types= root.types();
+ if (!types.isEmpty()) {
+ return root.getExtendedStartPosition(((ASTNode) types.get(0)));
+ }
+ return -1;
+ }
+
+ private int getPackageStatementEndPos(CompilationUnit root) {
+ PackageDeclaration packDecl= root.getPackage();
+ if (packDecl != null) {
+ int afterPackageStatementPos= -1;
+ int lineNumber= root.getLineNumber(packDecl.getStartPosition() + packDecl.getLength());
+ if (lineNumber >= 0) {
+ int lineAfterPackage= lineNumber + 1;
+ afterPackageStatementPos= root.getPosition(lineAfterPackage, 0);
+ }
+ if (afterPackageStatementPos < 0) {
+ this.flags|= F_NEEDS_LEADING_DELIM;
+ return packDecl.getStartPosition() + packDecl.getLength();
+ }
+ int firstTypePos= getFirstTypeBeginPos(root);
+ if (firstTypePos != -1 && firstTypePos <= afterPackageStatementPos) {
+ this.flags|= F_NEEDS_TRAILING_DELIM;
+ if (firstTypePos == afterPackageStatementPos) {
+ this.flags|= F_NEEDS_LEADING_DELIM;
+ }
+ return firstTypePos;
+ }
+ this.flags|= F_NEEDS_LEADING_DELIM;
+ return afterPackageStatementPos; // insert a line after after package statement
+ }
+ this.flags |= F_NEEDS_TRAILING_DELIM;
+ return 0;
+ }
+
+ public String toString() {
+ int nPackages= this.packageEntries.size();
+ StringBuffer buf= new StringBuffer("\n-----------------------\n"); //$NON-NLS-1$
+ for (int i= 0; i < nPackages; i++) {
+ PackageEntry entry= (PackageEntry) this.packageEntries.get(i);
+ if (entry.isStatic()) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+ buf.append(entry.toString());
+ }
+ return buf.toString();
+ }
+
+ private static final class ImportDeclEntry {
+
+ private String elementName;
+ private IRegion sourceRange;
+ private final boolean isStatic;
+//{ObjectTeams: base import
+ private boolean isBase = false;
+// SH}
+
+ public ImportDeclEntry(String elementName, boolean isStatic, IRegion sourceRange) {
+ this.elementName= elementName;
+ this.sourceRange= sourceRange;
+ this.isStatic= isStatic;
+ }
+
+ public String getElementName() {
+ return this.elementName;
+ }
+
+ public int compareTo(String fullName, boolean isStaticImport) {
+ int cmp= this.elementName.compareTo(fullName);
+ if (cmp == 0) {
+ if (this.isStatic == isStaticImport) {
+ return 0;
+ }
+ return this.isStatic ? -1 : 1;
+ }
+ return cmp;
+ }
+
+ public String getSimpleName() {
+ return Signature.getSimpleName(this.elementName);
+ }
+
+ public boolean isOnDemand() {
+ return this.elementName != null && this.elementName.endsWith(".*"); //$NON-NLS-1$
+ }
+
+ public boolean isStatic() {
+ return this.isStatic;
+ }
+
+ public boolean isNew() {
+ return this.sourceRange == null;
+ }
+
+ public boolean isComment() {
+ return this.elementName == null;
+ }
+
+ public IRegion getSourceRange() {
+ return this.sourceRange;
+ }
+//{ObjectTeams: base import:
+ public void setIsBase(boolean flag) {
+ this.isBase = flag;
+ }
+ public boolean isBase() {
+ return this.isBase;
+ }
+// SH}
+ }
+
+ /*
+ * Internal element for the import structure: A container for imports
+ * of all types from the same package
+ */
+ private final static class PackageEntry {
+ private String name;
+ private ArrayList importEntries;
+ private String group;
+ private boolean isStatic;
+//{ObjectTeams: base import
+ private boolean isBase;
+// SH}
+
+ /**
+ * Comment package entry
+ */
+ public PackageEntry() {
+ this("!", null, false); //$NON-NLS-1$
+ }
+
+ /**
+ * @param name Name of the package entry. e.g. org.eclipse.jdt.ui, containing imports like
+ * org.eclipse.jdt.ui.JavaUI.
+ * @param group The index of the preference order entry assigned
+ * different group id's will result in spacers between the entries
+ */
+ public PackageEntry(String name, String group, boolean isStatic) {
+ this.name= name;
+ this.importEntries= new ArrayList(5);
+ this.group= group;
+ this.isStatic= isStatic;
+ }
+//{ObjectTeams: base import
+ public PackageEntry(String name, String group, boolean isStatic, boolean isBase) {
+ this(name, group, isStatic);
+ this.isBase = isBase;
+ }
+ public boolean isBase() {
+ return this.isBase;
+ }
+// SH}
+
+
+ public boolean isStatic() {
+ return this.isStatic;
+ }
+
+//{ObjectTeams: also compare base flag:
+/* orig:
+ public int compareTo(String otherName, boolean isOtherStatic) {
+ :giro */
+ public int compareTo(String otherName, boolean isOtherStatic, boolean isOtherBase)
+ {
+// SH}
+ int cmp= this.name.compareTo(otherName);
+ if (cmp == 0) {
+ if (this.isStatic == isOtherStatic) {
+//{ObjectTeams: more comparison:
+ if (this.isBase == isOtherBase)
+// SH}
+ return 0;
+ }
+ return this.isStatic ? -1 : 1;
+ }
+ return cmp;
+ }
+
+ public void sortIn(ImportDeclEntry imp) {
+ String fullImportName= imp.getElementName();
+ int insertPosition= -1;
+ int nInports= this.importEntries.size();
+ for (int i= 0; i < nInports; i++) {
+ ImportDeclEntry curr= getImportAt(i);
+ if (!curr.isComment()) {
+ int cmp= curr.compareTo(fullImportName, imp.isStatic());
+ if (cmp == 0) {
+ return; // exists already
+ } else if (cmp > 0 && insertPosition == -1) {
+ insertPosition= i;
+ }
+ }
+ }
+ if (insertPosition == -1) {
+ this.importEntries.add(imp);
+ } else {
+ this.importEntries.add(insertPosition, imp);
+ }
+ }
+
+
+ public void add(ImportDeclEntry imp) {
+ this.importEntries.add(imp);
+ }
+
+ public ImportDeclEntry find(String simpleName) {
+ int nInports= this.importEntries.size();
+ for (int i= 0; i < nInports; i++) {
+ ImportDeclEntry curr= getImportAt(i);
+ if (!curr.isComment()) {
+ String currName= curr.getElementName();
+ if (currName.endsWith(simpleName)) {
+ int dotPos= currName.length() - simpleName.length() - 1;
+ if ((dotPos == -1) || (dotPos > 0 && currName.charAt(dotPos) == '.')) {
+ return curr;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean remove(String fullName, boolean isStaticImport) {
+ int nInports= this.importEntries.size();
+ for (int i= 0; i < nInports; i++) {
+ ImportDeclEntry curr= getImportAt(i);
+ if (!curr.isComment() && curr.compareTo(fullName, isStaticImport) == 0) {
+ this.importEntries.remove(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void removeAllNew(Set onDemandConflicts) {
+ int nInports= this.importEntries.size();
+ for (int i= nInports - 1; i >= 0; i--) {
+ ImportDeclEntry curr= getImportAt(i);
+ if (curr.isNew() /*&& (onDemandConflicts == null || onDemandConflicts.contains(curr.getSimpleName()))*/) {
+ this.importEntries.remove(i);
+ }
+ }
+ }
+
+ public ImportDeclEntry getImportAt(int index) {
+ return (ImportDeclEntry) this.importEntries.get(index);
+ }
+
+ public boolean hasStarImport(int threshold, Set explicitImports) {
+ if (isComment() || isDefaultPackage()) { // can not star import default package
+ return false;
+ }
+ int nImports= getNumberOfImports();
+ int count= 0;
+ boolean containsNew= false;
+ for (int i= 0; i < nImports; i++) {
+ ImportDeclEntry curr= getImportAt(i);
+ if (curr.isOnDemand()) {
+ return true;
+ }
+ if (!curr.isComment()) {
+ count++;
+ boolean isExplicit= !curr.isStatic() && (explicitImports != null) && explicitImports.contains(curr.getSimpleName());
+ containsNew |= curr.isNew() && !isExplicit;
+ }
+ }
+ return (count >= threshold) && containsNew;
+ }
+
+ public int getNumberOfImports() {
+ return this.importEntries.size();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getGroupID() {
+ return this.group;
+ }
+
+ public void setGroupID(String groupID) {
+ this.group= groupID;
+ }
+
+ public boolean isSameGroup(PackageEntry other) {
+ if (this.group == null) {
+ return other.getGroupID() == null;
+ } else {
+ return this.group.equals(other.getGroupID()) && (this.isStatic == other.isStatic());
+ }
+ }
+
+//{ObjectTeams: restore method removed as of 3.5:
+ public ImportDeclEntry getLast() {
+ int nImports= getNumberOfImports();
+ if (nImports > 0) {
+ return getImportAt(nImports - 1);
+ }
+ return null;
+ }
+// SH}
+
+ public boolean isComment() {
+ return "!".equals(this.name); //$NON-NLS-1$
+ }
+
+ public boolean isDefaultPackage() {
+ return this.name.length() == 0;
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ if (isComment()) {
+ buf.append("comment\n"); //$NON-NLS-1$
+ } else {
+ buf.append(this.name); buf.append(", groupId: "); buf.append(this.group); buf.append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ int nImports= getNumberOfImports();
+ for (int i= 0; i < nImports; i++) {
+ ImportDeclEntry curr= getImportAt(i);
+ buf.append(" "); //$NON-NLS-1$
+ if (curr.isStatic()) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+//{ObjectTeams:
+ else if (curr.isBase()) {
+ buf.append("base "); //$NON-NLS-1$
+ }
+// SH}
+ buf.append(curr.getSimpleName());
+ if (curr.isNew()) {
+ buf.append(" (new)"); //$NON-NLS-1$
+ }
+ buf.append("\n"); //$NON-NLS-1$
+ }
+ }
+ return buf.toString();
+ }
+ }
+
+ public String[] getCreatedImports() {
+ return (String[]) this.importsCreated.toArray(new String[this.importsCreated.size()]);
+ }
+
+ public String[] getCreatedStaticImports() {
+ return (String[]) this.staticImportsCreated.toArray(new String[this.staticImportsCreated.size()]);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineCommentEndOffsets.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineCommentEndOffsets.java
new file mode 100644
index 000000000..772fa6aad
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineCommentEndOffsets.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.LineComment;
+import org.eclipse.jdt.core.formatter.IndentManipulation;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class LineCommentEndOffsets {
+
+ private int[] offsets;
+ private final List commentList;
+
+ public LineCommentEndOffsets(List commentList) {
+ this.commentList= commentList;
+ this.offsets= null; // create on demand
+ }
+
+ private int[] getOffsets() {
+ if (this.offsets == null) {
+ if (this.commentList != null) {
+ int nComments= this.commentList.size();
+ // count the number of line comments
+ int count= 0;
+ for (int i= 0; i < nComments; i++) {
+ Object curr= this.commentList.get(i);
+ if (curr instanceof LineComment) {
+ count++;
+ }
+ }
+ // fill the offset table
+ this.offsets= new int[count];
+ for (int i= 0, k= 0; i < nComments; i++) {
+ Object curr= this.commentList.get(i);
+ if (curr instanceof LineComment) {
+ LineComment comment= (LineComment) curr;
+ this.offsets[k++]= comment.getStartPosition() + comment.getLength();
+ }
+ }
+ } else {
+ this.offsets= Util.EMPTY_INT_ARRAY;
+ }
+ }
+ return this.offsets;
+ }
+
+ public boolean isEndOfLineComment(int offset) {
+ return offset >= 0 && Arrays.binarySearch(getOffsets(), offset) >= 0;
+ }
+
+ public boolean isEndOfLineComment(int offset, char[] content) {
+ if (offset < 0 || (offset < content.length && !IndentManipulation.isLineDelimiterChar(content[offset]))) {
+ return false;
+ }
+ return Arrays.binarySearch(getOffsets(), offset) >= 0;
+ }
+
+ public boolean remove(int offset) {
+ int[] offsetArray= getOffsets(); // returns the shared array
+ int index= Arrays.binarySearch(offsetArray, offset);
+ if (index >= 0) {
+ if (index > 0) {
+ // shift from the beginning and insert -1 (smallest number) at the beginning
+ // 1, 2, 3, x, 4, 5 -> -1, 1, 2, 3, 4, 5
+ System.arraycopy(offsetArray, 0, offsetArray, 1, index);
+ }
+ offsetArray[0]= -1;
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java
new file mode 100644
index 000000000..fca9ea5e0
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ *
+ */
+public abstract class LineInformation {
+
+ public static LineInformation create(final IDocument doc) {
+ return new LineInformation() {
+ public int getLineOfOffset(int offset) {
+ try {
+ return doc.getLineOfOffset(offset);
+ } catch (BadLocationException e) {
+ return -1;
+ }
+ }
+
+ public int getLineOffset(int line) {
+ try {
+ return doc.getLineOffset(line);
+ } catch (BadLocationException e) {
+ return -1;
+ }
+ }
+ };
+ }
+
+ public static LineInformation create(final CompilationUnit astRoot) {
+ return new LineInformation() {
+ public int getLineOfOffset(int offset) {
+ return astRoot.getLineNumber(offset) - 1;
+ }
+ public int getLineOffset(int line) {
+ return astRoot.getPosition(line + 1, 0);
+ }
+ };
+ }
+
+
+
+ public abstract int getLineOfOffset(int offset);
+ public abstract int getLineOffset(int line);
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ListRewriteEvent.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ListRewriteEvent.java
new file mode 100644
index 000000000..e32af7fee
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ListRewriteEvent.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+
+/**
+ *
+ */
+public class ListRewriteEvent extends RewriteEvent {
+
+ public final static int NEW= 1;
+ public final static int OLD= 2;
+ public final static int BOTH= NEW | OLD;
+
+ /** original list of 'ASTNode' */
+ private List originalNodes;
+
+ /** list of type 'RewriteEvent' */
+ private List listEntries;
+
+ /**
+ * Creates a ListRewriteEvent from the original ASTNodes. The resulting event
+ * represents the unmodified list.
+ * @param originalNodes The original nodes (type ASTNode)
+ */
+ public ListRewriteEvent(List originalNodes) {
+ this.originalNodes= new ArrayList(originalNodes);
+ }
+
+ /**
+ * Creates a ListRewriteEvent from existing rewrite events.
+ * @param children The rewrite events for this list.
+ */
+ public ListRewriteEvent(RewriteEvent[] children) {
+ this.listEntries= new ArrayList(children.length * 2);
+ this.originalNodes= new ArrayList(children.length * 2);
+ for (int i= 0; i < children.length; i++) {
+ RewriteEvent curr= children[i];
+ this.listEntries.add(curr);
+ if (curr.getOriginalValue() != null) {
+ this.originalNodes.add(curr.getOriginalValue());
+ }
+ }
+ }
+
+ private List getEntries() {
+ if (this.listEntries == null) {
+ // create if not yet existing
+ int nNodes= this.originalNodes.size();
+ this.listEntries= new ArrayList(nNodes * 2);
+ for (int i= 0; i < nNodes; i++) {
+ ASTNode node= (ASTNode) this.originalNodes.get(i);
+ // all nodes unchanged
+ this.listEntries.add(new NodeRewriteEvent(node, node));
+ }
+ }
+ return this.listEntries;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.ASTRewriteChange#getChangeKind()
+ */
+ public int getChangeKind() {
+ if (this.listEntries != null) {
+ for (int i= 0; i < this.listEntries.size(); i++) {
+ RewriteEvent curr= (RewriteEvent) this.listEntries.get(i);
+ if (curr.getChangeKind() != UNCHANGED) {
+ return CHILDREN_CHANGED;
+ }
+ }
+ }
+ return UNCHANGED;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.ASTRewriteChange#isListChange()
+ */
+ public boolean isListRewrite() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#getChildren()
+ */
+ public RewriteEvent[] getChildren() {
+ List entries= getEntries();
+ return (RewriteEvent[]) entries.toArray(new RewriteEvent[entries.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#getOriginalNode()
+ */
+ public Object getOriginalValue() {
+ return this.originalNodes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#getNewValue()
+ */
+ public Object getNewValue() {
+ List entries= getEntries();
+ ArrayList res= new ArrayList(entries.size());
+ for (int i= 0; i < entries.size(); i++) {
+ RewriteEvent curr= (RewriteEvent) entries.get(i);
+ Object newVal= curr.getNewValue();
+ if (newVal != null) {
+ res.add(newVal);
+ }
+ }
+ return res;
+ }
+
+ // API to modify the list nodes
+
+ public RewriteEvent removeEntry(ASTNode originalEntry) {
+ return replaceEntry(originalEntry, null);
+ }
+
+ public RewriteEvent replaceEntry(ASTNode entry, ASTNode newEntry) {
+ if (entry == null) {
+ throw new IllegalArgumentException();
+ }
+
+ List entries= getEntries();
+ int nEntries= entries.size();
+ for (int i= 0; i < nEntries; i++) {
+ NodeRewriteEvent curr= (NodeRewriteEvent) entries.get(i);
+ if (curr.getOriginalValue() == entry || curr.getNewValue() == entry) {
+ curr.setNewValue(newEntry);
+ if (curr.getNewValue() == null && curr.getOriginalValue() == null) { // removed an inserted node
+ entries.remove(i);
+ return null;
+ }
+ return curr;
+ }
+ }
+ return null;
+ }
+
+ public void revertChange(NodeRewriteEvent event) {
+ Object originalValue = event.getOriginalValue();
+ if (originalValue == null) {
+ List entries= getEntries();
+ entries.remove(event);
+ } else {
+ event.setNewValue(originalValue);
+ }
+ }
+
+ public int getIndex(ASTNode node, int kind) {
+ List entries= getEntries();
+ for (int i= entries.size() - 1; i >= 0; i--) {
+ RewriteEvent curr= (RewriteEvent) entries.get(i);
+ if (((kind & OLD) != 0) && (curr.getOriginalValue() == node)) {
+ return i;
+ }
+ if (((kind & NEW) != 0) && (curr.getNewValue() == node)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public RewriteEvent insert(ASTNode insertedNode, int insertIndex) {
+ NodeRewriteEvent change= new NodeRewriteEvent(null, insertedNode);
+ if (insertIndex != -1) {
+ getEntries().add(insertIndex, change);
+ } else {
+ getEntries().add(change);
+ }
+ return change;
+ }
+
+ public void setNewValue(ASTNode newValue, int insertIndex) {
+ NodeRewriteEvent curr= (NodeRewriteEvent) getEntries().get(insertIndex);
+ curr.setNewValue(newValue);
+ }
+
+ public int getChangeKind(int index) {
+ return ((NodeRewriteEvent) getEntries().get(index)).getChangeKind();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ buf.append(" [list change\n\t"); //$NON-NLS-1$
+
+ RewriteEvent[] events= getChildren();
+ for (int i= 0; i < events.length; i++) {
+ if (i != 0) {
+ buf.append("\n\t"); //$NON-NLS-1$
+ }
+ buf.append(events[i]);
+ }
+ buf.append("\n]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeInfoStore.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeInfoStore.java
new file mode 100644
index 000000000..6c03454cb
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeInfoStore.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+
+/**
+ *
+ */
+public final class NodeInfoStore {
+ private AST ast;
+
+ private Map placeholderNodes;
+ private Set collapsedNodes;
+
+ public NodeInfoStore(AST ast) {
+ super();
+ this.ast= ast;
+ this.placeholderNodes= null;
+ this.collapsedNodes= null;
+ }
+
+ /**
+ * Marks a node as a placehoder for a plain string content. The type of the node should correspond to the
+ * code's code content.
+ * @param placeholder The placeholder node that acts for the string content.
+ * @param code The string content.
+ */
+ public final void markAsStringPlaceholder(ASTNode placeholder, String code) {
+ StringPlaceholderData data= new StringPlaceholderData();
+ data.code= code;
+ setPlaceholderData(placeholder, data);
+ }
+
+ /**
+ * Marks a node as a copy or move target. The copy target represents a copied node at the target (copied) site.
+ * @param target The node at the target site. Can be a placeholder node but also the source node itself.
+ * @param copySource The info at the source site.
+ */
+ public final void markAsCopyTarget(ASTNode target, CopySourceInfo copySource) {
+ CopyPlaceholderData data= new CopyPlaceholderData();
+ data.copySource= copySource;
+ setPlaceholderData(target, data);
+ }
+
+ /**
+ * Creates a placeholder node of the given type. <code>null</code> if the type is not supported
+ * @param nodeType Type of the node to create. Use the type constants in {@link NodeInfoStore}.
+ * @return Returns a place holder node.
+ */
+ public final ASTNode newPlaceholderNode(int nodeType) {
+ try {
+ ASTNode node= this.ast.createInstance(nodeType);
+ switch (node.getNodeType()) {
+ case ASTNode.FIELD_DECLARATION:
+ ((FieldDeclaration) node).fragments().add(this.ast.newVariableDeclarationFragment());
+ break;
+ case ASTNode.MODIFIER:
+ ((Modifier) node).setKeyword(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case ASTNode.TRY_STATEMENT :
+ ((TryStatement) node).setFinally(this.ast.newBlock()); // have to set at least a finally block to be legal code
+ break;
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+ ((VariableDeclarationExpression) node).fragments().add(this.ast.newVariableDeclarationFragment());
+ break;
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT :
+ ((VariableDeclarationStatement) node).fragments().add(this.ast.newVariableDeclarationFragment());
+ break;
+ case ASTNode.PARAMETERIZED_TYPE :
+ ((ParameterizedType) node).typeArguments().add(this.ast.newWildcardType());
+ break;
+ }
+ return node;
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+
+ // collapsed nodes: in source: use one node that represents many; to be used as
+ // copy/move source or to replace at once.
+ // in the target: one block node that is not flattened.
+
+ public Block createCollapsePlaceholder() {
+ Block placeHolder= this.ast.newBlock();
+ if (this.collapsedNodes == null) {
+ this.collapsedNodes= new HashSet();
+ }
+ this.collapsedNodes.add(placeHolder);
+ return placeHolder;
+ }
+
+ public boolean isCollapsed(ASTNode node) {
+ if (this.collapsedNodes != null) {
+ return this.collapsedNodes.contains(node);
+ }
+ return false;
+ }
+
+ public Object getPlaceholderData(ASTNode node) {
+ if (this.placeholderNodes != null) {
+ return this.placeholderNodes.get(node);
+ }
+ return null;
+ }
+
+ private void setPlaceholderData(ASTNode node, PlaceholderData data) {
+ if (this.placeholderNodes == null) {
+ this.placeholderNodes= new IdentityHashMap();
+ }
+ this.placeholderNodes.put(node, data);
+ }
+
+ static class PlaceholderData {
+ // base class
+ }
+
+ protected static final class CopyPlaceholderData extends PlaceholderData {
+ public CopySourceInfo copySource;
+ public String toString() {
+ return "[placeholder " + this.copySource +"]"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+
+ protected static final class StringPlaceholderData extends PlaceholderData {
+ public String code;
+ public String toString() {
+ return "[placeholder string: " + this.code +"]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ *
+ */
+ public void clear() {
+ this.placeholderNodes= null;
+ this.collapsedNodes= null;
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeRewriteEvent.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeRewriteEvent.java
new file mode 100644
index 000000000..cb063ebb7
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/NodeRewriteEvent.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+
+
+/**
+ *
+ */
+public class NodeRewriteEvent extends RewriteEvent {
+
+ private Object originalValue;
+ private Object newValue;
+
+ public NodeRewriteEvent(Object originalValue, Object newValue) {
+ this.originalValue= originalValue;
+ this.newValue= newValue;
+ }
+
+ /**
+ * @return Returns the new value.
+ */
+ public Object getNewValue() {
+ return this.newValue;
+ }
+
+ /**
+ * @return Returns the original value.
+ */
+ public Object getOriginalValue() {
+ return this.originalValue;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#getChangeKind()
+ */
+ public int getChangeKind() {
+ if (this.originalValue == this.newValue) {
+ return UNCHANGED;
+ }
+ if (this.originalValue == null) {
+ return INSERTED;
+ }
+ if (this.newValue == null) {
+ return REMOVED;
+ }
+ if (this.originalValue.equals(this.newValue)) {
+ return UNCHANGED;
+ }
+ return REPLACED;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#isListRewrite()
+ */
+ public boolean isListRewrite() {
+ return false;
+ }
+
+ /*
+ * Sets a new value for the new node. Internal access only.
+ * @param newValue The new value to set.
+ */
+ public void setNewValue(Object newValue) {
+ this.newValue= newValue;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.RewriteEvent#getChildren()
+ */
+ public RewriteEvent[] getChildren() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ switch (getChangeKind()) {
+ case INSERTED:
+ buf.append(" [inserted: "); //$NON-NLS-1$
+ buf.append(getNewValue());
+ buf.append(']');
+ break;
+ case REPLACED:
+ buf.append(" [replaced: "); //$NON-NLS-1$
+ buf.append(getOriginalValue());
+ buf.append(" -> "); //$NON-NLS-1$
+ buf.append(getNewValue());
+ buf.append(']');
+ break;
+ case REMOVED:
+ buf.append(" [removed: "); //$NON-NLS-1$
+ buf.append(getOriginalValue());
+ buf.append(']');
+ break;
+ default:
+ buf.append(" [unchanged]"); //$NON-NLS-1$
+ }
+ return buf.toString();
+ }
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEvent.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEvent.java
new file mode 100644
index 000000000..e957b360b
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEvent.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+
+/**
+ *
+ */
+public abstract class RewriteEvent {
+
+ /**
+ * Change kind to describe that the event is an insert event.
+ * Does not apply for list events.
+ */
+ public static final int INSERTED= 1;
+
+ /**
+ * Change kind to describe that the event is an remove event.
+ * Does not apply for list events.
+ */
+ public static final int REMOVED= 2;
+
+ /**
+ * Change kind to describe that the event is an replace event.
+ * Does not apply for list events.
+ */
+ public static final int REPLACED= 4;
+
+ /**
+ * Change kind to signal that children changed. Does only apply for list events.
+ */
+ public static final int CHILDREN_CHANGED= 8;
+
+ /**
+ * Change kind to signal that the property did not change
+ */
+ public static final int UNCHANGED= 0;
+
+ /**
+ * @return Returns the event's change kind.
+ */
+ public abstract int getChangeKind();
+
+ /**
+ * @return Returns true if the given event is a list event.
+ */
+ public abstract boolean isListRewrite();
+
+ /**
+ * @return Returns the original value. For lists this is a <code>List<code> of ASTNode's, for non-list
+ * events this can be an ASTNode (for node properties), Integer (for an integer property),
+ * Boolean (for boolean node properties) or properties like Operator.
+ * <code>null</code> is returned if the event is a insert event.
+ */
+ public abstract Object getOriginalValue();
+
+ /**
+ * @return Returns the new value. For lists this is a <code>List<code> of ASTNode's, for non-list
+ * events this can be an ASTNode (for node properties), Integer (for an integer property),
+ * Boolean (for boolean node properties) or properties like Operator.
+ * <code>null</code> is returned if the event is a remove event.
+ */
+ public abstract Object getNewValue();
+
+ /**
+ * @return Return the events describing the changes in a list. returns <code>null</code> if the
+ * event is not a list event.
+ */
+ public abstract RewriteEvent[] getChildren();
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
new file mode 100644
index 000000000..7b0d5974d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
@@ -0,0 +1,872 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.*;
+
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
+import org.eclipse.text.edits.TextEditGroup;
+
+
+/**
+ * Stores all rewrite events, descriptions of events and knows which nodes
+ * are copy or move sources or tracked.
+ */
+public final class RewriteEventStore {
+
+
+ public static final class PropertyLocation {
+ private final ASTNode parent;
+ private final StructuralPropertyDescriptor property;
+
+ public PropertyLocation(ASTNode parent, StructuralPropertyDescriptor property) {
+ this.parent= parent;
+ this.property= property;
+ }
+
+ public ASTNode getParent() {
+ return this.parent;
+ }
+
+ public StructuralPropertyDescriptor getProperty() {
+ return this.property;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj != null && obj.getClass().equals(getClass())) {
+ PropertyLocation other= (PropertyLocation) obj;
+ return other.getParent().equals(getParent()) && other.getProperty().equals(getProperty());
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return getParent().hashCode() + getProperty().hashCode();
+ }
+
+ }
+
+ /**
+ * Interface that allows to override the way how children are accessed from
+ * a parent. Use this interface when the rewriter is set up on an already
+ * modified AST's (as it is the case in the old ASTRewrite infrastructure)
+ */
+ public static interface INodePropertyMapper {
+ /**
+ * Returns the node attribute for a given property name.
+ * @param parent The parent node
+ * @param childProperty The child property to access
+ * @return The child node at the given property location.
+ */
+ Object getOriginalValue(ASTNode parent, StructuralPropertyDescriptor childProperty);
+ }
+
+ /*
+ * Store element to associate event and node position/
+ */
+ private static class EventHolder {
+ public final ASTNode parent;
+ public final StructuralPropertyDescriptor childProperty;
+ public final RewriteEvent event;
+
+ public EventHolder(ASTNode parent, StructuralPropertyDescriptor childProperty, RewriteEvent change) {
+ this.parent= parent;
+ this.childProperty= childProperty;
+ this.event= change;
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ buf.append(this.parent).append(" - "); //$NON-NLS-1$
+ buf.append(this.childProperty.getId()).append(": "); //$NON-NLS-1$
+ buf.append(this.event).append('\n');
+ return buf.toString();
+ }
+ }
+
+ public static class CopySourceInfo implements Comparable {
+ public final PropertyLocation location; // can be null, only used to mark as removed on move
+ private final ASTNode node;
+ public final boolean isMove;
+
+ public CopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
+ this.location= location;
+ this.node= node;
+ this.isMove= isMove;
+ }
+
+ public ASTNode getNode() {
+ return this.node;
+ }
+
+ public int compareTo(Object o2) {
+ CopySourceInfo r2= (CopySourceInfo) o2;
+
+ int startDiff= getNode().getStartPosition() - r2.getNode().getStartPosition();
+ if (startDiff != 0) {
+ return startDiff; // insert before if start node is first
+ }
+
+ if (r2.isMove != this.isMove) {
+ return this.isMove ? -1 : 1; // first move then copy
+ }
+ return 0;
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ if (this.isMove) {
+ buf.append("move source: "); //$NON-NLS-1$
+ } else {
+ buf.append("copy source: "); //$NON-NLS-1$
+ }
+ buf.append(this.node);
+ return buf.toString();
+ }
+ }
+
+ private static class NodeRangeInfo implements Comparable {
+ private final ASTNode first;
+ private final ASTNode last;
+ public final CopySourceInfo copyInfo; // containing the internal placeholder and the 'isMove' flag
+ public final ASTNode replacingNode;
+ public final TextEditGroup editGroup;
+
+ public NodeRangeInfo(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, CopySourceInfo copyInfo, ASTNode replacingNode, TextEditGroup editGroup) {
+ this.first= first;
+ this.last= last;
+ this.copyInfo= copyInfo;
+ this.replacingNode= replacingNode;
+ this.editGroup= editGroup;
+ }
+
+ public ASTNode getStartNode() {
+ return this.first;
+ }
+
+ public ASTNode getEndNode() {
+ return this.last;
+ }
+
+ public boolean isMove() {
+ return this.copyInfo.isMove;
+ }
+
+ public Block getInternalPlaceholder() {
+ return (Block) this.copyInfo.getNode();
+ }
+
+ public int compareTo(Object o2) {
+ NodeRangeInfo r2= (NodeRangeInfo) o2;
+
+ int startDiff= getStartNode().getStartPosition() - r2.getStartNode().getStartPosition();
+ if (startDiff != 0) {
+ return startDiff; // insert before if start node is first
+ }
+ int endDiff= getEndNode().getStartPosition() - r2.getEndNode().getStartPosition();
+ if (endDiff != 0) {
+ return -endDiff; // insert before if length is longer
+ }
+ if (r2.isMove() != isMove()) {
+ return isMove() ? -1 : 1; // first move then copy
+ }
+ return 0;
+ }
+
+ public void updatePlaceholderSourceRanges(TargetSourceRangeComputer sourceRangeComputer) {
+ TargetSourceRangeComputer.SourceRange startRange= sourceRangeComputer.computeSourceRange(getStartNode());
+ TargetSourceRangeComputer.SourceRange endRange= sourceRangeComputer.computeSourceRange(getEndNode());
+ int startPos= startRange.getStartPosition();
+ int endPos= endRange.getStartPosition() + endRange.getLength();
+
+ Block internalPlaceholder= getInternalPlaceholder();
+ internalPlaceholder.setSourceRange(startPos, endPos - startPos);
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ if (this.first != this.last) {
+ buf.append("range "); //$NON-NLS-1$
+ }
+ if (isMove()) {
+ buf.append("move source: "); //$NON-NLS-1$
+ } else {
+ buf.append("copy source: "); //$NON-NLS-1$
+ }
+ buf.append(this.first);
+ buf.append(" - "); //$NON-NLS-1$
+ buf.append(this.last);
+ return buf.toString();
+ }
+
+
+ }
+
+ /**
+ * Iterates over all event parent nodes, tracked nodes and all copy/move sources
+ */
+ private class ParentIterator implements Iterator {
+
+ private Iterator eventIter;
+ private Iterator sourceNodeIter;
+ private Iterator rangeNodeIter;
+ private Iterator trackedNodeIter;
+
+ public ParentIterator() {
+ this.eventIter= RewriteEventStore.this.eventLookup.keySet().iterator();
+ if (RewriteEventStore.this.nodeCopySources != null) {
+ this.sourceNodeIter= RewriteEventStore.this.nodeCopySources.iterator();
+ } else {
+ this.sourceNodeIter= Collections.EMPTY_LIST.iterator();
+ }
+ if (RewriteEventStore.this.nodeRangeInfos != null) {
+ this.rangeNodeIter= RewriteEventStore.this.nodeRangeInfos.keySet().iterator();
+ } else {
+ this.rangeNodeIter= Collections.EMPTY_LIST.iterator();
+ }
+ if (RewriteEventStore.this.trackedNodes != null) {
+ this.trackedNodeIter= RewriteEventStore.this.trackedNodes.keySet().iterator();
+ } else {
+ this.trackedNodeIter= Collections.EMPTY_LIST.iterator();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return this.eventIter.hasNext() || this.sourceNodeIter.hasNext() || this.rangeNodeIter.hasNext() || this.trackedNodeIter.hasNext();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+ if (this.eventIter.hasNext()) {
+ return this.eventIter.next();
+ }
+ if (this.sourceNodeIter.hasNext()) {
+ return ((CopySourceInfo) this.sourceNodeIter.next()).getNode();
+ }
+ if (this.rangeNodeIter.hasNext()) {
+ return ((PropertyLocation) this.rangeNodeIter.next()).getParent();
+ }
+ return this.trackedNodeIter.next();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public final static int NEW= 1;
+ public final static int ORIGINAL= 2;
+ public final static int BOTH= NEW | ORIGINAL;
+
+
+ /** all events by parent*/
+ final Map eventLookup;
+
+ /** cache for last accessed event */
+ private EventHolder lastEvent;
+
+ /** Maps events to group descriptions */
+ private Map editGroups;
+
+ /** Stores which nodes are source of a copy or move (list of CopySourceInfo)*/
+ List nodeCopySources;
+
+ /** Stores node ranges that are used to copy or move (map of <PropertyLocation, CopyRangeInfo>)*/
+ Map nodeRangeInfos;
+
+ /** Stores which nodes are tracked and the corresponding edit group*/
+ Map trackedNodes;
+
+ /** Stores which inserted nodes bound to the previous node. If not, a node is
+ * always bound to the next node */
+ private Set insertBoundToPrevious;
+
+ /** optional mapper to allow fix already modified AST trees */
+ private INodePropertyMapper nodePropertyMapper;
+
+ private static final String INTERNAL_PLACEHOLDER_PROPERTY= "rewrite_internal_placeholder"; //$NON-NLS-1$
+
+ public RewriteEventStore() {
+ this.eventLookup= new HashMap();
+ this.lastEvent= null;
+
+ this.editGroups= null; // lazy initialization
+
+ this.trackedNodes= null;
+ this.insertBoundToPrevious= null;
+
+ this.nodePropertyMapper= null;
+ this.nodeCopySources= null;
+ this.nodeRangeInfos= null;
+ }
+
+ /**
+ * Override the default way how to access children from a parent node.
+ * @param nodePropertyMapper The new <code>INodePropertyMapper</code> or
+ * <code>null</code>. to use the default.
+ */
+ public void setNodePropertyMapper(INodePropertyMapper nodePropertyMapper) {
+ this.nodePropertyMapper= nodePropertyMapper;
+ }
+
+ public void clear() {
+ this.eventLookup.clear();
+ this.lastEvent= null;
+ this.trackedNodes= null;
+
+ this.editGroups= null; // lazy initialization
+ this.insertBoundToPrevious= null;
+ this.nodeCopySources= null;
+ }
+
+ public void addEvent(ASTNode parent, StructuralPropertyDescriptor childProperty, RewriteEvent event) {
+ validateHasChildProperty(parent, childProperty);
+
+ if (event.isListRewrite()) {
+ validateIsListProperty(childProperty);
+ }
+
+ EventHolder holder= new EventHolder(parent, childProperty, event);
+
+ List entriesList = (List) this.eventLookup.get(parent);
+ if (entriesList != null) {
+ for (int i= 0; i < entriesList.size(); i++) {
+ EventHolder curr= (EventHolder) entriesList.get(i);
+ if (curr.childProperty == childProperty) {
+ entriesList.set(i, holder);
+ this.lastEvent= null;
+ return;
+ }
+ }
+ } else {
+ entriesList= new ArrayList(3);
+ this.eventLookup.put(parent, entriesList);
+ }
+ entriesList.add(holder);
+ }
+
+ public RewriteEvent getEvent(ASTNode parent, StructuralPropertyDescriptor property) {
+ validateHasChildProperty(parent, property);
+
+ if (this.lastEvent != null && this.lastEvent.parent == parent && this.lastEvent.childProperty == property) {
+ return this.lastEvent.event;
+ }
+
+ List entriesList = (List) this.eventLookup.get(parent);
+ if (entriesList != null) {
+ for (int i= 0; i < entriesList.size(); i++) {
+ EventHolder holder= (EventHolder) entriesList.get(i);
+ if (holder.childProperty == property) {
+ this.lastEvent= holder;
+ return holder.event;
+ }
+ }
+ }
+ return null;
+ }
+
+ public NodeRewriteEvent getNodeEvent(ASTNode parent, StructuralPropertyDescriptor childProperty, boolean forceCreation) {
+ validateIsNodeProperty(childProperty);
+ NodeRewriteEvent event= (NodeRewriteEvent) getEvent(parent, childProperty);
+ if (event == null && forceCreation) {
+ Object originalValue= accessOriginalValue(parent, childProperty);
+ event= new NodeRewriteEvent(originalValue, originalValue);
+ addEvent(parent, childProperty, event);
+ }
+ return event;
+ }
+
+ public ListRewriteEvent getListEvent(ASTNode parent, StructuralPropertyDescriptor childProperty, boolean forceCreation) {
+ validateIsListProperty(childProperty);
+ ListRewriteEvent event= (ListRewriteEvent) getEvent(parent, childProperty);
+ if (event == null && forceCreation) {
+ List originalValue= (List) accessOriginalValue(parent, childProperty);
+ event= new ListRewriteEvent(originalValue);
+ addEvent(parent, childProperty, event);
+ }
+ return event;
+ }
+
+ public Iterator getChangeRootIterator() {
+ return new ParentIterator();
+ }
+
+
+ public boolean hasChangedProperties(ASTNode parent) {
+ List entriesList = (List) this.eventLookup.get(parent);
+ if (entriesList != null) {
+ for (int i= 0; i < entriesList.size(); i++) {
+ EventHolder holder= (EventHolder) entriesList.get(i);
+ if (holder.event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public PropertyLocation getPropertyLocation(Object value, int kind) {
+ for (Iterator iter= this.eventLookup.values().iterator(); iter.hasNext();) {
+ List events= (List) iter.next();
+ for (int i= 0; i < events.size(); i++) {
+ EventHolder holder= (EventHolder) events.get(i);
+ RewriteEvent event= holder.event;
+ if (isNodeInEvent(event, value, kind)) {
+ return new PropertyLocation(holder.parent, holder.childProperty);
+ }
+ if (event.isListRewrite()) {
+ RewriteEvent[] children= event.getChildren();
+ for (int k= 0; k < children.length; k++) {
+ if (isNodeInEvent(children[k], value, kind)) {
+ return new PropertyLocation(holder.parent, holder.childProperty);
+ }
+ }
+ }
+ }
+ }
+ if (value instanceof ASTNode) {
+ ASTNode node= (ASTNode) value;
+ return new PropertyLocation(node.getParent(), node.getLocationInParent());
+ }
+ return null;
+ }
+
+
+ /**
+ * Kind is either ORIGINAL, NEW, or BOTH
+ * @param value
+ * @param kind
+ * @return Returns the event with the given value of <code>null</code>.
+ */
+ public RewriteEvent findEvent(Object value, int kind) {
+ for (Iterator iter= this.eventLookup.values().iterator(); iter.hasNext();) {
+ List events= (List) iter.next();
+ for (int i= 0; i < events.size(); i++) {
+ RewriteEvent event= ((EventHolder) events.get(i)).event;
+ if (isNodeInEvent(event, value, kind)) {
+ return event;
+ }
+ if (event.isListRewrite()) {
+ RewriteEvent[] children= event.getChildren();
+ for (int k= 0; k < children.length; k++) {
+ if (isNodeInEvent(children[k], value, kind)) {
+ return children[k];
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private boolean isNodeInEvent(RewriteEvent event, Object value, int kind) {
+ if (((kind & NEW) != 0) && event.getNewValue() == value) {
+ return true;
+ }
+ if (((kind & ORIGINAL) != 0) && event.getOriginalValue() == value) {
+ return true;
+ }
+ return false;
+ }
+
+
+ public Object getOriginalValue(ASTNode parent, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ return event.getOriginalValue();
+ }
+ return accessOriginalValue(parent, property);
+ }
+
+ public Object getNewValue(ASTNode parent, StructuralPropertyDescriptor property) {
+ RewriteEvent event= getEvent(parent, property);
+ if (event != null) {
+ return event.getNewValue();
+ }
+ return accessOriginalValue(parent, property);
+ }
+
+ public List getChangedPropertieEvents(ASTNode parent) {
+ List changedPropertiesEvent = new ArrayList();
+
+ List entriesList = (List) this.eventLookup.get(parent);
+ if (entriesList != null) {
+ for (int i= 0; i < entriesList.size(); i++) {
+ EventHolder holder= (EventHolder) entriesList.get(i);
+ if (holder.event.getChangeKind() != RewriteEvent.UNCHANGED) {
+ changedPropertiesEvent.add(holder.event);
+ }
+ }
+ }
+ return changedPropertiesEvent;
+ }
+
+ public int getChangeKind(ASTNode node) {
+ RewriteEvent event= findEvent(node, ORIGINAL);
+ if (event != null) {
+ return event.getChangeKind();
+ }
+ return RewriteEvent.UNCHANGED;
+ }
+
+ /*
+ * Gets an original child from the AST.
+ * Temporarily overridden to port the old rewriter to the new infrastructure.
+ */
+ private Object accessOriginalValue(ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ if (this.nodePropertyMapper != null) {
+ return this.nodePropertyMapper.getOriginalValue(parent, childProperty);
+ }
+
+ return parent.getStructuralProperty(childProperty);
+ }
+
+ public TextEditGroup getEventEditGroup(RewriteEvent event) {
+ if (this.editGroups == null) {
+ return null;
+ }
+ return (TextEditGroup) this.editGroups.get(event);
+ }
+
+ public void setEventEditGroup(RewriteEvent event, TextEditGroup editGroup) {
+ if (this.editGroups == null) {
+ this.editGroups= new IdentityHashMap(5);
+ }
+ this.editGroups.put(event, editGroup);
+ }
+
+
+ public final TextEditGroup getTrackedNodeData(ASTNode node) {
+ if (this.trackedNodes != null) {
+ return (TextEditGroup) this.trackedNodes.get(node);
+ }
+ return null;
+ }
+
+ public void setTrackedNodeData(ASTNode node, TextEditGroup editGroup) {
+ if (this.trackedNodes == null) {
+ this.trackedNodes= new IdentityHashMap();
+ }
+ this.trackedNodes.put(node, editGroup);
+ }
+
+ /**
+ * Marks a node as tracked. The edits added to the group editGroup can be used to get the
+ * position of the node after the rewrite operation.
+ * @param node The node to track
+ * @param editGroup Collects the range markers describing the node position.
+ */
+ public final void markAsTracked(ASTNode node, TextEditGroup editGroup) {
+ if (getTrackedNodeData(node) != null) {
+ throw new IllegalArgumentException("Node is already marked as tracked"); //$NON-NLS-1$
+ }
+ setTrackedNodeData(node, editGroup);
+ }
+
+ private final CopySourceInfo createCopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
+ CopySourceInfo copySource= new CopySourceInfo(location, node, isMove);
+
+ if (this.nodeCopySources == null) {
+ this.nodeCopySources= new ArrayList();
+ }
+ this.nodeCopySources.add(copySource);
+ return copySource;
+ }
+
+ public final CopySourceInfo markAsCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode node, boolean isMove) {
+ return createCopySourceInfo(new PropertyLocation(parent, property), node, isMove);
+ }
+
+ public final boolean isRangeCopyPlaceholder(ASTNode node) {
+ return node.getProperty(INTERNAL_PLACEHOLDER_PROPERTY) != null;
+ }
+
+ public final CopySourceInfo createRangeCopy(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, boolean isMove, ASTNode internalPlaceholder, ASTNode replacingNode, TextEditGroup editGroup) {
+ CopySourceInfo copyInfo= createCopySourceInfo(null, internalPlaceholder, isMove);
+ internalPlaceholder.setProperty(INTERNAL_PLACEHOLDER_PROPERTY, internalPlaceholder);
+
+ NodeRangeInfo copyRangeInfo= new NodeRangeInfo(parent, childProperty, first, last, copyInfo, replacingNode, editGroup);
+
+ ListRewriteEvent listEvent= getListEvent(parent, childProperty, true);
+
+ int indexFirst= listEvent.getIndex(first, ListRewriteEvent.OLD);
+ if (indexFirst == -1) {
+ throw new IllegalArgumentException("Start node is not a original child of the given list"); //$NON-NLS-1$
+ }
+ int indexLast= listEvent.getIndex(last, ListRewriteEvent.OLD);
+ if (indexLast == -1) {
+ throw new IllegalArgumentException("End node is not a original child of the given list"); //$NON-NLS-1$
+ }
+
+ if (indexFirst > indexLast) {
+ throw new IllegalArgumentException("Start node must be before end node"); //$NON-NLS-1$
+ }
+
+ if (this.nodeRangeInfos == null) {
+ this.nodeRangeInfos= new HashMap();
+ }
+ PropertyLocation loc= new PropertyLocation(parent, childProperty);
+ List innerList= (List) this.nodeRangeInfos.get(loc);
+ if (innerList == null) {
+ innerList= new ArrayList(2);
+ this.nodeRangeInfos.put(loc, innerList);
+ } else {
+ assertNoOverlap(listEvent, indexFirst, indexLast, innerList);
+ }
+ innerList.add(copyRangeInfo);
+
+
+ return copyInfo;
+ }
+
+ public CopySourceInfo[] getNodeCopySources(ASTNode node) {
+ if (this.nodeCopySources == null) {
+ return null;
+ }
+ return internalGetCopySources(this.nodeCopySources, node);
+ }
+
+
+ public CopySourceInfo[] internalGetCopySources(List copySources, ASTNode node) {
+ ArrayList res= new ArrayList(3);
+ for (int i= 0; i < copySources.size(); i++) {
+ CopySourceInfo curr= (CopySourceInfo) copySources.get(i);
+ if (curr.getNode() == node) {
+ res.add(curr);
+ }
+ }
+ if (res.isEmpty()) {
+ return null;
+ }
+
+ CopySourceInfo[] arr= (CopySourceInfo[]) res.toArray(new CopySourceInfo[res.size()]);
+ Arrays.sort(arr);
+ return arr;
+ }
+
+
+ private void assertNoOverlap(ListRewriteEvent listEvent, int indexFirst, int indexLast, List innerList) {
+ for (Iterator iter= innerList.iterator(); iter.hasNext();) {
+ NodeRangeInfo curr= (NodeRangeInfo) iter.next();
+ int currStart= listEvent.getIndex(curr.getStartNode(), ListRewriteEvent.BOTH);
+ int currEnd= listEvent.getIndex(curr.getEndNode(), ListRewriteEvent.BOTH);
+ if (currStart < indexFirst && currEnd < indexLast && currEnd >= indexFirst
+ || currStart > indexFirst && currStart <= currEnd && currEnd > indexLast) {
+ throw new IllegalArgumentException("Range overlapps with an existing copy or move range"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ public void prepareMovedNodes(TargetSourceRangeComputer sourceRangeComputer) {
+ if (this.nodeCopySources != null) {
+ prepareSingleNodeCopies();
+ }
+
+ if (this.nodeRangeInfos != null) {
+ prepareNodeRangeCopies(sourceRangeComputer);
+ }
+ }
+
+ public void revertMovedNodes() {
+ if (this.nodeRangeInfos != null) {
+ removeMoveRangePlaceholders();
+ }
+ }
+
+ private void removeMoveRangePlaceholders() {
+ for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry= (Map.Entry) iter.next();
+ Set placeholders= new HashSet(); // collect all placeholders
+ List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
+ for (int i= 0; i < rangeInfos.size(); i++) {
+ placeholders.add(((NodeRangeInfo) rangeInfos.get(i)).getInternalPlaceholder());
+ }
+
+ PropertyLocation loc= (PropertyLocation) entry.getKey();
+
+ RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
+ List revertedChildren= new ArrayList();
+ revertListWithRanges(children, placeholders, revertedChildren);
+ RewriteEvent[] revertedChildrenArr= (RewriteEvent[]) revertedChildren.toArray(new RewriteEvent[revertedChildren.size()]);
+ addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(revertedChildrenArr)); // replace the current edits
+ }
+ }
+
+ private void revertListWithRanges(RewriteEvent[] childEvents, Set placeholders, List revertedChildren) {
+ for (int i= 0; i < childEvents.length; i++) {
+ RewriteEvent event= childEvents[i];
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ if (placeholders.contains(node)) {
+ RewriteEvent[] placeholderChildren= getListEvent(node, Block.STATEMENTS_PROPERTY, false).getChildren();
+ revertListWithRanges(placeholderChildren, placeholders, revertedChildren);
+ } else {
+ revertedChildren.add(event);
+ }
+ }
+ }
+
+ private void prepareNodeRangeCopies(TargetSourceRangeComputer sourceRangeComputer) {
+ for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry= (Map.Entry) iter.next();
+ List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
+ Collections.sort(rangeInfos); // sort by start index, length, move or copy
+
+ PropertyLocation loc= (PropertyLocation) entry.getKey();
+ RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
+
+ RewriteEvent[] newChildren= processListWithRanges(rangeInfos, children, sourceRangeComputer);
+ addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(newChildren)); // replace the current edits
+ }
+ }
+
+ private RewriteEvent[] processListWithRanges(List rangeInfos, RewriteEvent[] childEvents, TargetSourceRangeComputer sourceRangeComputer) {
+ List newChildEvents= new ArrayList(childEvents.length);
+ NodeRangeInfo topInfo= null;
+ Stack newChildrenStack= new Stack();
+ Stack topInfoStack= new Stack();
+
+ Iterator rangeInfoIterator= rangeInfos.iterator();
+ NodeRangeInfo nextInfo= (NodeRangeInfo) rangeInfoIterator.next();
+
+ for (int k= 0; k < childEvents.length; k++) {
+ RewriteEvent event= childEvents[k];
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ // check for ranges and add a placeholder for them
+ while (nextInfo != null && node == nextInfo.getStartNode()) { // is this child the beginning of a range?
+ nextInfo.updatePlaceholderSourceRanges(sourceRangeComputer);
+
+ Block internalPlaceholder= nextInfo.getInternalPlaceholder();
+ RewriteEvent newEvent;
+ if (nextInfo.isMove()) {
+ newEvent= new NodeRewriteEvent(internalPlaceholder, nextInfo.replacingNode); // remove or replace
+ } else {
+ newEvent= new NodeRewriteEvent(internalPlaceholder, internalPlaceholder); // unchanged
+ }
+ newChildEvents.add(newEvent);
+ if (nextInfo.editGroup != null) {
+ setEventEditGroup(newEvent, nextInfo.editGroup);
+ }
+
+ newChildrenStack.push(newChildEvents);
+ topInfoStack.push(topInfo);
+
+ newChildEvents= new ArrayList(childEvents.length);
+ topInfo= nextInfo;
+
+ nextInfo= rangeInfoIterator.hasNext() ? (NodeRangeInfo) rangeInfoIterator.next() : null;
+ }
+
+ newChildEvents.add(event);
+
+ while (topInfo != null && node == topInfo.getEndNode()) {
+ RewriteEvent[] placeholderChildEvents= (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
+ Block internalPlaceholder= topInfo.getInternalPlaceholder();
+ addEvent(internalPlaceholder, Block.STATEMENTS_PROPERTY, new ListRewriteEvent(placeholderChildEvents));
+
+ newChildEvents= (List) newChildrenStack.pop();
+ topInfo= (NodeRangeInfo) topInfoStack.pop();
+ }
+ }
+ return (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
+ }
+
+ /**
+ * Make sure all moved nodes are marked as removed or replaced.
+ */
+ private void prepareSingleNodeCopies() {
+ for (int i= 0; i < this.nodeCopySources.size(); i++) {
+ CopySourceInfo curr= (CopySourceInfo) this.nodeCopySources.get(i);
+ if (curr.isMove && curr.location != null) {
+ doMarkMovedAsRemoved(curr, curr.location.getParent(), curr.location.getProperty());
+ }
+ }
+
+ }
+
+ private void doMarkMovedAsRemoved(CopySourceInfo curr, ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ if (childProperty.isChildListProperty()) {
+ ListRewriteEvent event= getListEvent(parent, childProperty, true);
+ int index= event.getIndex(curr.getNode(), ListRewriteEvent.OLD);
+ if (index != -1 && event.getChangeKind(index) == RewriteEvent.UNCHANGED) {
+ event.setNewValue(null, index);
+ }
+ } else {
+ NodeRewriteEvent event= getNodeEvent(parent, childProperty, true);
+ if (event.getChangeKind() == RewriteEvent.UNCHANGED) {
+ event.setNewValue(null);
+ }
+ }
+ }
+
+ public boolean isInsertBoundToPrevious(ASTNode node) {
+ if (this.insertBoundToPrevious != null) {
+ return this.insertBoundToPrevious.contains(node);
+ }
+ return false;
+ }
+
+ public void setInsertBoundToPrevious(ASTNode node) {
+ if (this.insertBoundToPrevious == null) {
+ this.insertBoundToPrevious= new HashSet();
+ }
+ this.insertBoundToPrevious.add(node);
+ }
+
+ private void validateIsListProperty(StructuralPropertyDescriptor property) {
+ if (!property.isChildListProperty()) {
+ String message= property.getId() + " is not a list property"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ private void validateHasChildProperty(ASTNode parent, StructuralPropertyDescriptor property) {
+ if (!parent.structuralPropertiesForType().contains(property)) {
+ String message= Signature.getSimpleName(parent.getClass().getName()) + " has no property " + property.getId(); //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ private void validateIsNodeProperty(StructuralPropertyDescriptor property) {
+ if (property.isChildListProperty()) {
+ String message= property.getId() + " is not a node property"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ for (Iterator iter = this.eventLookup.values().iterator(); iter.hasNext();) {
+ List events = (List) iter.next();
+ for (int i= 0; i < events.size(); i++) {
+ buf.append(events.get(i).toString()).append('\n');
+ }
+ }
+ return buf.toString();
+ }
+
+ public static boolean isNewNode(ASTNode node) {
+ return (node.getFlags() & ASTNode.ORIGINAL) == 0;
+ }
+
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/SourceModifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/SourceModifier.java
new file mode 100644
index 000000000..9e83303b6
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/SourceModifier.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.formatter.IndentManipulation;
+import org.eclipse.text.edits.ISourceModifier;
+import org.eclipse.text.edits.ReplaceEdit;
+
+
+public class SourceModifier implements ISourceModifier {
+
+ private final String destinationIndent;
+ private final int sourceIndentLevel;
+ private final int tabWidth;
+ private final int indentWidth;
+
+ public SourceModifier(int sourceIndentLevel, String destinationIndent, int tabWidth, int indentWidth) {
+ this.destinationIndent= destinationIndent;
+ this.sourceIndentLevel= sourceIndentLevel;
+ this.tabWidth= tabWidth;
+ this.indentWidth= indentWidth;
+ }
+
+ public ISourceModifier copy() {
+ // We are state less
+ return this;
+ }
+
+ public ReplaceEdit[] getModifications(String source) {
+ List result= new ArrayList();
+ int destIndentLevel= IndentManipulation.measureIndentUnits(this.destinationIndent, this.tabWidth, this.indentWidth);
+ if (destIndentLevel == this.sourceIndentLevel) {
+ return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
+ }
+ return IndentManipulation.getChangeIndentEdits(source, this.sourceIndentLevel, this.tabWidth, this.indentWidth, this.destinationIndent);
+ }
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java
new file mode 100644
index 000000000..344272b7d
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Wraps a scanner and offers convenient methods for finding tokens
+ */
+public class TokenScanner {
+
+ public static final int END_OF_FILE= 20001;
+ public static final int LEXICAL_ERROR= 20002;
+ public static final int DOCUMENT_ERROR= 20003;
+
+ private final Scanner scanner;
+ private final int endPosition;
+
+ /**
+ * Creates a TokenScanner
+ * @param scanner The scanner to be wrapped
+ */
+ public TokenScanner(Scanner scanner) {
+ this.scanner= scanner;
+ this.endPosition= this.scanner.getSource().length - 1;
+ }
+
+ /**
+ * Returns the wrapped scanner
+ * @return IScanner
+ */
+ public Scanner getScanner() {
+ return this.scanner;
+ }
+
+ /**
+ * Sets the scanner offset to the given offset.
+ * @param offset The offset to set
+ */
+ public void setOffset(int offset) {
+ this.scanner.resetTo(offset, this.endPosition);
+ }
+
+ /**
+ * @return Returns the offset after the current token
+ */
+ public int getCurrentEndOffset() {
+ return this.scanner.getCurrentTokenEndPosition() + 1;
+ }
+
+ /**
+ * @return Returns the start offset of the current token
+ */
+ public int getCurrentStartOffset() {
+ return this.scanner.getCurrentTokenStartPosition();
+ }
+
+ /**
+ * @return Returns the length of the current token
+ */
+ public int getCurrentLength() {
+ return getCurrentEndOffset() - getCurrentStartOffset();
+ }
+
+ /**
+ * Reads the next token.
+ * @param ignoreComments If set, comments will be overread
+ * @return Return the token id.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int readNext(boolean ignoreComments) throws CoreException {
+ int curr= 0;
+ do {
+ try {
+ curr= this.scanner.getNextToken();
+ if (curr == TerminalTokens.TokenNameEOF) {
+ throw new CoreException(createError(END_OF_FILE, "End Of File", null)); //$NON-NLS-1$
+ }
+ } catch (InvalidInputException e) {
+ throw new CoreException(createError(LEXICAL_ERROR, e.getMessage(), e));
+ }
+ } while (ignoreComments && isComment(curr));
+ return curr;
+ }
+
+ /**
+ * Reads the next token from the given offset.
+ * @param offset The offset to start reading from.
+ * @param ignoreComments If set, comments will be overread.
+ * @return Returns the token id.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int readNext(int offset, boolean ignoreComments) throws CoreException {
+ setOffset(offset);
+ return readNext(ignoreComments);
+ }
+
+ /**
+ * Reads the next token from the given offset and returns the start offset of the token.
+ * @param offset The offset to start reading from.
+ * @param ignoreComments If set, comments will be overread
+ * @return Returns the start position of the next token.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int getNextStartOffset(int offset, boolean ignoreComments) throws CoreException {
+ readNext(offset, ignoreComments);
+ return getCurrentStartOffset();
+ }
+
+ /**
+ * Reads the next token from the given offset and returns the offset after the token.
+ * @param offset The offset to start reading from.
+ * @param ignoreComments If set, comments will be overread
+ * @return Returns the start position of the next token.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int getNextEndOffset(int offset, boolean ignoreComments) throws CoreException {
+ readNext(offset, ignoreComments);
+ return getCurrentEndOffset();
+ }
+
+ /**
+ * Reads until a token is reached.
+ * @param tok The token to read to.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public void readToToken(int tok) throws CoreException {
+ int curr= 0;
+ do {
+ curr= readNext(false);
+ } while (curr != tok);
+ }
+
+ /**
+ * Reads until a token is reached, starting from the given offset.
+ * @param tok The token to read to.
+ * @param offset The offset to start reading from.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public void readToToken(int tok, int offset) throws CoreException {
+ setOffset(offset);
+ readToToken(tok);
+ }
+
+ /**
+ * Reads from the given offset until a token is reached and returns the start offset of the token.
+ * @param token The token to be found.
+ * @param startOffset The offset to start reading from.
+ * @return Returns the start position of the found token.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int getTokenStartOffset(int token, int startOffset) throws CoreException {
+ readToToken(token, startOffset);
+ return getCurrentStartOffset();
+ }
+
+ /**
+ * Reads from the given offset until a token is reached and returns the offset after the token.
+ * @param token The token to be found.
+ * @param startOffset Offset to start reading from
+ * @return Returns the end position of the found token.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int getTokenEndOffset(int token, int startOffset) throws CoreException {
+ readToToken(token, startOffset);
+ return getCurrentEndOffset();
+ }
+
+ /**
+ * Reads from the given offset until a token is reached and returns the offset after the previous token.
+ * @param token The token to be found.
+ * @param startOffset The offset to start scanning from.
+ * @return Returns the end offset of the token previous to the given token.
+ * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
+ * or a lexical error was detected while scanning (code LEXICAL_ERROR)
+ */
+ public int getPreviousTokenEndOffset(int token, int startOffset) throws CoreException {
+ setOffset(startOffset);
+ int res= startOffset;
+ int curr= readNext(false);
+ while (curr != token) {
+ res= getCurrentEndOffset();
+ curr= readNext(false);
+ }
+ return res;
+ }
+
+ public static boolean isComment(int token) {
+ return token == TerminalTokens.TokenNameCOMMENT_BLOCK || token == TerminalTokens.TokenNameCOMMENT_JAVADOC
+ || token == TerminalTokens.TokenNameCOMMENT_LINE;
+ }
+
+ public static boolean isModifier(int token) {
+ switch (token) {
+ case TerminalTokens.TokenNamepublic:
+ case TerminalTokens.TokenNameprotected:
+ case TerminalTokens.TokenNameprivate:
+ case TerminalTokens.TokenNamestatic:
+ case TerminalTokens.TokenNamefinal:
+ case TerminalTokens.TokenNameabstract:
+ case TerminalTokens.TokenNamenative:
+ case TerminalTokens.TokenNamevolatile:
+ case TerminalTokens.TokenNamestrictfp:
+ case TerminalTokens.TokenNametransient:
+ case TerminalTokens.TokenNamesynchronized:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static IStatus createError(int code, String message, Throwable throwable) {
+ return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, code, message, throwable);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TrackedNodePosition.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TrackedNodePosition.java
new file mode 100644
index 000000000..3c971f4ae
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/TrackedNodePosition.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
+import org.eclipse.jface.text.IRegion;
+
+/**
+ *
+ */
+public class TrackedNodePosition implements ITrackedNodePosition {
+
+ private final TextEditGroup group;
+ private final ASTNode node;
+
+ public TrackedNodePosition(TextEditGroup group, ASTNode node) {
+ this.group= group;
+ this.node= node;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.ITrackedNodePosition#getStartPosition()
+ */
+ public int getStartPosition() {
+ if (this.group.isEmpty()) {
+ return this.node.getStartPosition();
+ }
+ IRegion coverage= TextEdit.getCoverage(this.group.getTextEdits());
+ if (coverage == null) {
+ return this.node.getStartPosition();
+ }
+ return coverage.getOffset();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.dom.ITrackedNodePosition#getLength()
+ */
+ public int getLength() {
+ if (this.group.isEmpty()) {
+ return this.node.getLength();
+ }
+ IRegion coverage= TextEdit.getCoverage(this.group.getTextEdits());
+ if (coverage == null) {
+ return this.node.getLength();
+ }
+ return coverage.getLength();
+ }
+}

Back to the top