improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / util / ASTNodeFinder.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.util;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.IField;
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IMethod;
18 import net.sourceforge.phpdt.core.IType;
19 import net.sourceforge.phpdt.core.compiler.CharOperation;
20 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
21 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
23 import net.sourceforge.phpdt.internal.core.SourceType;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
31
32 /**
33  * Finds an ASTNode given an IJavaElement in a CompilationUnitDeclaration
34  */
35 public class ASTNodeFinder {
36         private CompilationUnitDeclaration unit;
37
38         public ASTNodeFinder(CompilationUnitDeclaration unit) {
39                 this.unit = unit;
40         }
41
42         /*
43          * Finds the FieldDeclaration in the given ast corresponding to the given field handle.
44          * Returns null if not found.
45          */
46         public FieldDeclaration findField(IField fieldHandle) {
47                 TypeDeclaration typeDecl = findType((IType)fieldHandle.getParent());
48                 if (typeDecl == null) return null;
49                 FieldDeclaration[] fields = typeDecl.fields;
50                 if (fields != null) {
51                         char[] fieldName = fieldHandle.getElementName().toCharArray();
52                         for (int i = 0, length = fields.length; i < length; i++) {
53                                 FieldDeclaration field = fields[i];
54                                 if (CharOperation.equals(fieldName, field.name)) {
55                                         return field;
56                                 }
57                         }
58                 }
59                 return null;
60         }
61
62         /*
63          * Finds the Initializer in the given ast corresponding to the given initializer handle.
64          * Returns null if not found.
65          */
66 //      public Initializer findInitializer(IInitializer initializerHandle) {
67 //              TypeDeclaration typeDecl = findType((IType)initializerHandle.getParent());
68 //              if (typeDecl == null) return null;
69 //              FieldDeclaration[] fields = typeDecl.fields;
70 //              if (fields != null) {
71 //                      int occurenceCount = ((JavaElement)initializerHandle).occurrenceCount;
72 //                      for (int i = 0, length = fields.length; i < length; i++) {
73 //                              FieldDeclaration field = fields[i];
74 //                              if (field instanceof Initializer && --occurenceCount == 0) {
75 //                                      return (Initializer)field;
76 //                              }
77 //                      }
78 //              }
79 //              return null;
80 //      }
81
82         /*
83          * Finds the AbstractMethodDeclaration in the given ast corresponding to the given method handle.
84          * Returns null if not found.
85          */
86         public AbstractMethodDeclaration findMethod(IMethod methodHandle) {
87                 TypeDeclaration typeDecl = findType((IType)methodHandle.getParent());
88                 if (typeDecl == null) return null;
89                 AbstractMethodDeclaration[] methods = typeDecl.methods;
90                 if (methods != null) {
91                         char[] selector = methodHandle.getElementName().toCharArray();
92                         String[] parameterTypeSignatures = methodHandle.getParameterTypes();
93                         int parameterCount = parameterTypeSignatures.length;
94                         nextMethod: for (int i = 0, length = methods.length; i < length; i++) {
95                                 AbstractMethodDeclaration method = methods[i];
96                                 if (CharOperation.equals(selector, method.selector)) {
97                                         Argument[] args = method.arguments;
98                                         int argsLength = args == null ? 0 : args.length;
99                                         if (argsLength == parameterCount) {
100                                                 for (int j = 0; j < parameterCount; j++) {
101                                                         TypeReference type = args[j].type;
102                                                         String signature = Util.typeSignature(type);
103                                                         if (!signature.equals(parameterTypeSignatures[j])) {
104                                                                 continue nextMethod;
105                                                         }
106                                                 }
107                                                 return method;
108                                         }
109                                 }
110                         }
111                 }
112                 return null;
113         }
114
115         /*
116          * Finds the TypeDeclaration in the given ast corresponding to the given type handle.
117          * Returns null if not found.
118          */
119         public TypeDeclaration findType(IType typeHandle) {
120                 IJavaElement parent = typeHandle.getParent();
121                 final char[] typeName = typeHandle.getElementName().toCharArray();
122 //              final int occurenceCount = ((SourceType)typeHandle).occurrenceCount;
123                 final boolean findAnonymous = typeName.length == 0;
124                 class Visitor extends ASTVisitor {
125                         TypeDeclaration result;
126                         int count = 0;
127                         public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
128                                 if (result != null) return false;
129 //                              if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
130 //                                      if (findAnonymous && ++count == occurenceCount) {
131 //                                              result = typeDeclaration;
132 //                                      }
133 //                              } else {
134                                         if (!findAnonymous && CharOperation.equals(typeName, typeDeclaration.name)) {
135                                                 result = typeDeclaration;
136                                         }
137 //                              }
138                                 return false; // visit only one level
139                         }
140                 }
141                 switch (parent.getElementType()) {
142                         case IJavaElement.COMPILATION_UNIT:
143                                 ArrayList types = this.unit.types;
144                                 if (types != null) {
145                                         for (int i = 0, length = types.size(); i < length; i++) {
146                                                 TypeDeclaration type = (TypeDeclaration)types.get(i);//[i];
147                                                 if (CharOperation.equals(typeName, type.name)) {
148                                                         return type;
149                                                 }
150                                         }
151                                 }
152                                 break;
153                         case IJavaElement.TYPE:
154                                 TypeDeclaration parentDecl = findType((IType)parent);
155                                 if (parentDecl == null) return null;
156 //                              types = parentDecl.memberTypes;
157 //                              if (types != null) {
158 //                                      for (int i = 0, length = types.length; i < length; i++) {
159 //                                              TypeDeclaration type = types[i];
160 //                                              if (CharOperation.equals(typeName, type.name)) {
161 //                                                      return type;
162 //                                              }
163 //                                      }
164 //                              }
165                                 break;
166                         case IJavaElement.FIELD:
167                                 FieldDeclaration fieldDecl = findField((IField)parent);
168                                 if (fieldDecl == null) return null;
169                                 Visitor visitor = new Visitor();
170                                 fieldDecl.traverse(visitor, null);
171                                 return visitor.result;
172 //                      case IJavaElement.INITIALIZER:
173 //                              Initializer initializer = findInitializer((IInitializer)parent);
174 //                              if (initializer == null) return null;
175 //                              visitor = new Visitor();
176 //                              initializer.traverse(visitor, null);
177 //                              return visitor.result;
178                         case IJavaElement.METHOD:
179                                 AbstractMethodDeclaration methodDecl = findMethod((IMethod)parent);
180                                 if (methodDecl == null) return null;
181                                 visitor = new Visitor();
182                                 methodDecl.traverse(visitor, (ClassScope)null);
183                                 return visitor.result;
184                 }
185                 return null;
186         }
187 }