Package org.aspectj.org.eclipse.jdt.internal.core.search.matching

Source Code of org.aspectj.org.eclipse.jdt.internal.core.search.matching.SuperTypeNamesCollector

/*******************************************************************************
* Copyright (c) 2000, 2006 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
*******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.core.search.matching;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.aspectj.org.eclipse.jdt.core.*;
import org.aspectj.org.eclipse.jdt.core.ICompilationUnit;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.core.search.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.aspectj.org.eclipse.jdt.internal.core.*;
import org.aspectj.org.eclipse.jdt.internal.core.search.*;
import org.aspectj.org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
import org.aspectj.org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.aspectj.org.eclipse.jdt.internal.core.util.ASTNodeFinder;
import org.aspectj.org.eclipse.jdt.internal.core.util.Util;

/**
* Collects the super type names of a given declaring type.
* Returns NOT_FOUND_DECLARING_TYPE if the declaring type was not found.
* Returns null if the declaring type pattern doesn't require an exact match.
*/
public class SuperTypeNamesCollector {

  /**
   * An ast visitor that visits type declarations and member type declarations
   * collecting their super type names.
   */
  public class TypeDeclarationVisitor extends ASTVisitor {
    public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
      ReferenceBinding binding = typeDeclaration.binding;
      if (SuperTypeNamesCollector.this.matches(binding))
        SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
      return true;
    }
    public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
      ReferenceBinding binding = typeDeclaration.binding;
      if (SuperTypeNamesCollector.this.matches(binding))
        SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
      return true;
    }
    public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
      ReferenceBinding binding = memberTypeDeclaration.binding;
      if (SuperTypeNamesCollector.this.matches(binding))
        SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
      return true;
    }
    public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
      return false; // don't visit field declarations
    }
    public boolean visit(Initializer initializer, MethodScope scope) {
      return false; // don't visit initializers
    }
    public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
      return false; // don't visit constructor declarations
    }
    public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
      return false; // don't visit method declarations
    }
  }
SearchPattern pattern;
char[] typeSimpleName;
char[] typeQualification;
MatchLocator locator;
IType type;
IProgressMonitor progressMonitor;
char[][][] result;
int resultIndex;

public SuperTypeNamesCollector(
  SearchPattern pattern,
  char[] typeSimpleName,
  char[] typeQualification,
  MatchLocator locator,
  IType type,
  IProgressMonitor progressMonitor) {

  this.pattern = pattern;
  this.typeSimpleName = typeSimpleName;
  this.typeQualification = typeQualification;
  this.locator = locator;
  this.type = type;
  this.progressMonitor = progressMonitor;
}

protected void addToResult(char[][] compoundName) {
  int resultLength = this.result.length;
  for (int i = 0; i < resultLength; i++)
    if (CharOperation.equals(this.result[i], compoundName)) return; // already known

  if (resultLength == this.resultIndex)
    System.arraycopy(this.result, 0, this.result = new char[resultLength*2][][], 0, resultLength);
  this.result[this.resultIndex++] = compoundName;
}
/*
* Parse the given compiation unit and build its type bindings.
*/
protected CompilationUnitDeclaration buildBindings(ICompilationUnit compilationUnit, boolean isTopLevelOrMember) throws JavaModelException {
  // source unit
  org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnit;

  CompilationResult compilationResult = new CompilationResult(sourceUnit, 1, 1, 0);
  CompilationUnitDeclaration unit =
    isTopLevelOrMember ?
      this.locator.basicParser().dietParse(sourceUnit, compilationResult) :
      this.locator.basicParser().parse(sourceUnit, compilationResult);
  if (unit != null) {
    this.locator.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
    this.locator.lookupEnvironment.completeTypeBindings(unit, !isTopLevelOrMember);
    if (!isTopLevelOrMember) {
      if (unit.scope != null)
        unit.scope.faultInTypes(); // fault in fields & methods
      unit.resolve();
    }
  }
  return unit;
}
public char[][][] collect() throws JavaModelException {
  if (this.type != null) {
    // Collect the paths of the cus that are in the hierarchy of the given type
    this.result = new char[1][][];
    this.resultIndex = 0;
    JavaProject javaProject = (JavaProject) this.type.getJavaProject();
    this.locator.initialize(javaProject, 0);
    try {
      if (this.type.isBinary()) {
        BinaryTypeBinding binding = this.locator.cacheBinaryType(this.type, null);
        if (binding != null)
          collectSuperTypeNames(binding);
      } else {
        ICompilationUnit unit = this.type.getCompilationUnit();
        SourceType sourceType = (SourceType) this.type;
        boolean isTopLevelOrMember = sourceType.getOuterMostLocalContext() == null;
        CompilationUnitDeclaration parsedUnit = buildBindings(unit, isTopLevelOrMember);
        if (parsedUnit != null) {
          TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(this.type);
          if (typeDecl != null && typeDecl.binding != null)
            collectSuperTypeNames(typeDecl.binding);
        }
      }
    } catch (AbortCompilation e) {
      // problem with classpath: report inacurrate matches
      return null;
    }
    if (this.result.length > this.resultIndex)
      System.arraycopy(this.result, 0, this.result = new char[this.resultIndex][][], 0, this.resultIndex);
    return this.result;
  }

  // Collect the paths of the cus that declare a type which matches declaringQualification + declaringSimpleName
  String[] paths = this.getPathsOfDeclaringType();
  if (paths == null) return null;

  // Create bindings from source types and binary types and collect super type names of the type declaration
  // that match the given declaring type
  Util.sort(paths); // sort by projects
  JavaProject previousProject = null;
  this.result = new char[1][][];
  this.resultIndex = 0;
  for (int i = 0, length = paths.length; i < length; i++) {
    try {
      Openable openable = this.locator.handleFactory.createOpenable(paths[i], this.locator.scope);
      if (openable == null) continue; // outside classpath

      IJavaProject project = openable.getJavaProject();
      if (!project.equals(previousProject)) {
        previousProject = (JavaProject) project;
        this.locator.initialize(previousProject, 0);
      }
      if (openable instanceof ICompilationUnit) {
        ICompilationUnit unit = (ICompilationUnit) openable;
        CompilationUnitDeclaration parsedUnit = buildBindings(unit, true /*only toplevel and member types are visible to the focus type*/);
        if (parsedUnit != null)
          parsedUnit.traverse(new TypeDeclarationVisitor(), parsedUnit.scope);
      } else if (openable instanceof IClassFile) {
        IClassFile classFile = (IClassFile) openable;
        BinaryTypeBinding binding = this.locator.cacheBinaryType(classFile.getType(), null);
        if (matches(binding))
          collectSuperTypeNames(binding);
      }
    } catch (AbortCompilation e) {
      // ignore: continue with next element
    } catch (JavaModelException e) {
      // ignore: continue with next element
    }
  }
  if (this.result.length > this.resultIndex)
    System.arraycopy(this.result, 0, this.result = new char[this.resultIndex][][], 0, this.resultIndex);
  return this.result;
}
/**
* Collects the names of all the supertypes of the given type.
*/
protected void collectSuperTypeNames(ReferenceBinding binding) {
  ReferenceBinding superclass = binding.superclass();
  if (superclass != null) {
    this.addToResult(superclass.compoundName);
    this.collectSuperTypeNames(superclass);
  }

  ReferenceBinding[] interfaces = binding.superInterfaces();
  if (interfaces != null) {
    for (int i = 0; i < interfaces.length; i++) {
      ReferenceBinding interfaceBinding = interfaces[i];
      this.addToResult(interfaceBinding.compoundName);
      this.collectSuperTypeNames(interfaceBinding);
    }
  }
}
protected String[] getPathsOfDeclaringType() {
  if (this.typeQualification == null && this.typeSimpleName == null) return null;

  final PathCollector pathCollector = new PathCollector();
  IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
  IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
  SearchPattern searchPattern = new TypeDeclarationPattern(
    this.typeSimpleName != null ? null : this.typeQualification, // use the qualification only if no simple name
    null, // do find member types
    this.typeSimpleName,
    IIndexConstants.TYPE_SUFFIX,
    this.pattern.getMatchRule());
  IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
    public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) {
      TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
      if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) {  // filter out local and anonymous classes
        pathCollector.acceptIndexMatch(documentPath, indexRecord, participant, access);
      }
      return true;
    }   
  };   

  indexManager.performConcurrentJob(
    new PatternSearchJob(
      searchPattern,
      new JavaSearchParticipant(),
      scope,
      searchRequestor),
    IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
    progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
  return pathCollector.getPaths();
}
protected boolean matches(char[][] compoundName) {
  int length = compoundName.length;
  if (length == 0) return false;
  char[] simpleName = compoundName[length-1];
  int last = length - 1;
  if (this.typeSimpleName == null || this.pattern.matchesName(simpleName, this.typeSimpleName)) {
    // most frequent case: simple name equals last segment of compoundName
    char[][] qualification = new char[last][];
    System.arraycopy(compoundName, 0, qualification, 0, last);
    return this.pattern.matchesName(this.typeQualification, CharOperation.concatWith(qualification, '.'));
  }

  if (!CharOperation.endsWith(simpleName, this.typeSimpleName)) return false;

  // member type -> transform A.B.C$D into A.B.C.D
  System.arraycopy(compoundName, 0, compoundName = new char[length+1][], 0, last);
  int dollar = CharOperation.indexOf('$', simpleName);
  if (dollar == -1) return false;
  compoundName[last] = CharOperation.subarray(simpleName, 0, dollar);
  compoundName[length] = CharOperation.subarray(simpleName, dollar+1, simpleName.length);
  return this.matches(compoundName);
}
protected boolean matches(ReferenceBinding binding) {
  return binding != null && binding.compoundName != null && this.matches(binding.compoundName);
}
}
TOP

Related Classes of org.aspectj.org.eclipse.jdt.internal.core.search.matching.SuperTypeNamesCollector

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.