Index: src/org/aspectj/org/eclipse/jdt/core/dom/InterTypeFieldDeclaration.java =================================================================== RCS file: /cvsroot/tools/org.aspectj/modules/org.aspectj.ajdt.core/src/org/aspectj/org/eclipse/jdt/core/dom/InterTypeFieldDeclaration.java,v retrieving revision 1.2 diff -u -r1.2 InterTypeFieldDeclaration.java --- src/org/aspectj/org/eclipse/jdt/core/dom/InterTypeFieldDeclaration.java 11 Nov 2005 08:29:32 -0000 1.2 +++ src/org/aspectj/org/eclipse/jdt/core/dom/InterTypeFieldDeclaration.java 15 May 2007 17:37:35 -0000 @@ -10,57 +10,437 @@ *******************************************************************************/ package org.aspectj.org.eclipse.jdt.core.dom; +import java.util.ArrayList; +import java.util.List; /** - * InterTypeFieldDeclaration DOM AST node. - * has: - * everything FieldDeclarations have - * - * Refused Bequest: - * has the variableDeclarationFragments list - * it redundantly inherits from FieldDeclaration - * as fields can be declared like "int b; int a = b = 5;" - * but ITD fields can't. - * Note: - * should also have the name of the type it was declared on! + * InterTypeFieldDeclaration DOM AST node. has: everything FieldDeclarations + * have, but has only one variable declaration fragment and contains the target + * type. + * * @author ajh02 */ -public class InterTypeFieldDeclaration extends FieldDeclaration { +public class InterTypeFieldDeclaration extends BodyDeclaration { + + /** + * The "javadoc" structural property of this node type. + * + * @since 3.0 + */ + public static final ChildPropertyDescriptor JAVADOC_PROPERTY = internalJavadocPropertyFactory(InterTypeFieldDeclaration.class); + + /** + * The "modifiers" structural property of this node type (JLS2 API only). + * + * @since 3.0 + */ + public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = internalModifiersPropertyFactory(InterTypeFieldDeclaration.class); + + /** + * The "modifiers" structural property of this node type (added in JLS3 + * API). + * + * @since 3.1 + */ + public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = internalModifiers2PropertyFactory(InterTypeFieldDeclaration.class); + + /** + * The "type" structural property of this node type. + * + * @since 3.0 + */ + public static final ChildPropertyDescriptor TYPE_PROPERTY = new ChildPropertyDescriptor( + InterTypeFieldDeclaration.class, + "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "onType" structural property of this node type. + */ + public static final ChildPropertyDescriptor ON_TYPE_PROPERTY = new ChildPropertyDescriptor( + InterTypeFieldDeclaration.class, + "onType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "fragments" structural property of this node type). + * + * @since 3.0 + */ + public static final ChildPropertyDescriptor FRAGMENT_PROPERTY = new ChildPropertyDescriptor( + InterTypeFieldDeclaration.class, + "fragment", VariableDeclarationFragment.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(6); + createPropertyList(FieldDeclaration.class, propertyList); + addProperty(JAVADOC_PROPERTY, propertyList); + addProperty(MODIFIERS_PROPERTY, propertyList); + addProperty(TYPE_PROPERTY, propertyList); + addProperty(FRAGMENT_PROPERTY, propertyList); + addProperty(ON_TYPE_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList); + + propertyList = new ArrayList(6); + createPropertyList(FieldDeclaration.class, propertyList); + addProperty(JAVADOC_PROPERTY, propertyList); + addProperty(MODIFIERS2_PROPERTY, propertyList); + addProperty(TYPE_PROPERTY, propertyList); + addProperty(FRAGMENT_PROPERTY, propertyList); + addProperty(ON_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}) + * @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 target type. + */ + private Name onType = null; + + /** + * The variable declaration fragment of this Inter-type Field Declaration. + */ + VariableDeclarationFragment variableDeclarationFragment = null; + InterTypeFieldDeclaration(AST ast) { super(ast); } - + + /** + * Sets the target type of this inter-type field declaration to the given + * type. + * + * @param type + * the new target type + * @exception IllegalArgumentException + * if: + * + */ + public void setOnType(Name type) { + if (type == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.onType; + preReplaceChild(oldChild, type, ON_TYPE_PROPERTY); + this.onType = type; + postReplaceChild(oldChild, type, ON_TYPE_PROPERTY); + } + + /** + * Returns the target type of this inter-type field declaration. + * + * @return the target type + */ + public Name getOnType() { + if (this.onType == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.onType == null) { + preLazyInit(); + this.onType = this.ast.newName("java.lang.Object"); + postLazyInit(this.onType, ON_TYPE_PROPERTY); + } + } + } + return this.onType; + } + + /* + * (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; + } + } + if (property == ON_TYPE_PROPERTY) { + if (get) { + return getOnType(); + } else { + setOnType((Name) child); + return null; + } + } + if (property == FRAGMENT_PROPERTY) { + if (get) { + return getFragment(); + } else { + setFragment((VariableDeclarationFragment) 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 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; // shouldn't we create a new one? + } + + /* + * (omit javadoc for this method) Method declared on ASTNode. + */ ASTNode clone0(AST target) { InterTypeFieldDeclaration result = new InterTypeFieldDeclaration(target); result.setSourceRange(this.getStartPosition(), this.getLength()); - result.setJavadoc( - (Javadoc) ASTNode.copySubtree(target, getJavadoc())); + 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.modifiers() + .addAll(ASTNode.copySubtrees(target, modifiers())); } result.setType((Type) getType().clone(target)); - result.fragments().addAll( - ASTNode.copySubtrees(target, fragments())); + result.setOnType((Name) getOnType().clone(target)); + result.setFragment((VariableDeclarationFragment) getFragment().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 ((AjASTMatcher) matcher).match(this, other); + } + + /* + * (omit javadoc for this method) Method declared on ASTNode. + */ void accept0(ASTVisitor visitor) { - if (visitor instanceof AjASTVisitor) { - boolean visitChildren = ((AjASTVisitor)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); + boolean visitChildren = ((AjASTVisitor) 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, getOnType()); + acceptChild(visitor, getType()); + acceptChild(visitor, this.variableDeclarationFragment); + } + ((AjASTVisitor) visitor).endVisit(this); + } + + /** + * Returns the base type declared in this field declaration. + *

+ * 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. + *

+ * + * @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); } - acceptChild(visitor, getType()); - acceptChildren(visitor, this.variableDeclarationFragments); } - ((AjASTVisitor)visitor).endVisit(this); } + 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: + * + */ + 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 variable declaration fragment of this Inter-type Field + * Declaration. + * + * @return the live list of variable declaration fragments in this statement + * (element type: VariableDeclarationFragment) + */ + public VariableDeclarationFragment getFragment() { + return this.variableDeclarationFragment; + } + + /** + * Sets the variable declaration fragment of this inter-type field + * declaration to the given fragment. + * + * @param type + * the new fragment + * @exception IllegalArgumentException + * if: + * + */ + public void setFragment(VariableDeclarationFragment fragment) { + if (fragment == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.variableDeclarationFragment; + preReplaceChild(oldChild, fragment, FRAGMENT_PROPERTY); + this.variableDeclarationFragment = fragment; + postReplaceChild(oldChild, fragment, FRAGMENT_PROPERTY); + } + + /* + * (omit javadoc for this method) Method declared on ASTNode. + */ + int memSize() { + return super.memSize() + 2 * 4; // i have no idea how this works, left + // the one copied FieldDeclaration + } + + /* + * (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.onType == null ? 0 : getOnType().treeSize()) + + (this.baseType == null ? 0 : getType().treeSize()) + + (this.variableDeclarationFragment == null ? 0 + : this.variableDeclarationFragment.treeSize()); } } \ No newline at end of file Index: src/org/aspectj/org/eclipse/jdt/core/dom/AjASTMatcher.java =================================================================== RCS file: /cvsroot/tools/org.aspectj/modules/org.aspectj.ajdt.core/src/org/aspectj/org/eclipse/jdt/core/dom/AjASTMatcher.java,v retrieving revision 1.2 diff -u -r1.2 AjASTMatcher.java --- src/org/aspectj/org/eclipse/jdt/core/dom/AjASTMatcher.java 26 Jan 2006 10:57:12 -0000 1.2 +++ src/org/aspectj/org/eclipse/jdt/core/dom/AjASTMatcher.java 15 May 2007 17:37:35 -0000 @@ -210,7 +210,8 @@ return safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeMatch(node.getType(), o.getType()) - && safeSubtreeListMatch(node.fragments(), o.fragments()); + && safeSubtreeMatch(node.getOnType(), o.getOnType()) + && safeSubtreeMatch(node.getFragment(), o.getFragment()); } public boolean match(InterTypeMethodDeclaration node, Object other) { // ajh02: method added Index: src/org/aspectj/org/eclipse/jdt/core/dom/AjASTConverter.java =================================================================== RCS file: /cvsroot/tools/org.aspectj/modules/org.aspectj.ajdt.core/src/org/aspectj/org/eclipse/jdt/core/dom/AjASTConverter.java,v retrieving revision 1.8 diff -u -r1.8 AjASTConverter.java --- src/org/aspectj/org/eclipse/jdt/core/dom/AjASTConverter.java 6 Feb 2006 13:31:23 -0000 1.8 +++ src/org/aspectj/org/eclipse/jdt/core/dom/AjASTConverter.java 15 May 2007 17:37:35 -0000 @@ -493,7 +493,7 @@ checkCanceled(); // ajh02: is this line needed? VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl); final org.aspectj.org.eclipse.jdt.core.dom.InterTypeFieldDeclaration fieldDeclaration = new org.aspectj.org.eclipse.jdt.core.dom.InterTypeFieldDeclaration(this.ast); - fieldDeclaration.fragments().add(variableDeclarationFragment); + fieldDeclaration.setFragment(variableDeclarationFragment); IVariableBinding binding = null; if (this.resolveBindings) { recordNodes(variableDeclarationFragment, fieldDecl); @@ -501,7 +501,9 @@ } fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationSourceEnd - fieldDecl.declarationSourceStart + 1); Type type = convertType(fieldDecl.returnType); - setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions()); + setTypeForIntertypeFieldDeclaration(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions()); + Name onType = convert(fieldDecl.getOnType()); + fieldDeclaration.setOnType(onType); setModifiers(fieldDeclaration, fieldDecl); if (!(this.resolveBindings && binding == null)) { convert(fieldDecl.javadoc, fieldDeclaration); @@ -4301,6 +4303,47 @@ } } + protected void setTypeForIntertypeFieldDeclaration(org.aspectj.org.eclipse.jdt.core.dom.InterTypeFieldDeclaration 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 setTypeForAroundAdviceDeclaration(AroundAdviceDeclaration adviceDeclaration, Type type) { // ajh02: method added switch(this.ast.apiLevel) { Index: testsrc/org/aspectj/tools/ajc/ASTitdTest.java =================================================================== RCS file: /cvsroot/tools/org.aspectj/modules/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/ASTitdTest.java,v retrieving revision 1.1 diff -u -r1.1 ASTitdTest.java --- testsrc/org/aspectj/tools/ajc/ASTitdTest.java 21 Dec 2005 10:58:06 -0000 1.1 +++ testsrc/org/aspectj/tools/ajc/ASTitdTest.java 15 May 2007 17:37:36 -0000 @@ -84,7 +84,7 @@ return true; } public boolean visit(InterTypeFieldDeclaration node) { - b.append("name = " + node.fragments().get(0) + ", modifier = " + Modifier.toString(node.getModifiers())); + b.append("name = " + node.getFragment() + ", modifier = " + Modifier.toString(node.getModifiers())); return true; } public boolean visit(InterTypeMethodDeclaration node) {