/*******************************************************************************
* Copyright (c) 2000, 2011 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.che.ide.ext.java.jdt.core.dom;
import org.eclipse.che.ide.ext.java.jdt.core.compiler.CategorizedProblem;
import org.eclipse.che.ide.ext.java.jdt.core.compiler.CharOperation;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.CompilationResult;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.Compiler;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.IProblemFactory;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ISourceType;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.Binding;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.parser.Parser;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.che.ide.ext.java.jdt.internal.core.CancelableProblemFactory;
import org.eclipse.che.ide.ext.java.jdt.internal.core.util.BindingKeyResolver;
import org.eclipse.che.ide.ext.java.jdt.internal.core.util.CommentRecorderParser;
import org.eclipse.che.ide.util.ExceptionUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public 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;
/**
* Constant indicating that a reconcile operation should enable the bindings recovery
*
* @see ASTParser#setBindingsRecovery(boolean)
* @see IBinding#isRecovered()
* @since 3.3
*/
public static final int ENABLE_BINDINGS_RECOVERY = 0x04;
/**
* Constant indicating that a reconcile operation should enable the statements recovery.
*
* @see ASTParser#setStatementsRecovery(boolean)
* @since 3.3
*/
public static final int ENABLE_STATEMENTS_RECOVERY = 0x02;
/*
* 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;
/** 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.
* @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.
* @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.
* @see org.eclipse.che.ide.ext.java.jdt.internal.compiler.DefaultErrorHandlingPolicies
* @see org.eclipse.che.ide.ext.java.jdt.internal.compiler.CompilationResult
*/
public CompilationUnitResolver(INameEnvironment environment, IErrorHandlingPolicy policy,
CompilerOptions compilerOptions, ICompilerRequestor requestor, IProblemFactory problemFactory,
boolean fromJavaProject) {
super(environment, policy, compilerOptions, requestor, problemFactory);
this.hasCompilationAborted = false;
this.fromJavaProject = fromJavaProject;
}
/* Add additional source types */
@Override
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))
// TODO
// SourceTypeElementInfo sourceType = (SourceTypeElementInfo)sourceTypes[0];
// accept((org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit)sourceType.getHandle().getCompilationUnit(),
// accessRestriction);
}
@Override
public synchronized void accept(org.eclipse.che.ide.ext.java.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.che.ide.ext.java.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.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
CompilationUnitDeclaration parsedUnit;
CompilationResult unitResult =
new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
try {
// 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);
} 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);
}
}
// 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, this.bindingTables, false, this.fromJavaProject);
return resolver.getBinding(compilerBinding);
}
public static CompilationUnit convert(CompilationUnitDeclaration compilationUnitDeclaration, char[] source,
int apiLevel, Map<String, String> options, boolean needToResolveBindings,
DefaultBindingResolver.BindingTables bindingTables, int flags, boolean fromJavaProject) {
BindingResolver resolver = null;
AST ast = AST.newAST(apiLevel);
ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
CompilationUnit compilationUnit = null;
ASTConverter converter = new ASTConverter(options, needToResolveBindings);
if (needToResolveBindings) {
resolver =
new DefaultBindingResolver(compilationUnitDeclaration.scope, bindingTables,
(flags & 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() {
@Override
public boolean stopOnFirstError() {
return false;
}
@Override
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() {
@Override
public void acceptResult(CompilationResult compilationResult) {
// do nothing
}
};
}
/*
* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
*/
@Override
public void initializeParser() {
this.parser = new CommentRecorderParser(this.problemReporter, false);
}
@Override
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 */
@Override
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 */
@Override
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 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<String, String> options, int flags)
// {
// CompilerOptions compilerOptions = new CompilerOptions(options);
// compilerOptions.ignoreMethodBodies = (flags & IGNORE_METHOD_BODIES) != 0;
// Parser parser =
// new CommentRecorderParser(new ProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(),
// compilerOptions, new DefaultProblemFactory()), false);
// int unitLength = sourceUnits.length;
// for (int i = 0; i < unitLength; i++)
// {
// char[] contents = null;
// String encoding = encodings != null ? encodings[i] : null;
// // try { TODO
// // 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.che.ide.ext.java.jdt.compiler.batch.CompilationUnit compilationUnit =
// new org.eclipse.che.ide.ext.java.jdt.compiler.batch.CompilationUnit(contents, sourceUnits[i], encoding);
// org.eclipse.che.ide.ext.java.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.che.ide.ext.java.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 binding
// * table needed
// */,
// flags /* flags */, true);
//
// // accept AST
// astRequestor.acceptAST(sourceUnits[i], node);
//
// }
// }
public static CompilationUnitDeclaration parse(
org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit sourceUnit, NodeSearcher nodeSearcher,
Map<String, String> settings, int flags) {
if (sourceUnit == null) {
throw new IllegalStateException();
}
CompilerOptions compilerOptions = new CompilerOptions(settings);
boolean statementsRecovery = (flags & ENABLE_STATEMENTS_RECOVERY) != 0;
compilerOptions.performMethodsFullRecovery = statementsRecovery;
compilerOptions.performStatementsRecovery = statementsRecovery;
compilerOptions.ignoreMethodBodies = (flags & 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.che.ide.ext.java.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
if (node == null) {
return compilationUnitDeclaration;
}
org.eclipse.che.ide.ext.java.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.che.ide.ext.java.jdt.internal.compiler.ast.Initializer) {
((org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Initializer)node).parseStatements(parser,
enclosingTypeDeclaration,
compilationUnitDeclaration);
} else if (node instanceof org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.TypeDeclaration) {
((org.eclipse.che.ide.ext.java.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.che.ide.ext.java.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, int flags, IProgressMonitor monitor)
// {
// TODO
// 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), 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<String, String> options, List classpaths, int flags) {
// TODO
// 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
// }
// }
}
// TODO
public static CompilationUnitDeclaration resolve(
org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit sourceUnit, List classpaths,
NodeSearcher nodeSearcher, Map options, int flags, INameEnvironment nameEnvironment) {
CompilationUnitDeclaration unit = null;
CancelableProblemFactory problemFactory = null;
CompilationUnitResolver resolver = null;
try {
problemFactory = new CancelableProblemFactory();
CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ENABLE_STATEMENTS_RECOVERY) != 0);
boolean ignoreMethodBodies = (flags & IGNORE_METHOD_BODIES) != 0;
compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
resolver =
new CompilationUnitResolver(nameEnvironment, getHandlingPolicy(), compilerOptions, getRequestor(),
problemFactory, false);
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;
} catch (Exception e) {
//TODO log error
throw new RuntimeException(e);
// Log.error(CompilationUnitDeclaration.class, e);
// return null;
}
}
// public static IBinding[] resolve(final IJavaElement[] elements, int apiLevel, Map compilerOptions,
// IJavaProject javaProject, int flags, IProgressMonitor monitor)
// {
//
// final int length = elements.length;
// final HashMap sourceElementPositions = new HashMap(); // a valueMap from ICompilationUnit to int[] (positions in elements)
// int cuNumber = 0;
// final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a valueMap from String (binding key) to
// int (position in elements)
// for (int i = 0; i < length; i++)
// {
// IJavaElement element = elements[i];
// //TODO
// // 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++)
// {
// //TODO
// // 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, 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.che.ide.ext.java.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.che.ide.ext.java.jdt.internal.compiler.ast.TypeDeclaration type) {
final org.eclipse.che.ide.ext.java.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.che.ide.ext.java.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, 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, 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, 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, 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 (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.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits =
new org.eclipse.che.ide.ext.java.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];
// TODO
// 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.che.ide.ext.java.jdt.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.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit source =
(org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit)this.requestedSources
.get(fileName);
if (source != null) {
// convert AST
CompilationResult compilationResult = unit.compilationResult;
org.eclipse.che.ide.ext.java.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
*/);
BindingResolver resolver =
new DefaultBindingResolver(unit.scope, this.bindingTables,
(flags & ENABLE_BINDINGS_RECOVERY) != 0, this.fromJavaProject);
ast.setBindingResolver(resolver);
converter.setAST(ast);
CompilationUnit compilationUnit = converter.convert(unit, contents);
compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
ast.setDefaultNodeFlag(0);
ast.setOriginalModificationCount(ast.modificationCount());
// pass it to requestor
astRequestor.acceptAST(new String(source.getFileName()), compilationUnit);
// 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);
} else if (key instanceof ArrayList) {
Iterator iterator = ((ArrayList)key).iterator();
while (iterator.hasNext()) {
reportBinding(iterator.next(), astRequestor, unit);
}
}
// 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, this.bindingTables,
(flags & ENABLE_BINDINGS_RECOVERY) != 0, true);
Object[] keys = this.requestedKeys.getArrayValues();
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.getArrayValues()[j]).getKey(), binding);
}
} 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, CompilationUnitDeclaration unit) {
BindingKeyResolver keyResolver = (BindingKeyResolver)key;
Binding compilerBinding = keyResolver.getCompilerBinding();
if (compilerBinding != null) {
DefaultBindingResolver resolver =
new DefaultBindingResolver(unit.scope, 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, 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.che.ide.ext.java.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.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit[]{sourceUnit});
// find the right unit from what was injected via accept(ICompilationUnit,..):
for (int i = 0, max = this.totalUnits; i < max; i++) {
CompilationUnitDeclaration currentCompilationUnitDeclaration = this.unitsToProcess[i];
if (currentCompilationUnitDeclaration != null
&& currentCompilationUnitDeclaration.compilationResult.compilationUnit == sourceUnit) {
unit = currentCompilationUnitDeclaration;
break;
}
}
if (unit == null) {
unit = this.unitsToProcess[0]; // fall back to old behavior
}
} 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.che.ide.ext.java.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.che.ide.ext.java.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.che.ide.ext.java.jdt.internal.compiler.ast.Initializer) {
((org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Initializer)node).parseStatements(
this.parser, enclosingTypeDeclaration, unit);
} else if (node instanceof org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.TypeDeclaration) {
((org.eclipse.che.ide.ext.java.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) {
String traceAsString = ExceptionUtils.getStackTraceAsString(e);
invokeBrowserLogger(traceAsString);
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();
}
}
private static native void invokeBrowserLogger(Object o) /*-{
if (console && console["error"]) {
console["error"](o);
}
return;
}-*/;
/*
* Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
*/
@Override
public CompilationUnitDeclaration resolve(
org.eclipse.che.ide.ext.java.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.getArrayValues();
for (int i = 0, l = sources.length; i < l; i++) {
if (sources[i] != null) {
return false;
}
}
Object[] keys = this.requestedKeys.getArrayValues();
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
*/
@Override
public CompilationUnitDeclaration resolve(CompilationUnitDeclaration unit,
org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
boolean verifyMethods,
boolean analyzeCode, boolean generateCode) {
return resolve(unit, sourceUnit, null/* no node searcher */, verifyMethods, analyzeCode, generateCode);
}
}