0181e4d6b4f33bfe236b285234a6e9f35312fbd2
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / SimpleName.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
19 import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
20
21 /**
22  * AST node for a simple name. A simple name is an identifier other than
23  * a keyword, boolean literal ("true", "false") or null literal ("null").
24  * <pre>
25  * SimpleName:
26  *     Identifier
27  * </pre>
28  * 
29  * @since 2.0
30  * @noinstantiate This class is not intended to be instantiated by clients.
31  */
32 public class SimpleName extends Name {
33
34         /**
35          * The "identifier" structural property of this node type.
36          * 
37          * @since 3.0
38          */
39         public static final SimplePropertyDescriptor IDENTIFIER_PROPERTY = 
40                 new SimplePropertyDescriptor(SimpleName.class, "identifier", String.class, MANDATORY); //$NON-NLS-1$
41         
42         /**
43          * A list of property descriptors (element type: 
44          * {@link StructuralPropertyDescriptor}),
45          * or null if uninitialized.
46          * @since 3.0
47          */
48         private static final List PROPERTY_DESCRIPTORS;
49         
50         static {
51                 List propertyList = new ArrayList(2);
52                 createPropertyList(SimpleName.class, propertyList);
53                 addProperty(IDENTIFIER_PROPERTY, propertyList);
54                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
55         }
56         
57         /**
58          * Returns a list of structural property descriptors for this node type.
59          * Clients must not modify the result.
60          * 
61          * @param apiLevel the API level; one of the AST.JLS* constants
62          * @return a list of property descriptors (element type: 
63          * {@link StructuralPropertyDescriptor})
64          * @since 3.0
65          */
66         public static List propertyDescriptors(int apiLevel) {
67                 return PROPERTY_DESCRIPTORS;
68         }
69         
70         /**
71          * An unspecified (but externally observable) legal Java identifier.
72          */
73         private static final String MISSING_IDENTIFIER = "MISSING";//$NON-NLS-1$
74         
75         /**
76          * The identifier; defaults to a unspecified, legal Java identifier.
77          */
78         private String identifier = MISSING_IDENTIFIER;
79         
80         /**
81          * Creates a new AST node for a simple name owned by the given AST.
82          * The new node has an unspecified, legal Java identifier.
83          * <p>
84          * N.B. This constructor is package-private; all subclasses must be 
85          * declared in the same package; clients are unable to declare 
86          * additional subclasses.
87          * </p>
88          * 
89          * @param ast the AST that is to own this node
90          */
91         SimpleName(AST ast) {
92                 super(ast);
93         }
94         
95         /* (omit javadoc for this method)
96          * Method declared on ASTNode.
97          * @since 3.0
98          */
99         final List internalStructuralPropertiesForType(int apiLevel) {
100                 return propertyDescriptors(apiLevel);
101         }
102         
103         /* (omit javadoc for this method)
104          * Method declared on ASTNode.
105          */
106         final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
107                 if (property == IDENTIFIER_PROPERTY) {
108                         if (get) {
109                                 return getIdentifier();
110                         } else {
111                                 setIdentifier((String) value);
112                                 return null;
113                         }
114                 }
115                 // allow default implementation to flag the error
116                 return super.internalGetSetObjectProperty(property, get, value);
117         }
118
119         /* (omit javadoc for this method)
120          * Method declared on ASTNode.
121          */
122         final int getNodeType0() {
123                 return SIMPLE_NAME;
124         }
125
126         /* (omit javadoc for this method)
127          * Method declared on ASTNode.
128          */
129         ASTNode clone0(AST target) {
130                 SimpleName result = new SimpleName(target);
131                 result.setSourceRange(this.getStartPosition(), this.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() && (d == MethodDeclaration.NAME_PROPERTY);
253                 }
254                 if (parent instanceof SingleVariableDeclaration) {
255                         return (d == SingleVariableDeclaration.NAME_PROPERTY);
256                 }
257                 if (parent instanceof VariableDeclarationFragment) {
258                         return (d == VariableDeclarationFragment.NAME_PROPERTY);
259                 }
260                 if (parent instanceof EnumDeclaration) {
261                         return (d == EnumDeclaration.NAME_PROPERTY);
262                 }
263                 if (parent instanceof EnumConstantDeclaration) {
264                         return (d == EnumConstantDeclaration.NAME_PROPERTY);
265                 }
266                 if (parent instanceof TypeParameter) {
267                         return (d == TypeParameter.NAME_PROPERTY);
268                 }
269                 if (parent instanceof AnnotationTypeDeclaration) {
270                         return (d == AnnotationTypeDeclaration.NAME_PROPERTY);
271                 }
272                 if (parent instanceof AnnotationTypeMemberDeclaration) {
273                         return (d == AnnotationTypeMemberDeclaration.NAME_PROPERTY);
274                 }
275                 return false;
276         }
277                 
278         /* (omit javadoc for this method)
279          * Method declared on Name.
280          */
281         void appendName(StringBuffer buffer) {
282                 buffer.append(getIdentifier());
283         }
284
285         /* (omit javadoc for this method)
286          * Method declared on ASTNode.
287          */
288         int memSize() {
289                 int size = BASE_NAME_NODE_SIZE + 2 * 4;
290                 if (identifier != MISSING_IDENTIFIER) {
291                         // everything but our missing id costs
292                         size += stringSize(identifier);
293                 }
294                 return size;
295         }
296         
297         /* (omit javadoc for this method)
298          * Method declared on ASTNode.
299          */
300         int treeSize() {
301                 return memSize();
302         }
303 }
304