Package org.eclipse.jdt.core.dom

Source Code of org.eclipse.jdt.core.dom.Requestor

/*******************************************************************************
* Copyright (c) 2000, 2010 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.eclipse.jdt.core.dom;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.compiler.util.Messages;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.BinaryMember;
import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
import org.eclipse.jdt.internal.core.CancelableProblemFactory;
import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.SourceRefElement;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
import org.eclipse.jdt.internal.core.util.BindingKeyResolver;
import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
import org.eclipse.jdt.internal.core.util.DOMFinder;

class CompilationUnitResolver extends Compiler {
  public static final int RESOLVE_BINDING = 0x1;
  public static final int PARTIAL = 0x2;
  public static final int STATEMENT_RECOVERY = 0x4;
  public static final int IGNORE_METHOD_BODIES = 0x8;
  public static final int BINDING_RECOVERY = 0x10;
  public static final int INCLUDE_RUNNING_VM_BOOTCLASSPATH = 0x20;

  /* A list of int */
  static class IntArrayList {
    public int[] list = new int[5];
    public int length = 0;
    public void add(int i) {
      if (this.list.length == this.length) {
        System.arraycopy(this.list, 0, this.list = new int[this.length*2], 0, this.length);
      }
        this.list[this.length++] = i;
      }
    }

  /*
   * The sources that were requested.
   * Map from file name (char[]) to org.eclipse.jdt.internal.compiler.env.ICompilationUnit.
   */
  HashtableOfObject requestedSources;

  /*
   * The binding keys that were requested.
   * Map from file name (char[]) to BindingKey (or ArrayList if multiple keys in the same file).
   */
  HashtableOfObject requestedKeys;

  DefaultBindingResolver.BindingTables bindingTables;

  boolean hasCompilationAborted;

  private IProgressMonitor monitor;
 
  /**
   * Set to <code>true</code> if the receiver was initialized using a java project name environment
   */
  boolean fromJavaProject;

  /**
   * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
   * The environment and options will be in effect for the lifetime of the compiler.
   * When the compiler is run, compilation results are sent to the given requestor.
   *
   *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
   *      Environment used by the compiler in order to resolve type and package
   *      names. The name environment implements the actual connection of the compiler
   *      to the outside world (for example, in batch mode the name environment is performing
   *      pure file accesses, reuse previous build state or connection to repositories).
   *      Note: the name environment is responsible for implementing the actual classpath
   *            rules.
   *
   *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
   *      Configurable part for problem handling, allowing the compiler client to
   *      specify the rules for handling problems (stop on first error or accumulate
   *      them all) and at the same time perform some actions such as opening a dialog
   *      in UI when compiling interactively.
   *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
   *
   *  @param compilerOptions The compiler options to use for the resolution.
   *
   *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
   *      Component which will receive and persist all compilation results and is intended
   *      to consume them as they are produced. Typically, in a batch compiler, it is
   *      responsible for writing out the actual .class files to the file system.
   *      @see org.eclipse.jdt.internal.compiler.CompilationResult
   *
   *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
   *      Factory used inside the compiler to create problem descriptors. It allows the
   *      compiler client to supply its own representation of compilation problems in
   *      order to avoid object conversions. Note that the factory is not supposed
   *      to accumulate the created problems, the compiler will gather them all and hand
   *      them back as part of the compilation unit result.
   */
  public CompilationUnitResolver(
    INameEnvironment environment,
    IErrorHandlingPolicy policy,
    CompilerOptions compilerOptions,
    ICompilerRequestor requestor,
    IProblemFactory problemFactory,
    IProgressMonitor monitor,
    boolean fromJavaProject) {

    super(environment, policy, compilerOptions, requestor, problemFactory);
    this.hasCompilationAborted = false;
    this.monitor =monitor;
    this.fromJavaProject = fromJavaProject;
  }

  /*
   * Add additional source types
   */
  public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
    // Need to reparse the entire source of the compilation unit so as to get source positions
    // (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
    SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
    accept((org.eclipse.jdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getCompilationUnit(), accessRestriction);
  }
 
  public synchronized void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
    super.accept(sourceUnit, accessRestriction);
  }

  /**
   * Add the initial set of compilation units into the loop
   *  ->  build compilation unit declarations, their bindings and record their results.
   */
  protected void beginToCompile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
    int sourceLength = sourceUnits.length;
    int keyLength = bindingKeys.length;
    int maxUnits = sourceLength + keyLength;
    this.totalUnits = 0;
    this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
    int index = 0;

    // walks the source units
    this.requestedSources = new HashtableOfObject();
    for (int i = 0; i < sourceLength; i++) {
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
      CompilationUnitDeclaration parsedUnit;
      CompilationResult unitResult =
        new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
      try {
        if (this.options.verbose) {
          this.out.println(
            Messages.bind(Messages.compilation_request,
            new String[] {
              String.valueOf(index++ + 1),
              String.valueOf(maxUnits),
              new String(sourceUnit.getFileName())
            }));
        }
        // diet parsing for large collection of units
        if (this.totalUnits < this.parseThreshold) {
          parsedUnit = this.parser.parse(sourceUnit, unitResult);
        } else {
          parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
        }
        // initial type binding creation
        this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
        addCompilationUnit(sourceUnit, parsedUnit);
        this.requestedSources.put(unitResult.getFileName(), sourceUnit);
        worked(1);
      } finally {
        sourceUnits[i] = null; // no longer hold onto the unit
      }
    }

    // walk the binding keys
    this.requestedKeys = new HashtableOfObject();
    for (int i = 0; i < keyLength; i++) {
      BindingKeyResolver resolver = new BindingKeyResolver(bindingKeys[i], this, this.lookupEnvironment);
      resolver.parse(true/*pause after fully qualified name*/);
      // If it doesn't have a type name, then it is either an array type, package or base type, which will definitely not have a compilation unit.
      // Skipping it will speed up performance because the call will open jars. (theodora)
      CompilationUnitDeclaration parsedUnit = resolver.hasTypeName() ? resolver.getCompilationUnitDeclaration() : null;
      if (parsedUnit != null) {
        char[] fileName = parsedUnit.compilationResult.getFileName();
        Object existing = this.requestedKeys.get(fileName);
        if (existing == null)
          this.requestedKeys.put(fileName, resolver);
        else if (existing instanceof ArrayList)
          ((ArrayList) existing).add(resolver);
        else {
          ArrayList list = new ArrayList();
          list.add(existing);
          list.add(resolver);
          this.requestedKeys.put(fileName, list);
        }

      } else {
        char[] key = resolver.hasTypeName()
          ? resolver.getKey().toCharArray() // binary binding
          : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding
        this.requestedKeys.put(key, resolver);
      }
      worked(1);
    }

    // binding resolution
    this.lookupEnvironment.completeTypeBindings();
  }

  IBinding createBinding(String key) {
    if (this.bindingTables == null)
      throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
    BindingKeyResolver keyResolver = new BindingKeyResolver(key, this, this.lookupEnvironment);
    Binding compilerBinding = keyResolver.getCompilerBinding();
    if (compilerBinding == null) return null;
    DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables, false, this.fromJavaProject);
    return resolver.getBinding(compilerBinding);
  }

  public static CompilationUnit convert(
      CompilationUnitDeclaration compilationUnitDeclaration,
      char[] source,
      int apiLevel,
      Map options,
      boolean needToResolveBindings,
      WorkingCopyOwner owner,
      DefaultBindingResolver.BindingTables bindingTables,
      int flags,
      IProgressMonitor monitor,
      boolean fromJavaProject) {
    BindingResolver resolver = null;
    AST ast = AST.newAST(apiLevel);
    ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
    CompilationUnit compilationUnit = null;
    ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
    if (needToResolveBindings) {
      resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, fromJavaProject);
      ast.setFlag(flags | AST.RESOLVED_BINDINGS);
    } else {
      resolver = new BindingResolver();
      ast.setFlag(flags);
    }
    ast.setBindingResolver(resolver);
    converter.setAST(ast);
    compilationUnit = converter.convert(compilationUnitDeclaration, source);
    compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
    ast.setDefaultNodeFlag(0);
    ast.setOriginalModificationCount(ast.modificationCount());
    return compilationUnit;
  }

  protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
    CompilerOptions compilerOptions = new CompilerOptions(options);
    compilerOptions.performMethodsFullRecovery = statementsRecovery;
    compilerOptions.performStatementsRecovery = statementsRecovery;
    compilerOptions.parseLiteralExpressionsAsConstants = false;
    compilerOptions.storeAnnotations = true /*store annotations in the bindings*/;
    return compilerOptions;
  }
  /*
   *  Low-level API performing the actual compilation
   */
  protected static IErrorHandlingPolicy getHandlingPolicy() {

    // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
    return new IErrorHandlingPolicy() {
      public boolean stopOnFirstError() {
        return false;
      }
      public boolean proceedOnErrors() {
        return false; // stop if there are some errors
      }
    };
  }

  /*
   * Answer the component to which will be handed back compilation results from the compiler
   */
  protected static ICompilerRequestor getRequestor() {
    return new ICompilerRequestor() {
      public void acceptResult(CompilationResult compilationResult) {
        // do nothing
      }
    };
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
   */
  public void initializeParser() {
    this.parser = new CommentRecorderParser(this.problemReporter, false);
  }
  public void process(CompilationUnitDeclaration unit, int i) {
    // don't resolve a second time the same unit (this would create the same binding twice)
    char[] fileName = unit.compilationResult.getFileName();
    if (this.requestedKeys.get(fileName) == null && this.requestedSources.get(fileName) == null)
      super.process(unit, i);
  }
  /*
   * Compiler crash recovery in case of unexpected runtime exceptions
   */
  protected void handleInternalException(
      Throwable internalException,
      CompilationUnitDeclaration unit,
      CompilationResult result) {
    super.handleInternalException(internalException, unit, result);
    if (unit != null) {
      removeUnresolvedBindings(unit);
    }
  }

  /*
   * Compiler recovery in case of internal AbortCompilation event
   */
  protected void handleInternalException(
      AbortCompilation abortException,
      CompilationUnitDeclaration unit) {
    super.handleInternalException(abortException, unit);
    if (unit != null) {
      removeUnresolvedBindings(unit);
    }
    this.hasCompilationAborted = true;
  }

  public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
    try {
      CompilerOptions compilerOptions = new CompilerOptions(options);
      compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
      Parser parser = new CommentRecorderParser(
        new ProblemReporter(
            DefaultErrorHandlingPolicies.proceedWithAllProblems(),
            compilerOptions,
            new DefaultProblemFactory()),
        false);
      int unitLength = compilationUnits.length;
      if (monitor != null) monitor.beginTask("", unitLength); //$NON-NLS-1$
      for (int i = 0; i < unitLength; i++) {
        org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
        CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
        CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

        if (compilationUnitDeclaration.ignoreMethodBodies) {
          compilationUnitDeclaration.ignoreFurtherInvestigation = true;
          // if initial diet parse did not work, no need to dig into method bodies.
          continue;
        }

        //fill the methods bodies in order for the code to be generated
        //real parse of the method....
        org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
        if (types != null) {
          for (int j = 0, typeLength = types.length; j < typeLength; j++) {
            types[j].parseMethods(parser, compilationUnitDeclaration);
          }
        }

        // convert AST
        CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, flags /* flags */, monitor, true);
        node.setTypeRoot(compilationUnits[i]);

        // accept AST
        astRequestor.acceptAST(compilationUnits[i], node);

        if (monitor != null) monitor.worked(1);
      }
    } finally {
      if (monitor != null) monitor.done();
    }
  }
  public static void parse(
      String[] sourceUnits,
      String[] encodings,
      FileASTRequestor astRequestor,
      int apiLevel,
      Map options,
      int flags,
      IProgressMonitor monitor) {
    try {
      CompilerOptions compilerOptions = new CompilerOptions(options);
      compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
      Parser parser = new CommentRecorderParser(
        new ProblemReporter(
            DefaultErrorHandlingPolicies.proceedWithAllProblems(),
            compilerOptions,
            new DefaultProblemFactory()),
        false);
      int unitLength = sourceUnits.length;
      if (monitor != null) monitor.beginTask("", unitLength); //$NON-NLS-1$
      for (int i = 0; i < unitLength; i++) {
        char[] contents = null;
        String encoding = encodings != null ? encodings[i] : null;
        try {
          contents = Util.getFileCharContent(new File(sourceUnits[i]), encoding);
        } catch(IOException e) {
          // go to the next unit
          continue;
        }
        if (contents == null) {
          // go to the next unit
          continue;
        }
        org.eclipse.jdt.internal.compiler.batch.CompilationUnit compilationUnit = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnits[i], encoding);
        org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationUnit;
        CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
        CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

        if (compilationUnitDeclaration.ignoreMethodBodies) {
          compilationUnitDeclaration.ignoreFurtherInvestigation = true;
          // if initial diet parse did not work, no need to dig into method bodies.
          continue;
        }

        //fill the methods bodies in order for the code to be generated
        //real parse of the method....
        org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
        if (types != null) {
          for (int j = 0, typeLength = types.length; j < typeLength; j++) {
            types[j].parseMethods(parser, compilationUnitDeclaration);
          }
        }

        // convert AST
        CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, flags /* flags */, monitor, true);
        node.setTypeRoot(null);

        // accept AST
        astRequestor.acceptAST(sourceUnits[i], node);

        if (monitor != null) monitor.worked(1);
      }
    } finally {
      if (monitor != null) monitor.done();
    }
  }
  public static CompilationUnitDeclaration parse(
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
      NodeSearcher nodeSearcher,
      Map settings,
      int flags) {
    if (sourceUnit == null) {
      throw new IllegalStateException();
    }
    CompilerOptions compilerOptions = new CompilerOptions(settings);
    boolean statementsRecovery = (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
    compilerOptions.performMethodsFullRecovery = statementsRecovery;
    compilerOptions.performStatementsRecovery = statementsRecovery;
    compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
    Parser parser = new CommentRecorderParser(
      new ProblemReporter(
          DefaultErrorHandlingPolicies.proceedWithAllProblems(),
          compilerOptions,
          new DefaultProblemFactory()),
      false);
    CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
    CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

    if (compilationUnitDeclaration.ignoreMethodBodies) {
      compilationUnitDeclaration.ignoreFurtherInvestigation = true;
      // if initial diet parse did not work, no need to dig into method bodies.
      return compilationUnitDeclaration;
    }

    if (nodeSearcher != null) {
      char[] source = parser.scanner.getSource();
      int searchPosition = nodeSearcher.position;
      if (searchPosition < 0 || searchPosition > source.length) {
        // the position is out of range. There is no need to search for a node.
        return compilationUnitDeclaration;
      }

      compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);

      org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
      if (node == null) {
        return compilationUnitDeclaration;
      }

      org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;

      if (node instanceof AbstractMethodDeclaration) {
        ((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
      } else if (enclosingTypeDeclaration != null) {
        if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
          ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
        } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
          ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(parser, compilationUnitDeclaration);
        }
      }
    } else {
        //fill the methods bodies in order for the code to be generated
        //real parse of the method....     
        org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
        if (types != null) {
          for (int j = 0, typeLength = types.length; j < typeLength; j++) {
            types[j].parseMethods(parser, compilationUnitDeclaration);
          }
        }
    }
    return compilationUnitDeclaration;
  }

  public static void resolve(
    ICompilationUnit[] compilationUnits,
    String[] bindingKeys,
    ASTRequestor requestor,
    int apiLevel,
    Map options,
    IJavaProject javaProject,
    WorkingCopyOwner owner,
    int flags,
    IProgressMonitor monitor) {

    CancelableNameEnvironment environment = null;
    CancelableProblemFactory problemFactory = null;
    try {
      if (monitor != null) {
        int amountOfWork = (compilationUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
        monitor.beginTask("", amountOfWork); //$NON-NLS-1$
      }
      environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
      problemFactory = new CancelableProblemFactory(monitor);
      CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
      compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
      CompilationUnitResolver resolver =
        new CompilationUnitResolver(
          environment,
          getHandlingPolicy(),
          compilerOptions,
          getRequestor(),
          problemFactory,
          monitor,
          javaProject != null);
      resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
      if (NameLookup.VERBOSE) {
        System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
        System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
      }
    } catch (JavaModelException e) {
      // project doesn't exist -> simple parse without resolving
      parse(compilationUnits, requestor, apiLevel, options, flags, monitor);
    } finally {
      if (monitor != null) monitor.done();
      if (environment != null) {
        environment.setMonitor(null); // don't hold a reference to this external object
      }
      if (problemFactory != null) {
        problemFactory.monitor = null; // don't hold a reference to this external object
      }
    }
  }
  public static void resolve(
      String[] sourceUnits,
      String[] encodings,
      String[] bindingKeys,
      FileASTRequestor requestor,
      int apiLevel,
      Map options,
      List classpaths,
      int flags,
      IProgressMonitor monitor) {

      INameEnvironmentWithProgress environment = null;
      CancelableProblemFactory problemFactory = null;
      try {
        if (monitor != null) {
          int amountOfWork = (sourceUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
          monitor.beginTask("", amountOfWork); //$NON-NLS-1$
        }
        Classpath[] allEntries = new Classpath[classpaths.size()];
        classpaths.toArray(allEntries);
        environment = new NameEnvironmentWithProgress(allEntries, null, monitor);
        problemFactory = new CancelableProblemFactory(monitor);
        CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
        compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
        CompilationUnitResolver resolver =
          new CompilationUnitResolver(
            environment,
            getHandlingPolicy(),
            compilerOptions,
            getRequestor(),
            problemFactory,
            monitor,
            false);
        resolver.resolve(sourceUnits, encodings, bindingKeys, requestor, apiLevel, options, flags);
        if (NameLookup.VERBOSE && (environment instanceof CancelableNameEnvironment)) {
          CancelableNameEnvironment cancelableNameEnvironment = (CancelableNameEnvironment) environment;
          System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
          System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
        }
      } finally {
        if (monitor != null) monitor.done();
        if (environment != null) {
          environment.setMonitor(null); // don't hold a reference to this external object
        }
        if (problemFactory != null) {
          problemFactory.monitor = null; // don't hold a reference to this external object
        }
      }
    }
  public static CompilationUnitDeclaration resolve(
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
      IJavaProject javaProject,
      List classpaths,
      NodeSearcher nodeSearcher,
      Map options,
      WorkingCopyOwner owner,
      int flags,
      IProgressMonitor monitor) throws JavaModelException {

    CompilationUnitDeclaration unit = null;
    INameEnvironmentWithProgress environment = null;
    CancelableProblemFactory problemFactory = null;
    CompilationUnitResolver resolver = null;
    try {
      if (javaProject == null) {
        Classpath[] allEntries = new Classpath[classpaths.size()];
        classpaths.toArray(allEntries);
        environment = new NameEnvironmentWithProgress(allEntries, null, monitor);
      } else {
        environment = new CancelableNameEnvironment((JavaProject) javaProject, owner, monitor);
      }
      problemFactory = new CancelableProblemFactory(monitor);
      CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
      boolean ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
      compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
      resolver =
        new CompilationUnitResolver(
          environment,
          getHandlingPolicy(),
          compilerOptions,
          getRequestor(),
          problemFactory,
          monitor,
          javaProject != null);
      boolean analyzeAndGenerateCode = !ignoreMethodBodies;
      unit =
        resolver.resolve(
          null, // no existing compilation unit declaration
          sourceUnit,
          nodeSearcher,
          true, // method verification
          analyzeAndGenerateCode, // analyze code
          analyzeAndGenerateCode); // generate code
      if (resolver.hasCompilationAborted) {
        // the bindings could not be resolved due to missing types in name environment
        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
        CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
        final int problemCount = unit.compilationResult.problemCount;
        if (problemCount != 0) {
          unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
          System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
          unitDeclaration.compilationResult.problemCount = problemCount;
        }
        return unitDeclaration;
      }
      if (NameLookup.VERBOSE && environment instanceof CancelableNameEnvironment) {
        CancelableNameEnvironment cancelableNameEnvironment = (CancelableNameEnvironment) environment;
        System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
        System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms")//$NON-NLS-1$ //$NON-NLS-2$
      }
      return unit;
    } finally {
      if (environment != null) {
        // don't hold a reference to this external object
        environment.setMonitor(null);
      }
      if (problemFactory != null) {
        problemFactory.monitor = null; // don't hold a reference to this external object
      }
    }
  }
  public static IBinding[] resolve(
    final IJavaElement[] elements,
    int apiLevel,
    Map compilerOptions,
    IJavaProject javaProject,
    WorkingCopyOwner owner,
    int flags,
    IProgressMonitor monitor) {

    final int length = elements.length;
    final HashMap sourceElementPositions = new HashMap(); // a map from ICompilationUnit to int[] (positions in elements)
    int cuNumber = 0;
    final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
    for (int i = 0; i < length; i++) {
      IJavaElement element = elements[i];
      if (!(element instanceof SourceRefElement))
        throw new IllegalStateException(element + " is not part of a compilation unit or class file"); //$NON-NLS-1$
      Object cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
      if (cu != null) {
        // source member
        IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
        if (intList == null) {
          sourceElementPositions.put(cu, intList = new IntArrayList());
          cuNumber++;
        }
        intList.add(i);
      } else {
        // binary member
        try {
          String key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
          binaryElementPositions.put(key, i);
        } catch (JavaModelException e) {
          throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
        }
      }
    }
    ICompilationUnit[] cus = new ICompilationUnit[cuNumber];
    sourceElementPositions.keySet().toArray(cus);

    int bindingKeyNumber = binaryElementPositions.size();
    String[] bindingKeys = new String[bindingKeyNumber];
    binaryElementPositions.keysToArray(bindingKeys);

    class Requestor extends ASTRequestor {
      IBinding[] bindings = new IBinding[length];
      public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
        // TODO (jerome) optimize to visit the AST only once
        IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
        for (int i = 0; i < intList.length; i++) {
          final int index = intList.list[i];
          SourceRefElement element = (SourceRefElement) elements[index];
          DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
          try {
            finder.search();
          } catch (JavaModelException e) {
            throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
          }
          this.bindings[index] = finder.foundBinding;
        }
      }
      public void acceptBinding(String bindingKey, IBinding binding) {
        int index = binaryElementPositions.get(bindingKey);
        this.bindings[index] = binding;
      }
    }
    Requestor requestor = new Requestor();
    resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
    return requestor.bindings;
  }
  /*
   * When unit result is about to be accepted, removed back pointers
   * to unresolved bindings
   */
  public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
    final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
    if (types != null) {
      for (int i = 0, max = types.length; i < max; i++) {
        removeUnresolvedBindings(types[i]);
      }
    }
  }
  private void removeUnresolvedBindings(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type) {
    final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
    if (memberTypes != null) {
      for (int i = 0, max = memberTypes.length; i < max; i++){
        removeUnresolvedBindings(memberTypes[i]);
      }
    }
    if (type.binding != null && (type.binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
      type.binding = null;
    }

    final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
    if (fields != null) {
      for (int i = 0, max = fields.length; i < max; i++){
        if (fields[i].binding != null && (fields[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
          fields[i].binding = null;
        }
      }
    }

    final AbstractMethodDeclaration[] methods = type.methods;
    if (methods != null) {
      for (int i = 0, max = methods.length; i < max; i++){
        if (methods[i].binding !=  null && (methods[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
          methods[i].binding = null;
        }
      }
    }
  }

  private void resolve(
      ICompilationUnit[] compilationUnits,
      String[] bindingKeys,
      ASTRequestor astRequestor,
      int apiLevel,
      Map compilerOptions,
      WorkingCopyOwner owner,
      int flags) {

    // temporarily connect ourselves to the ASTResolver - must disconnect when done
    astRequestor.compilationUnitResolver = this;
    this.bindingTables = new DefaultBindingResolver.BindingTables();
    CompilationUnitDeclaration unit = null;
    try {
      int length = compilationUnits.length;
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
      System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
      beginToCompile(sourceUnits, bindingKeys);
      // process all units (some more could be injected in the loop by the lookup environment)
      for (int i = 0; i < this.totalUnits; i++) {
        if (resolvedRequestedSourcesAndKeys(i)) {
          // no need to keep resolving if no more ASTs and no more binding keys are needed
          // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
          // cleanup remaining units
          for (; i < this.totalUnits; i++) {
            this.unitsToProcess[i].cleanUp();
            this.unitsToProcess[i] = null;
          }
          break;
        }
        unit = this.unitsToProcess[i];
        try {
          super.process(unit, i); // this.process(...) is optimized to not process already known units

          // requested AST
          char[] fileName = unit.compilationResult.getFileName();
          ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
          if (source != null) {
            // convert AST
            CompilationResult compilationResult = unit.compilationResult;
            org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
            char[] contents = sourceUnit.getContents();
            AST ast = AST.newAST(apiLevel);
            ast.setFlag(flags | AST.RESOLVED_BINDINGS);
            ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
            ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
            BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, this.fromJavaProject);
            ast.setBindingResolver(resolver);
            converter.setAST(ast);
            CompilationUnit compilationUnit = converter.convert(unit, contents);
            compilationUnit.setTypeRoot(source);
            compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
            ast.setDefaultNodeFlag(0);
            ast.setOriginalModificationCount(ast.modificationCount());

            // pass it to requestor
            astRequestor.acceptAST(source, compilationUnit);

            worked(1);

            // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
            this.requestedSources.put(fileName, null); // mark it as removed
          }

          // requested binding
          Object key = this.requestedKeys.get(fileName);
          if (key != null) {
            if (key instanceof BindingKeyResolver) {
              reportBinding(key, astRequestor, owner, unit);
              worked(1);
            } else if (key instanceof ArrayList) {
              Iterator iterator = ((ArrayList) key).iterator();
              while (iterator.hasNext()) {
                reportBinding(iterator.next(), astRequestor, owner, unit);
                worked(1);
              }
            }

            // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
            this.requestedKeys.put(fileName, null); // mark it as removed
          }
        } finally {
          // cleanup compilation unit result
          unit.cleanUp();
        }
        this.unitsToProcess[i] = null; // release reference to processed unit declaration
        this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
      }

      // remaining binding keys
      DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, true);
      Object[] keys = this.requestedKeys.valueTable;
      for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
        BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
        if (keyResolver == null) continue;
        Binding compilerBinding = keyResolver.getCompilerBinding();
        IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
        // pass it to requestor
        astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
        worked(1);
      }
    } catch (OperationCanceledException e) {
      throw e;
    } catch (AbortCompilation e) {
      this.handleInternalException(e, unit);
    } catch (Error e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } catch (RuntimeException e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } finally {
      // disconnect ourselves from ast requestor
      astRequestor.compilationUnitResolver = null;
    }
  }

  private void resolve(
      String[] sourceCompilationUnits,
      String[] encodings,
      String[] bindingKeys,
      FileASTRequestor astRequestor,
      int apiLevel,
      Map compilerOptions,
      int flags) {

    // temporarily connect ourselves to the ASTResolver - must disconnect when done
    astRequestor.compilationUnitResolver = this;
    this.bindingTables = new DefaultBindingResolver.BindingTables();
    CompilationUnitDeclaration unit = null;
    try {
      int length = sourceCompilationUnits.length;
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
      int count = 0;
      for (int i = 0; i < length; i++) {
        char[] contents = null;
        String encoding = encodings != null ? encodings[i] : null;
        String sourceUnitPath = sourceCompilationUnits[i];
        try {
          contents = Util.getFileCharContent(new File(sourceUnitPath), encoding);
        } catch(IOException e) {
          // go to the next unit
          continue;
        }
        if (contents == null) {
          // go to the next unit
          continue;
        }
        sourceUnits[count++] = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnitPath, encoding);
      }
      beginToCompile(sourceUnits, bindingKeys);
      // process all units (some more could be injected in the loop by the lookup environment)
      for (int i = 0; i < this.totalUnits; i++) {
        if (resolvedRequestedSourcesAndKeys(i)) {
          // no need to keep resolving if no more ASTs and no more binding keys are needed
          // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
          // cleanup remaining units
          for (; i < this.totalUnits; i++) {
            this.unitsToProcess[i].cleanUp();
            this.unitsToProcess[i] = null;
          }
          break;
        }
        unit = this.unitsToProcess[i];
        try {
          super.process(unit, i); // this.process(...) is optimized to not process already known units

          // requested AST
          char[] fileName = unit.compilationResult.getFileName();
          org.eclipse.jdt.internal.compiler.env.ICompilationUnit source = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.requestedSources.get(fileName);
          if (source != null) {
            // convert AST
            CompilationResult compilationResult = unit.compilationResult;
            org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
            char[] contents = sourceUnit.getContents();
            AST ast = AST.newAST(apiLevel);
            ast.setFlag(flags | AST.RESOLVED_BINDINGS);
            ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
            ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
            BindingResolver resolver = new DefaultBindingResolver(unit.scope, null, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, this.fromJavaProject);
            ast.setBindingResolver(resolver);
            converter.setAST(ast);
            CompilationUnit compilationUnit = converter.convert(unit, contents);
            compilationUnit.setTypeRoot(null);
            compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
            ast.setDefaultNodeFlag(0);
            ast.setOriginalModificationCount(ast.modificationCount());

            // pass it to requestor
            astRequestor.acceptAST(new String(source.getFileName()), compilationUnit);

            worked(1);

            // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
            this.requestedSources.put(fileName, null); // mark it as removed
          }

          // requested binding
          Object key = this.requestedKeys.get(fileName);
          if (key != null) {
            if (key instanceof BindingKeyResolver) {
              reportBinding(key, astRequestor, unit);
              worked(1);
            } else if (key instanceof ArrayList) {
              Iterator iterator = ((ArrayList) key).iterator();
              while (iterator.hasNext()) {
                reportBinding(iterator.next(), astRequestor, unit);
                worked(1);
              }
            }

            // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
            this.requestedKeys.put(fileName, null); // mark it as removed
          }
        } finally {
          // cleanup compilation unit result
          unit.cleanUp();
        }
        this.unitsToProcess[i] = null; // release reference to processed unit declaration
        this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
      }

      // remaining binding keys
      DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, true);
      Object[] keys = this.requestedKeys.valueTable;
      for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
        BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
        if (keyResolver == null) continue;
        Binding compilerBinding = keyResolver.getCompilerBinding();
        IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
        // pass it to requestor
        astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
        worked(1);
      }
    } catch (OperationCanceledException e) {
      throw e;
    } catch (AbortCompilation e) {
      this.handleInternalException(e, unit);
    } catch (Error e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } catch (RuntimeException e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } finally {
      // disconnect ourselves from ast requestor
      astRequestor.compilationUnitResolver = null;
    }
  }

  private void reportBinding(Object key, ASTRequestor astRequestor, WorkingCopyOwner owner, CompilationUnitDeclaration unit) {
    BindingKeyResolver keyResolver = (BindingKeyResolver) key;
    Binding compilerBinding = keyResolver.getCompilerBinding();
    if (compilerBinding != null) {
      DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, false, this.fromJavaProject);
      AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
      IBinding binding;
      if (annotationBinding != null) {
        binding = resolver.getAnnotationInstance(annotationBinding);
      } else {
        binding = resolver.getBinding(compilerBinding);
      }
      if (binding != null)
        astRequestor.acceptBinding(keyResolver.getKey(), binding);
    }
  }

  private void reportBinding(Object key, FileASTRequestor astRequestor, CompilationUnitDeclaration unit) {
    BindingKeyResolver keyResolver = (BindingKeyResolver) key;
    Binding compilerBinding = keyResolver.getCompilerBinding();
    if (compilerBinding != null) {
      DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, null, this.bindingTables, false, this.fromJavaProject);
      AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
      IBinding binding;
      if (annotationBinding != null) {
        binding = resolver.getAnnotationInstance(annotationBinding);
      } else {
        binding = resolver.getBinding(compilerBinding);
      }
      if (binding != null)
        astRequestor.acceptBinding(keyResolver.getKey(), binding);
    }
  }

  private CompilationUnitDeclaration resolve(
      CompilationUnitDeclaration unit,
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
      NodeSearcher nodeSearcher,
      boolean verifyMethods,
      boolean analyzeCode,
      boolean generateCode) {

    try {

      if (unit == null) {
        // build and record parsed units
        this.parseThreshold = 0; // will request a full parse
        beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
        // process all units (some more could be injected in the loop by the lookup environment)
        unit = this.unitsToProcess[0];
      } else {
        // initial type binding creation
        this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);

        // binding resolution
        this.lookupEnvironment.completeTypeBindings();
      }

      if (nodeSearcher == null) {
        this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
      } else {
        int searchPosition = nodeSearcher.position;
        char[] source = sourceUnit.getContents();
        int length = source.length;
        if (searchPosition >= 0 && searchPosition <= length) {
          unit.traverse(nodeSearcher, unit.scope);

          org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;

           if (node != null) {
            // save existing values to restore them at the end of the parsing process
            // see bug 47079 for more details
            int[] oldLineEnds = this.parser.scanner.lineEnds;
            int oldLinePtr = this.parser.scanner.linePtr;

            this.parser.scanner.setSource(source, unit.compilationResult);

            org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
            if (node instanceof AbstractMethodDeclaration) {
              ((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
            } else if (enclosingTypeDeclaration != null) {
              if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
                ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
              } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
                ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(this.parser, unit);
              }
            }
            // this is done to prevent any side effects on the compilation unit result
            // line separator positions array.
            this.parser.scanner.lineEnds = oldLineEnds;
            this.parser.scanner.linePtr = oldLinePtr;
          }
        }
      }

      if (unit.scope != null) {
        // fault in fields & methods
        unit.scope.faultInTypes();
        if (unit.scope != null && verifyMethods) {
          // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
           // verify inherited methods
          unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
        }
        // type checking
        unit.resolve();

        // flow analysis
        if (analyzeCode) unit.analyseCode();

        // code generation
        if (generateCode) unit.generateCode();

        // finalize problems (suppressWarnings)
        unit.finalizeProblems();
      }
      if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
      this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
      return unit;
    } catch (AbortCompilation e) {
      this.handleInternalException(e, unit);
      return unit == null ? this.unitsToProcess[0] : unit;
    } catch (Error e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } catch (RuntimeException e) {
      this.handleInternalException(e, unit, null);
      throw e; // rethrow
    } finally {
      // No reset is performed there anymore since,
      // within the CodeAssist (or related tools),
      // the compiler may be called *after* a call
      // to this resolve(...) method. And such a call
      // needs to have a compiler with a non-empty
      // environment.
      // this.reset();
    }
  }
  /*
   * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
   */
  public CompilationUnitDeclaration resolve(
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
      boolean verifyMethods,
      boolean analyzeCode,
      boolean generateCode) {

    return resolve(
      null, /* no existing compilation unit declaration*/
      sourceUnit,
      null/*no node searcher*/,
      verifyMethods,
      analyzeCode,
      generateCode);
  }

  boolean resolvedRequestedSourcesAndKeys(int unitIndexToProcess) {
    if (unitIndexToProcess < this.requestedSources.size() && unitIndexToProcess < this.requestedKeys.size())
      return false; // must process at least this many units before checking to see if all are done

    Object[] sources = this.requestedSources.valueTable;
    for (int i = 0, l = sources.length; i < l; i++)
      if (sources[i] != null) return false;
    Object[] keys = this.requestedKeys.valueTable;
    for (int i = 0, l = keys.length; i < l; i++)
      if (keys[i] != null) return false;
    return true;
  }

  /*
   * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
   */
  public CompilationUnitDeclaration resolve(
      CompilationUnitDeclaration unit,
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
      boolean verifyMethods,
      boolean analyzeCode,
      boolean generateCode) {

    return resolve(
      unit,
      sourceUnit,
      null/*no node searcher*/,
      verifyMethods,
      analyzeCode,
      generateCode);
  }

  private void worked(int work) {
    if (this.monitor != null) {
      if (this.monitor.isCanceled())
        throw new OperationCanceledException();
      this.monitor.worked(work);
    }
  }
}
TOP

Related Classes of org.eclipse.jdt.core.dom.Requestor

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.
clipse.jdt.internal.compiler.ICompilerRequestor
  • org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy
  • org.eclipse.jdt.internal.compiler.impl.CompilerOptions
  • org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding
  • org.eclipse.jdt.internal.compiler.lookup.Binding
  • org.eclipse.jdt.internal.compiler.parser.Parser
  • 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.