package org.eclipse.jdt.internal.core.builder.impl; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import org.eclipse.jdt.internal.compiler.*; | |
import org.eclipse.jdt.internal.compiler.Compiler; | |
import org.eclipse.jdt.internal.compiler.impl.*; | |
import org.eclipse.jdt.internal.core.builder.*; | |
import java.util.*; | |
/** | |
* The abstract superclass of image builders. | |
* Provides the building and compilation mechanism | |
* in common with the batch and incremental builders. | |
*/ | |
public abstract class AbstractImageBuilder implements IImageBuilder, ICompilerRequestor { | |
protected JavaDevelopmentContextImpl fDC; | |
protected StateImpl fOldState; | |
protected StateImpl fNewState; | |
protected WorkQueue fWorkQueue; | |
protected BuilderEnvironment fBuilderEnvironment; | |
protected BuildNotifier fNotifier; | |
protected org.eclipse.jdt.internal.compiler.Compiler fCompiler; | |
protected Map fCompilerOptions; | |
protected Vector fCompilationResults; | |
public int MAX_AT_ONCE = 1000; | |
/** | |
* Creates a new builder. | |
*/ | |
protected AbstractImageBuilder() { | |
} | |
public void acceptResult(CompilationResult result) { | |
ConvertedCompilationResult convertedResult = fNewState.convertCompilationResult(result, getBuilderEnvironment().getDefaultPackage()); | |
PackageElement element = convertedResult.getPackageElement(); | |
if (!fWorkQueue.hasBeenCompiled(element)) { | |
fCompilationResults.addElement(convertedResult); | |
fNotifier.compiled((CompilerCompilationUnit) result.getCompilationUnit()); | |
fWorkQueue.compiled(element); | |
} | |
} | |
/** | |
* Check whether the build has been canceled. | |
*/ | |
protected void checkCancel() { | |
fNotifier.checkCancel(); | |
} | |
/** | |
* Since the image builder is given as a result, let go of | |
* any unneeded structures. | |
*/ | |
protected void cleanUp() { | |
fCompiler = null; | |
fCompilationResults = null; | |
fWorkQueue = null; | |
fBuilderEnvironment = null; | |
fNotifier = null; | |
fNewState.cleanUp(); | |
} | |
/** | |
* Compile the given elements, adding more elements to the work queue | |
* if they are affected by the changes. | |
*/ | |
protected void compile(Vector vToCompile) { | |
int i = 0; | |
Vector vToCompileAtOnce = new Vector(Math.min(vToCompile.size(), MAX_AT_ONCE)); | |
while (i < vToCompile.size()) { | |
vToCompileAtOnce.removeAllElements(); | |
while (i < vToCompile.size() && vToCompileAtOnce.size() < MAX_AT_ONCE) { | |
PackageElement unit = (PackageElement) vToCompile.elementAt(i); | |
// Although it needed compiling when this method was called, | |
// it may have already been compiled due to being brought in | |
// by another unit. | |
if (fWorkQueue.needsCompile(unit)) { | |
SourceEntry sEntry = fNewState.getSourceEntry(unit); | |
CompilerCompilationUnit compUnit = new CompilerCompilationUnit(fNewState, sEntry, fNotifier); | |
compiling(compUnit); | |
vToCompileAtOnce.addElement(compUnit); | |
checkCancel(); | |
} | |
++i; | |
} | |
if (vToCompileAtOnce.size() > 0) { | |
CompilerCompilationUnit[] toCompile = new CompilerCompilationUnit[vToCompileAtOnce.size()]; | |
vToCompileAtOnce.copyInto(toCompile); | |
try { | |
fDC.inCompiler = true; | |
getCompiler().compile(toCompile); | |
} finally { | |
fDC.inCompiler = false; | |
} | |
/* Check for cancel immediately after a compile, because the compile may have been | |
* canceled but without propagating the build canceled exception. */ | |
checkCancel(); | |
/* store results in new state and get new units to compile */ | |
ConvertedCompilationResult[] results = getCompilationResults(); | |
updateState(results); | |
checkCancel(); | |
} | |
} | |
} | |
/** | |
* A unit is being (re)compiled. Save any previous type structure. | |
*/ | |
protected void compiling(CompilerCompilationUnit unit) { | |
} | |
/** | |
* Returns the builder environment to use for this builder. | |
*/ | |
public BuilderEnvironment getBuilderEnvironment() { | |
if (fBuilderEnvironment == null) { | |
fBuilderEnvironment = new BuilderEnvironment(this); | |
fBuilderEnvironment.setDefaultPackage(fNewState.defaultPackageForProject()); | |
} | |
return fBuilderEnvironment; | |
} | |
/** | |
* Returns the results of the last compile. | |
*/ | |
protected ConvertedCompilationResult[] getCompilationResults() { | |
ConvertedCompilationResult[] results = new ConvertedCompilationResult[fCompilationResults.size()]; | |
fCompilationResults.copyInto(results); | |
fCompilationResults = null; | |
return results; | |
} | |
/** | |
* Returns the compiler to use. | |
*/ | |
protected Compiler getCompiler() { | |
// Make sure to clear the results before starting a new compile. | |
fCompilationResults = new Vector(); | |
if (fCompiler == null) { | |
IErrorHandlingPolicy errorPolicy = DefaultErrorHandlingPolicies.proceedWithAllProblems(); | |
IProblemFactory problemFactory = ProblemFactory.getProblemFactory(Locale.getDefault()); | |
fCompiler = new Compiler(getBuilderEnvironment(), errorPolicy, fCompilerOptions, this, problemFactory); | |
} | |
return fCompiler; | |
} | |
/** | |
* Returns the state that is being built. | |
*/ | |
public IState getNewState() { | |
return fNewState; | |
} | |
/** | |
* Returns the old state if the image is being built incrementally | |
*/ | |
public IState getOldState() { | |
return fOldState; | |
} | |
/** | |
* Returns true if the given source entry must be recompiled, false otherwise. | |
*/ | |
protected boolean isInvalid(SourceEntry sEntry) { | |
return fWorkQueue.needsCompile(fNewState.packageElementFromSourceEntry(sEntry)); | |
} | |
/** | |
* Stores the results of a compilation in the appropriate state tables. | |
* Keeps track of what compilation units need to be compiled as a result | |
* of the changes. | |
*/ | |
protected void updateState(ConvertedCompilationResult[] results) { | |
// Must store all compilation results, so state has sufficient information | |
// to calculate changes. | |
fNewState.putCompilationResults(results); | |
// Notify listeners | |
fNotifier.notifyElementsChanged(results, fOldState, fNewState); | |
} | |
} |