improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / util / ASTNodeFinder.java
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/ASTNodeFinder.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/ASTNodeFinder.java
new file mode 100644 (file)
index 0000000..40f0d2a
--- /dev/null
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core.util;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+import net.sourceforge.phpdt.internal.core.SourceType;
+import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
+import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
+import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
+
+/**
+ * Finds an ASTNode given an IJavaElement in a CompilationUnitDeclaration
+ */
+public class ASTNodeFinder {
+       private CompilationUnitDeclaration unit;
+
+       public ASTNodeFinder(CompilationUnitDeclaration unit) {
+               this.unit = unit;
+       }
+
+       /*
+        * Finds the FieldDeclaration in the given ast corresponding to the given field handle.
+        * Returns null if not found.
+        */
+       public FieldDeclaration findField(IField fieldHandle) {
+               TypeDeclaration typeDecl = findType((IType)fieldHandle.getParent());
+               if (typeDecl == null) return null;
+               FieldDeclaration[] fields = typeDecl.fields;
+               if (fields != null) {
+                       char[] fieldName = fieldHandle.getElementName().toCharArray();
+                       for (int i = 0, length = fields.length; i < length; i++) {
+                               FieldDeclaration field = fields[i];
+                               if (CharOperation.equals(fieldName, field.name)) {
+                                       return field;
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Finds the Initializer in the given ast corresponding to the given initializer handle.
+        * Returns null if not found.
+        */
+//     public Initializer findInitializer(IInitializer initializerHandle) {
+//             TypeDeclaration typeDecl = findType((IType)initializerHandle.getParent());
+//             if (typeDecl == null) return null;
+//             FieldDeclaration[] fields = typeDecl.fields;
+//             if (fields != null) {
+//                     int occurenceCount = ((JavaElement)initializerHandle).occurrenceCount;
+//                     for (int i = 0, length = fields.length; i < length; i++) {
+//                             FieldDeclaration field = fields[i];
+//                             if (field instanceof Initializer && --occurenceCount == 0) {
+//                                     return (Initializer)field;
+//                             }
+//                     }
+//             }
+//             return null;
+//     }
+
+       /*
+        * Finds the AbstractMethodDeclaration in the given ast corresponding to the given method handle.
+        * Returns null if not found.
+        */
+       public AbstractMethodDeclaration findMethod(IMethod methodHandle) {
+               TypeDeclaration typeDecl = findType((IType)methodHandle.getParent());
+               if (typeDecl == null) return null;
+               AbstractMethodDeclaration[] methods = typeDecl.methods;
+               if (methods != null) {
+                       char[] selector = methodHandle.getElementName().toCharArray();
+                       String[] parameterTypeSignatures = methodHandle.getParameterTypes();
+                       int parameterCount = parameterTypeSignatures.length;
+                       nextMethod: for (int i = 0, length = methods.length; i < length; i++) {
+                               AbstractMethodDeclaration method = methods[i];
+                               if (CharOperation.equals(selector, method.selector)) {
+                                       Argument[] args = method.arguments;
+                                       int argsLength = args == null ? 0 : args.length;
+                                       if (argsLength == parameterCount) {
+                                               for (int j = 0; j < parameterCount; j++) {
+                                                       TypeReference type = args[j].type;
+                                                       String signature = Util.typeSignature(type);
+                                                       if (!signature.equals(parameterTypeSignatures[j])) {
+                                                               continue nextMethod;
+                                                       }
+                                               }
+                                               return method;
+                                       }
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Finds the TypeDeclaration in the given ast corresponding to the given type handle.
+        * Returns null if not found.
+        */
+       public TypeDeclaration findType(IType typeHandle) {
+               IJavaElement parent = typeHandle.getParent();
+               final char[] typeName = typeHandle.getElementName().toCharArray();
+//             final int occurenceCount = ((SourceType)typeHandle).occurrenceCount;
+               final boolean findAnonymous = typeName.length == 0;
+               class Visitor extends ASTVisitor {
+                       TypeDeclaration result;
+                       int count = 0;
+                       public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+                               if (result != null) return false;
+//                             if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+//                                     if (findAnonymous && ++count == occurenceCount) {
+//                                             result = typeDeclaration;
+//                                     }
+//                             } else {
+                                       if (!findAnonymous && CharOperation.equals(typeName, typeDeclaration.name)) {
+                                               result = typeDeclaration;
+                                       }
+//                             }
+                               return false; // visit only one level
+                       }
+               }
+               switch (parent.getElementType()) {
+                       case IJavaElement.COMPILATION_UNIT:
+                               ArrayList types = this.unit.types;
+                               if (types != null) {
+                                       for (int i = 0, length = types.size(); i < length; i++) {
+                                               TypeDeclaration type = (TypeDeclaration)types.get(i);//[i];
+                                               if (CharOperation.equals(typeName, type.name)) {
+                                                       return type;
+                                               }
+                                       }
+                               }
+                               break;
+                       case IJavaElement.TYPE:
+                               TypeDeclaration parentDecl = findType((IType)parent);
+                               if (parentDecl == null) return null;
+//                             types = parentDecl.memberTypes;
+//                             if (types != null) {
+//                                     for (int i = 0, length = types.length; i < length; i++) {
+//                                             TypeDeclaration type = types[i];
+//                                             if (CharOperation.equals(typeName, type.name)) {
+//                                                     return type;
+//                                             }
+//                                     }
+//                             }
+                               break;
+                       case IJavaElement.FIELD:
+                               FieldDeclaration fieldDecl = findField((IField)parent);
+                               if (fieldDecl == null) return null;
+                               Visitor visitor = new Visitor();
+                               fieldDecl.traverse(visitor, null);
+                               return visitor.result;
+//                     case IJavaElement.INITIALIZER:
+//                             Initializer initializer = findInitializer((IInitializer)parent);
+//                             if (initializer == null) return null;
+//                             visitor = new Visitor();
+//                             initializer.traverse(visitor, null);
+//                             return visitor.result;
+                       case IJavaElement.METHOD:
+                               AbstractMethodDeclaration methodDecl = findMethod((IMethod)parent);
+                               if (methodDecl == null) return null;
+                               visitor = new Visitor();
+                               methodDecl.traverse(visitor, (ClassScope)null);
+                               return visitor.result;
+               }
+               return null;
+       }
+}