Package org.eclipse.php.internal.core.search

Source Code of org.eclipse.php.internal.core.search.PHPMatchLocator$LocalDeclarationVisitor

/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.core.search;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.declarations.FieldDeclaration;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.expressions.CallExpression;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.compiler.env.lookup.Scope;
import org.eclipse.dltk.compiler.util.HashtableOfIntValues;
import org.eclipse.dltk.core.*;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.matching.MatchLocator;
import org.eclipse.dltk.core.search.matching.PatternLocator;
import org.eclipse.dltk.internal.core.search.matching.MatchingNodeSet;
import org.eclipse.dltk.internal.core.search.matching.MethodPattern;
import org.eclipse.dltk.internal.core.search.matching.OrPattern;
import org.eclipse.php.core.compiler.PHPFlags;
import org.eclipse.php.internal.core.compiler.ast.nodes.NamespaceDeclaration;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPCallExpression;
import org.eclipse.php.internal.core.compiler.ast.parser.ASTUtils;

public class PHPMatchLocator extends MatchLocator {

  /**
   * An ast visitor that visits local type declarations.
   */
  public class LocalDeclarationVisitor extends ASTVisitor {

    IModelElement parent;
    MatchingNodeSet nodeSet;
    HashtableOfIntValues occurrencesCounts = new HashtableOfIntValues();

    public LocalDeclarationVisitor(IModelElement parent,
        MatchingNodeSet nodeSet) {
      this.parent = parent;
      this.nodeSet = nodeSet;
    }

    public boolean visit(Expression expression) {
      if (expression instanceof CallExpression) {
        try {
          FieldDeclaration constantDecl = ASTUtils
              .getConstantDeclaration((CallExpression) expression);
          if (constantDecl != null) {
            Integer level = (Integer) nodeSet.matchingNodes
                .removeKey(constantDecl);
            reportMatching(null, constantDecl, parent,
                level != null ? level.intValue() : -1, nodeSet);
            return false;
          }
        } catch (CoreException e) {
          throw new WrappedCoreException(e);
        }
      }
      return true;
    }

    public boolean visit(TypeDeclaration typeDeclaration) {
      if (typeDeclaration instanceof NamespaceDeclaration
          && ((NamespaceDeclaration) typeDeclaration).isGlobal()) {
        return false;
      }
      try {
        char[] simpleName = typeDeclaration.getName().toCharArray();
        int occurrenceCount = occurrencesCounts.get(simpleName);
        if (occurrenceCount == HashtableOfIntValues.NO_VALUE) {
          occurrenceCount = 1;
        } else {
          occurrenceCount = occurrenceCount + 1;
        }
        occurrencesCounts.put(simpleName, occurrenceCount);
        Integer level = (Integer) nodeSet.matchingNodes
            .removeKey(typeDeclaration);
        reportMatching(typeDeclaration, parent,
            level != null ? level.intValue() : -1, nodeSet,
            occurrenceCount);
        return false; // don't visit members as this was done during
      } catch (CoreException e) {
        throw new WrappedCoreException(e);
      }
    }

    public boolean visit(MethodDeclaration method) {
      try {
        Integer level = (Integer) nodeSet.matchingNodes
            .removeKey(method);
        reportMatching(null, method, parent,
            level != null ? level.intValue() : -1, nodeSet);
        return false; // don't visit members as this was done during
      } catch (CoreException e) {
        throw new WrappedCoreException(e);
      }
    }
  }

  protected void reportMatching(ModuleDeclaration module,
      MethodDeclaration method, IModelElement parent, int accuracy,
      MatchingNodeSet nodeSet) throws CoreException {
    if (parent == null) {
      parent = createSourceModuleHandle();
    }
    IModelElement enclosingElement = createHandle(method, parent);
    if (enclosingElement == null) {
      enclosingElement = createMethodHandle(method.getName());
    }
    if (accuracy > -1 && enclosingElement != null) { // skip if unable to
      // find method
      if (encloses(enclosingElement)) {
        SearchMatch match = null;
        if (DLTKCore.DEBUG) {
          System.out.println("TODO: AST Add constructor support."); //$NON-NLS-1$
        }
        match = this.patternLocator.newDeclarationMatch(method,
            enclosingElement, accuracy, this);
        if (match != null) {
          report(match);
        }
      }
    }

    // handle nodes for the local type first
    LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(
        enclosingElement, nodeSet);
    try {
      method.getBody().traverse(localDeclarationVisitor);
    } catch (Exception e) {
      if (DLTKCore.DEBUG) {
        e.printStackTrace();
      }
    }

    // references in this method
    ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(),
        method.sourceEnd());
    if (nodes != null) {
      if (parent == null) {
        parent = createSourceModuleHandle();
      }
      if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
        if (enclosingElement == null)
          enclosingElement = createHandle(method, parent);
        if (encloses(enclosingElement)) {
          for (int i = 0, l = nodes.length; i < l; i++) {
            ASTNode node = nodes[i];
            Integer level = (Integer) nodeSet.matchingNodes
                .removeKey(node);
            if (DLTKCore.DEBUG) {
              System.out
                  .println("TODO: Searching. Add scope support."); //$NON-NLS-1$
            }
            this.patternLocator.matchReportReference(node,
                enclosingElement, (Scope) null,
                level.intValue(), this);
          }
          return;
        }
      }
      for (int i = 0, l = nodes.length; i < l; i++)
        nodeSet.matchingNodes.removeKey(nodes[i]);
    }
  }

  protected void reportMatching(TypeDeclaration type,
      MethodDeclaration method, IModelElement parent, int accuracy,
      boolean typeInHierarchy, MatchingNodeSet nodeSet)
      throws CoreException {
    IModelElement enclosingElement = createHandle(method, parent);
    if (accuracy > -1 && enclosingElement != null) { // skip if unable to
      // find method
      if (encloses(enclosingElement)) {
        SearchMatch match = null;
        if (DLTKCore.DEBUG) {
          System.out.println("TODO: AST Add constructor support."); //$NON-NLS-1$
        }
        match = this.patternLocator.newDeclarationMatch(method,
            enclosingElement, accuracy, this);
        if (match != null) {
          report(match);
        }
      }
    }

    // handle nodes for the local type first
    LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(
        enclosingElement, nodeSet);
    try {
      method.getBody().traverse(localDeclarationVisitor);
    } catch (Exception e) {
      if (DLTKCore.DEBUG) {
        e.printStackTrace();
      }
    }

    // references in this method
    if (typeInHierarchy) {
      ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(),
          method.sourceEnd());
      if (nodes != null) {
        if ((this.matchContainer & PatternLocator.CLASS_CONTAINER) != 0) {
          if (enclosingElement == null)
            enclosingElement = createHandle(method, parent);
          if (encloses(enclosingElement)) {
            for (int i = 0, l = nodes.length; i < l; i++) {
              ASTNode node = nodes[i];
              Integer level = (Integer) nodeSet.matchingNodes
                  .removeKey(node);
              if (DLTKCore.DEBUG) {
                System.out
                    .println("TODO: Searching. Add scope support."); //$NON-NLS-1$
              }
              this.patternLocator.matchReportReference(node,
                  enclosingElement, (Scope) null,
                  level.intValue(), this);
            }
            return;
          }
        }
        for (int i = 0, l = nodes.length; i < l; i++)
          nodeSet.matchingNodes.removeKey(nodes[i]);
      }
    }
  }

  protected void reportMatching(TypeDeclaration type, IModelElement parent,
      int accuracy, MatchingNodeSet nodeSet, int occurrenceCount)
      throws CoreException {
    if (parent != null && parent.getElementType() == IModelElement.METHOD) {
      // All PHP elements declared inside of function are automatically
      // belonging
      // to the global scope. When parent = null parent implementation
      // uses source module:
      parent = null;
    }
    super.reportMatching(type, parent, accuracy, nodeSet, occurrenceCount);
  }

  @Override
  public SearchMatch newMethodReferenceMatch(IModelElement enclosingElement,
      int accuracy, int offset, int length, boolean isConstructor,
      boolean isSynthetic, ASTNode reference) {
    return newMethodReferenceMatch(enclosingElement, accuracy, offset,
        length, isConstructor, isSynthetic, reference, pattern);
  }

  public SearchMatch newMethodReferenceMatch(IModelElement enclosingElement,
      int accuracy, int offset, int length, boolean isConstructor,
      boolean isSynthetic, ASTNode reference, SearchPattern pattern) {
    if (pattern instanceof MethodPattern
        && (reference instanceof PHPCallExpression)) {
      PHPCallExpression pce = (PHPCallExpression) reference;
      ISourceModule module = (ISourceModule) enclosingElement
          .getAncestor(IModelElement.SOURCE_MODULE);
      if (module != null) {
        try {
          MethodPattern methodPattern = (MethodPattern) pattern;
          IModelElement[] elements = module.codeSelect(pce
              .getCallName().sourceStart(), 0);
          if (elements == null || elements.length == 0) {
            return super.newMethodReferenceMatch(enclosingElement,
                accuracy, offset, length, isConstructor,
                isSynthetic, reference);
          } else {
            for (int i = 0; i < elements.length; i++) {
              if (pattern.focus != null) {
                if (pattern.focus.equals(elements[i])) {
                  return super.newMethodReferenceMatch(
                      enclosingElement, accuracy, offset,
                      length, isConstructor, isSynthetic,
                      reference);
                }
              } else {
                if (methodPattern.declaringSimpleName != null
                    && elements[i]
                        .getAncestor(IModelElement.TYPE) != null
                    && PHPFlags
                        .isClass(((IType) elements[i]
                            .getAncestor(IModelElement.TYPE))
                            .getFlags())
                    && new String(
                        methodPattern.declaringSimpleName)
                        .equalsIgnoreCase(((IType) elements[i]
                            .getParent())
                            .getElementName())) {

                  return super.newMethodReferenceMatch(
                      enclosingElement, accuracy, offset,
                      length, isConstructor, isSynthetic,
                      reference);
                } else if (methodPattern.declaringSimpleName == null
                    && (elements[i]
                        .getAncestor(IModelElement.TYPE) == null || elements[i]
                        .getAncestor(IModelElement.TYPE) != null
                        && !PHPFlags
                            .isClass(((IType) elements[i]
                                .getAncestor(IModelElement.TYPE))
                                .getFlags()))) {

                  return super.newMethodReferenceMatch(
                      enclosingElement, accuracy, offset,
                      length, isConstructor, isSynthetic,
                      reference);
                } else if (methodPattern.declaringSimpleName == null
                    && methodPattern.selector != null
                    && new String(methodPattern.selector)
                        .equals(elements[i]
                            .getElementName())) {

                  return super.newMethodReferenceMatch(
                      enclosingElement, accuracy, offset,
                      length, isConstructor, isSynthetic,
                      reference);
                }

                // if (new String(methodPattern.selector)
                // .equals(elements[i].getElementName())) {
                // return super.newMethodReferenceMatch(
                // enclosingElement, accuracy, offset,
                // length, isConstructor, isSynthetic,
                // reference);
                // }

              }
            }
          }

        } catch (ModelException e) {
          e.printStackTrace();
        }
      }
    } else if (pattern instanceof OrPattern) {
      for (SearchPattern searchPattern : ((OrPattern) pattern)
          .getPatterns()) {
        if (searchPattern instanceof MethodPattern) {
          return newMethodReferenceMatch(enclosingElement, accuracy,
              offset, length, isConstructor, isSynthetic,
              reference, searchPattern);
        }

      }
    }
    return null;
  }

  private boolean isMethodPattern() {
    if (pattern instanceof MethodPattern) {
      return true;
    } else if (pattern instanceof OrPattern) {
      SearchPattern[] patterns = ((OrPattern) pattern).getPatterns();
      for (int i = 0; i < patterns.length; i++) {
        if (patterns[i] instanceof MethodPattern) {
          return true;
        }
      }
    }
    return false;
  }
}
TOP

Related Classes of org.eclipse.php.internal.core.search.PHPMatchLocator$LocalDeclarationVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.