001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.jdt.core.compiler.InvalidInputException;
016: import org.eclipse.jdt.internal.compiler.parser.Scanner;
017: import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
018:
019: /**
020: * AST node for a simple name. A simple name is an identifier other than
021: * a keyword, boolean literal ("true", "false") or null literal ("null").
022: * <pre>
023: * SimpleName:
024: * Identifier
025: * </pre>
026: *
027: * @since 2.0
028: */
029: public class SimpleName extends Name {
030:
031: /**
032: * The "identifier" structural property of this node type.
033: *
034: * @since 3.0
035: */
036: public static final SimplePropertyDescriptor IDENTIFIER_PROPERTY = new SimplePropertyDescriptor(
037: SimpleName.class, "identifier", String.class, MANDATORY); //$NON-NLS-1$
038:
039: /**
040: * A list of property descriptors (element type:
041: * {@link StructuralPropertyDescriptor}),
042: * or null if uninitialized.
043: * @since 3.0
044: */
045: private static final List PROPERTY_DESCRIPTORS;
046:
047: static {
048: List propertyList = new ArrayList(2);
049: createPropertyList(SimpleName.class, propertyList);
050: addProperty(IDENTIFIER_PROPERTY, propertyList);
051: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
052: }
053:
054: /**
055: * Returns a list of structural property descriptors for this node type.
056: * Clients must not modify the result.
057: *
058: * @param apiLevel the API level; one of the AST.JLS* constants
059: * @return a list of property descriptors (element type:
060: * {@link StructuralPropertyDescriptor})
061: * @since 3.0
062: */
063: public static List propertyDescriptors(int apiLevel) {
064: return PROPERTY_DESCRIPTORS;
065: }
066:
067: /**
068: * An unspecified (but externally observable) legal Java identifier.
069: */
070: private static final String MISSING_IDENTIFIER = "MISSING";//$NON-NLS-1$
071:
072: /**
073: * The identifier; defaults to a unspecified, legal Java identifier.
074: */
075: private String identifier = MISSING_IDENTIFIER;
076:
077: /**
078: * Creates a new AST node for a simple name owned by the given AST.
079: * The new node has an unspecified, legal Java identifier.
080: * <p>
081: * N.B. This constructor is package-private; all subclasses must be
082: * declared in the same package; clients are unable to declare
083: * additional subclasses.
084: * </p>
085: *
086: * @param ast the AST that is to own this node
087: */
088: SimpleName(AST ast) {
089: super (ast);
090: }
091:
092: /* (omit javadoc for this method)
093: * Method declared on ASTNode.
094: * @since 3.0
095: */
096: final List internalStructuralPropertiesForType(int apiLevel) {
097: return propertyDescriptors(apiLevel);
098: }
099:
100: /* (omit javadoc for this method)
101: * Method declared on ASTNode.
102: */
103: final Object internalGetSetObjectProperty(
104: SimplePropertyDescriptor property, boolean get, Object value) {
105: if (property == IDENTIFIER_PROPERTY) {
106: if (get) {
107: return getIdentifier();
108: } else {
109: setIdentifier((String) value);
110: return null;
111: }
112: }
113: // allow default implementation to flag the error
114: return super .internalGetSetObjectProperty(property, get, value);
115: }
116:
117: /* (omit javadoc for this method)
118: * Method declared on ASTNode.
119: */
120: final int getNodeType0() {
121: return SIMPLE_NAME;
122: }
123:
124: /* (omit javadoc for this method)
125: * Method declared on ASTNode.
126: */
127: ASTNode clone0(AST target) {
128: SimpleName result = new SimpleName(target);
129: result
130: .setSourceRange(this .getStartPosition(), this
131: .getLength());
132: result.setIdentifier(getIdentifier());
133: return result;
134: }
135:
136: /* (omit javadoc for this method)
137: * Method declared on ASTNode.
138: */
139: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
140: // dispatch to correct overloaded match method
141: return matcher.match(this , other);
142: }
143:
144: /* (omit javadoc for this method)
145: * Method declared on ASTNode.
146: */
147: void accept0(ASTVisitor visitor) {
148: visitor.visit(this );
149: visitor.endVisit(this );
150: }
151:
152: /**
153: * Returns this node's identifier.
154: *
155: * @return the identifier of this node
156: */
157: public String getIdentifier() {
158: return this .identifier;
159: }
160:
161: /**
162: * Sets the identifier of this node to the given value.
163: * The identifier should be legal according to the rules
164: * of the Java language. Note that keywords are not legal
165: * identifiers.
166: * <p>
167: * Note that the list of keywords may depend on the version of the
168: * language (determined when the AST object was created).
169: * </p>
170: *
171: * @param identifier the identifier of this node
172: * @exception IllegalArgumentException if the identifier is invalid
173: */
174: public void setIdentifier(String identifier) {
175: // update internalSetIdentifier if this is changed
176: if (identifier == null) {
177: throw new IllegalArgumentException();
178: }
179: Scanner scanner = this .ast.scanner;
180: char[] source = identifier.toCharArray();
181: scanner.setSource(source);
182: final int length = source.length;
183: scanner.resetTo(0, length - 1);
184: try {
185: int tokenType = scanner.scanIdentifier();
186: if (tokenType != TerminalTokens.TokenNameIdentifier) {
187: throw new IllegalArgumentException();
188: }
189: if (scanner.currentPosition != length) {
190: // this is the case when there is only one identifier see 87849
191: throw new IllegalArgumentException();
192: }
193: } catch (InvalidInputException e) {
194: throw new IllegalArgumentException();
195: }
196: preValueChange(IDENTIFIER_PROPERTY);
197: this .identifier = identifier;
198: postValueChange(IDENTIFIER_PROPERTY);
199: }
200:
201: /* (omit javadoc for this method)
202: * This method is a copy of setIdentifier(String) that doesn't do any validation.
203: */
204: void internalSetIdentifier(String ident) {
205: preValueChange(IDENTIFIER_PROPERTY);
206: this .identifier = ident;
207: postValueChange(IDENTIFIER_PROPERTY);
208: }
209:
210: /**
211: * Returns whether this simple name represents a name that is being defined,
212: * as opposed to one being referenced. The following positions are considered
213: * ones where a name is defined:
214: * <ul>
215: * <li>The type name in a <code>TypeDeclaration</code> node.</li>
216: * <li>The method name in a <code>MethodDeclaration</code> node
217: * providing <code>isConstructor</code> is <code>false</code>.</li>
218: * <li>The variable name in any type of <code>VariableDeclaration</code>
219: * node.</li>
220: * <li>The enum type name in a <code>EnumDeclaration</code> node.</li>
221: * <li>The enum constant name in an <code>EnumConstantDeclaration</code>
222: * node.</li>
223: * <li>The variable name in an <code>EnhancedForStatement</code>
224: * node.</li>
225: * <li>The type variable name in a <code>TypeParameter</code>
226: * node.</li>
227: * <li>The type name in an <code>AnnotationTypeDeclaration</code> node.</li>
228: * <li>The member name in an <code>AnnotationTypeMemberDeclaration</code> node.</li>
229: * </ul>
230: * <p>
231: * Note that this is a convenience method that simply checks whether
232: * this node appears in the declaration position relative to its parent.
233: * It always returns <code>false</code> if this node is unparented.
234: * </p>
235: *
236: * @return <code>true</code> if this node declares a name, and
237: * <code>false</code> otherwise
238: */
239: public boolean isDeclaration() {
240: StructuralPropertyDescriptor d = getLocationInParent();
241: if (d == null) {
242: // unparented node
243: return false;
244: }
245: ASTNode parent = getParent();
246: if (parent instanceof TypeDeclaration) {
247: return (d == TypeDeclaration.NAME_PROPERTY);
248: }
249: if (parent instanceof MethodDeclaration) {
250: MethodDeclaration p = (MethodDeclaration) parent;
251: // could be the name of the method or constructor
252: return !p.isConstructor()
253: && (d == MethodDeclaration.NAME_PROPERTY);
254: }
255: if (parent instanceof SingleVariableDeclaration) {
256: return (d == SingleVariableDeclaration.NAME_PROPERTY);
257: }
258: if (parent instanceof VariableDeclarationFragment) {
259: return (d == VariableDeclarationFragment.NAME_PROPERTY);
260: }
261: if (parent instanceof EnumDeclaration) {
262: return (d == EnumDeclaration.NAME_PROPERTY);
263: }
264: if (parent instanceof EnumConstantDeclaration) {
265: return (d == EnumConstantDeclaration.NAME_PROPERTY);
266: }
267: if (parent instanceof TypeParameter) {
268: return (d == TypeParameter.NAME_PROPERTY);
269: }
270: if (parent instanceof AnnotationTypeDeclaration) {
271: return (d == AnnotationTypeDeclaration.NAME_PROPERTY);
272: }
273: if (parent instanceof AnnotationTypeMemberDeclaration) {
274: return (d == AnnotationTypeMemberDeclaration.NAME_PROPERTY);
275: }
276: return false;
277: }
278:
279: /* (omit javadoc for this method)
280: * Method declared on Name.
281: */
282: void appendName(StringBuffer buffer) {
283: buffer.append(getIdentifier());
284: }
285:
286: /* (omit javadoc for this method)
287: * Method declared on ASTNode.
288: */
289: int memSize() {
290: int size = BASE_NAME_NODE_SIZE + 2 * 4;
291: if (identifier != MISSING_IDENTIFIER) {
292: // everything but our missing id costs
293: size += stringSize(identifier);
294: }
295: return size;
296: }
297:
298: /* (omit javadoc for this method)
299: * Method declared on ASTNode.
300: */
301: int treeSize() {
302: return memSize();
303: }
304: }
|