1f18312e1404a413aef0a961ae8f1decc4951969
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / MemberRef.java
1 /*******************************************************************************
2  * Copyright (c) 2004, 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 /**
18  * AST node for a member reference within a doc comment
19  * ({@link Javadoc}). The principal uses of these are in "@see" and "@link"
20  * tag elements, for references to field members (and occasionally to method
21  * and constructor members).
22  * <pre>
23  * MemberRef:
24  *              [ Name ] <b>#</b> Identifier
25  * </pre>
26  * 
27  * @see Javadoc
28  * @since 3.0
29  * @noinstantiate This class is not intended to be instantiated by clients.
30  */
31 public class MemberRef extends ASTNode implements IDocElement {
32         
33         /**
34          * The "qualifier" structural property of this node type.
35          * @since 3.0
36          */
37         public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
38                 new ChildPropertyDescriptor(MemberRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
39
40         /**
41          * The "name" structural property of this node type.
42          * @since 3.0
43          */
44         public static final ChildPropertyDescriptor NAME_PROPERTY = 
45                 new ChildPropertyDescriptor(MemberRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
46
47         /**
48          * A list of property descriptors (element type: 
49          * {@link StructuralPropertyDescriptor}),
50          * or null if uninitialized.
51          */
52         private static final List PROPERTY_DESCRIPTORS;
53         
54         static {
55                 List propertyList = new ArrayList(3);
56                 createPropertyList(MemberRef.class, propertyList);
57                 addProperty(QUALIFIER_PROPERTY, propertyList);
58                 addProperty(NAME_PROPERTY, propertyList);
59                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
60         }
61
62         /**
63          * Returns a list of structural property descriptors for this node type.
64          * Clients must not modify the result.
65          * 
66          * @param apiLevel the API level; one of the AST.JLS* constants
67          * @return a list of property descriptors (element type: 
68          * {@link StructuralPropertyDescriptor})
69          * @since 3.0
70          */
71         public static List propertyDescriptors(int apiLevel) {
72                 return PROPERTY_DESCRIPTORS;
73         }
74                         
75         /**
76          * The optional qualifier; <code>null</code> for none; defaults to none.
77          */
78         private Name optionalQualifier = null;
79
80         /**
81          * The member name; lazily initialized; defaults to a unspecified,
82          * legal Java method name.
83          */
84         private SimpleName memberName = null;
85         
86         /**
87          * Creates a new AST node for a member reference owned by the given 
88          * AST. By default, the method reference is for a member with an
89          * unspecified, but legal, name; and no qualifier.
90          * <p>
91          * N.B. This constructor is package-private; all subclasses must be 
92          * declared in the same package; clients are unable to declare 
93          * additional subclasses.
94          * </p>
95          * 
96          * @param ast the AST that is to own this node
97          */
98         MemberRef(AST ast) {
99                 super(ast);
100         }
101
102         /* (omit javadoc for this method)
103          * Method declared on ASTNode.
104          */
105         final List internalStructuralPropertiesForType(int apiLevel) {
106                 return propertyDescriptors(apiLevel);
107         }
108         
109         /* (omit javadoc for this method)
110          * Method declared on ASTNode.
111          */
112         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
113                 if (property == QUALIFIER_PROPERTY) {
114                         if (get) {
115                                 return getQualifier();
116                         } else {
117                                 setQualifier((Name) child);
118                                 return null;
119                         }
120                 }
121                 if (property == NAME_PROPERTY) {
122                         if (get) {
123                                 return getName();
124                         } else {
125                                 setName((SimpleName) child);
126                                 return null;
127                         }
128                 }
129                 // allow default implementation to flag the error
130                 return super.internalGetSetChildProperty(property, get, child);
131         }
132         
133         /* (omit javadoc for this method)
134          * Method declared on ASTNode.
135          */
136         final int getNodeType0() {
137                 return MEMBER_REF;
138         }
139
140         /* (omit javadoc for this method)
141          * Method declared on ASTNode.
142          */
143         ASTNode clone0(AST target) {
144                 MemberRef result = new MemberRef(target);
145                 result.setSourceRange(this.getStartPosition(), this.getLength());
146                 result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
147                 result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
148                 return result;
149         }
150
151         /* (omit javadoc for this method)
152          * Method declared on ASTNode.
153          */
154         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
155                 // dispatch to correct overloaded match method
156                 return matcher.match(this, other);
157         }
158         
159         /* (omit javadoc for this method)
160          * Method declared on ASTNode.
161          */
162         void accept0(ASTVisitor visitor) {
163                 boolean visitChildren = visitor.visit(this);
164                 if (visitChildren) {
165                         // visit children in normal left to right reading order
166                         acceptChild(visitor, getQualifier());
167                         acceptChild(visitor, getName());
168                 }
169                 visitor.endVisit(this);
170         }
171         
172         /**
173          * Returns the qualifier of this member reference, or 
174          * <code>null</code> if there is none.
175          * 
176          * @return the qualifier name node, or <code>null</code> if there is none
177          */ 
178         public Name getQualifier() {
179                 return this.optionalQualifier;
180         }
181         
182         /**
183          * Sets or clears the qualifier of this member reference.
184          * 
185          * @param name the qualifier name node, or <code>null</code> if 
186          *    there is none
187          * @exception IllegalArgumentException if:
188          * <ul>
189          * <li>the node belongs to a different AST</li>
190          * <li>the node already has a parent</li>
191          * </ul>
192          */ 
193         public void setQualifier(Name name) {
194                 ASTNode oldChild = this.optionalQualifier;
195                 preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
196                 this.optionalQualifier = name;
197                 postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
198         }
199
200         /**
201          * Returns the name of the referenced member.
202          * 
203          * @return the member name node
204          */ 
205         public SimpleName getName() {
206                 if (this.memberName == null) {
207                         // lazy init must be thread-safe for readers
208                         synchronized (this) {
209                                 if (this.memberName == null) {
210                                         preLazyInit();
211                                         this.memberName = new SimpleName(this.ast);
212                                         postLazyInit(this.memberName, NAME_PROPERTY);
213                                 }
214                         }
215                 }
216                 return this.memberName;
217         }
218         
219         /**
220          * Sets the name of the referenced member to the given name.
221          * 
222          * @param name the new member name node
223          * @exception IllegalArgumentException if:
224          * <ul>
225          * <li>the name is <code>null</code></li>
226          * <li>the node belongs to a different AST</li>
227          * <li>the node already has a parent</li>
228          * </ul>
229          */ 
230         public void setName(SimpleName name) {
231                 if (name == null) {
232                         throw new IllegalArgumentException();
233                 }
234                 ASTNode oldChild = this.memberName;
235                 preReplaceChild(oldChild, name, NAME_PROPERTY);
236                 this.memberName = name;
237                 postReplaceChild(oldChild, name, NAME_PROPERTY);
238         }
239
240         /**
241          * Resolves and returns the binding for the entity referred to by
242          * this member reference.
243          * <p>
244          * Note that bindings are generally unavailable unless requested when the
245          * AST is being built.
246          * </p>
247          * 
248          * @return the binding, or <code>null</code> if the binding cannot be 
249          *    resolved
250          */     
251         public final IBinding resolveBinding() {
252                 return this.ast.getBindingResolver().resolveReference(this);
253         }
254
255         /* (omit javadoc for this method)
256          * Method declared on ASTNode.
257          */
258         int memSize() {
259                 return BASE_NODE_SIZE + 2 * 4;
260         }
261         
262         /* (omit javadoc for this method)
263          * Method declared on ASTNode.
264          */
265         int treeSize() {
266                 return
267                         memSize()
268                         + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
269                         + (this.memberName == null ? 0 : getName().treeSize());
270         }
271 }
272