import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
import net.sourceforge.phpdt.internal.compiler.ICompilerRequestor;
import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemHandler;
import net.sourceforge.phpdt.internal.core.util.Util;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
/**
- * The abstract superclass of Java builders.
- * Provides the building and compilation mechanism
- * in common with the batch and incremental builders.
+ * The abstract superclass of Java builders. Provides the building and compilation mechanism in common with the batch and
+ * incremental builders.
*/
public abstract class AbstractImageBuilder implements ICompilerRequestor {
-protected PHPBuilder javaBuilder;
-protected State newState;
+ protected PHPBuilder javaBuilder;
-// local copies
-protected NameEnvironment nameEnvironment;
-protected ClasspathMultiDirectory[] sourceLocations;
-protected BuildNotifier notifier;
+ protected State newState;
-protected String encoding;
-protected Compiler compiler;
-protected WorkQueue workQueue;
-protected ArrayList problemSourceFiles;
-protected boolean compiledAllAtOnce;
+ // local copies
+ protected NameEnvironment nameEnvironment;
-private boolean inCompiler;
+ protected ClasspathMultiDirectory[] sourceLocations;
-public static int MAX_AT_ONCE = 1000;
+ protected BuildNotifier notifier;
-protected AbstractImageBuilder(PHPBuilder javaBuilder) {
- this.javaBuilder = javaBuilder;
- this.newState = new State(javaBuilder);
+ protected String encoding;
- // local copies
- this.nameEnvironment = javaBuilder.nameEnvironment;
- this.sourceLocations = this.nameEnvironment.sourceLocations;
- this.notifier = javaBuilder.notifier;
+ protected Compiler compiler;
- this.encoding = javaBuilder.javaProject.getOption(JavaCore.CORE_ENCODING, true);
- this.compiler = newCompiler();
- this.workQueue = new WorkQueue();
- this.problemSourceFiles = new ArrayList(3);
-}
+ protected WorkQueue workQueue;
-public void acceptResult(CompilationResult result) {
- // In Batch mode, we write out the class files, hold onto the dependency info
- // & additional types and report problems.
+ protected ArrayList problemSourceFiles;
- // In Incremental mode, when writing out a class file we need to compare it
- // against the previous file, remembering if structural changes occured.
- // Before reporting the new problems, we need to update the problem count &
- // remove the old problems. Plus delete additional class files that no longer exist.
+ protected boolean compiledAllAtOnce;
- SourceFile compilationUnit = (SourceFile) result.getCompilationUnit(); // go directly back to the sourceFile
- if (!workQueue.isCompiled(compilationUnit)) {
- try {
- workQueue.finished(compilationUnit);
+ private boolean inCompiler;
+
+ public static int MAX_AT_ONCE = 1000;
+
+ protected AbstractImageBuilder(PHPBuilder javaBuilder) {
+ this.javaBuilder = javaBuilder;
+ this.newState = new State(javaBuilder);
+
+ // local copies
+ this.nameEnvironment = javaBuilder.nameEnvironment;
+ this.sourceLocations = this.nameEnvironment.sourceLocations;
+ this.notifier = javaBuilder.notifier;
+
+ this.encoding = javaBuilder.javaProject.getOption(JavaCore.CORE_ENCODING, true);
+ this.compiler = newCompiler();
+ this.workQueue = new WorkQueue();
+ this.problemSourceFiles = new ArrayList(3);
+ }
+
+ public void acceptResult(CompilationResult result) {
+ // In Batch mode, we write out the class files, hold onto the dependency info
+ // & additional types and report problems.
+
+ // In Incremental mode, when writing out a class file we need to compare it
+ // against the previous file, remembering if structural changes occured.
+ // Before reporting the new problems, we need to update the problem count &
+ // remove the old problems. Plus delete additional class files that no longer exist.
+
+ SourceFile compilationUnit = (SourceFile) result.getCompilationUnit(); // go directly back to the sourceFile
+ if (!workQueue.isCompiled(compilationUnit)) {
+// try {
+ workQueue.finished(compilationUnit);
+ try {
updateProblemsFor(compilationUnit, result); // record compilation problems before potentially adding duplicate errors
- updateTasksFor(compilationUnit, result); // record tasks
-
- String typeLocator = compilationUnit.typeLocator();
-// ClassFile[] classFiles = result.getClassFiles();
-// int length = classFiles.length;
-// ArrayList duplicateTypeNames = null;
-// ArrayList definedTypeNames = new ArrayList(length);
-// for (int i = 0; i < length; i++) {
-// ClassFile classFile = classFiles[i];
-// char[][] compoundName = classFile.getCompoundName();
-// char[] typeName = compoundName[compoundName.length - 1];
-// boolean isNestedType = CharOperation.contains('$', typeName);
-//
-// // Look for a possible collision, if one exists, report an error but do not write the class file
-// if (isNestedType) {
-// String qualifiedTypeName = new String(classFile.outerMostEnclosingClassFile().fileName());
-// if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator))
-// continue;
-// } else {
-// String qualifiedTypeName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
-// if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator)) {
-// if (duplicateTypeNames == null)
-// duplicateTypeNames = new ArrayList();
-// duplicateTypeNames.add(compoundName);
-// createErrorFor(compilationUnit.resource, ProjectPrefUtil.bind("build.duplicateClassFile", new String(typeName))); //$NON-NLS-1$
-// continue;
-// }
-// newState.recordLocatorForType(qualifiedTypeName, typeLocator);
-// }
-// definedTypeNames.add(writeClassFile(classFile, compilationUnit.sourceLocation.binaryFolder, !isNestedType));
-// }
-
-// finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
- notifier.compiled(compilationUnit);
+ updateTasksFor(compilationUnit, result); // record tasks
} catch (CoreException e) {
- Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
- createErrorFor(compilationUnit.resource, Util.bind("build.inconsistentClassFile")); //$NON-NLS-1$
- }
- }
-}
-
-protected void cleanUp() {
- this.nameEnvironment.cleanup();
-
- this.javaBuilder = null;
- this.nameEnvironment = null;
- this.sourceLocations = null;
- this.notifier = null;
- this.compiler = null;
- this.workQueue = null;
- this.problemSourceFiles = null;
-}
-
-/* Compile the given elements, adding more elements to the work queue
-* if they are affected by the changes.
-*/
-protected void compile(SourceFile[] units) {
- int toDo = units.length;
- if (this.compiledAllAtOnce = toDo <= MAX_AT_ONCE) {
- // do them all now
- if (PHPBuilder.DEBUG)
- for (int i = 0; i < toDo; i++)
- System.out.println("About to compile " + units[i].typeLocator()); //$NON-NLS-1$
- compile(units, null);
- } else {
- int i = 0;
- boolean compilingFirstGroup = true;
- while (i < toDo) {
- int doNow = toDo < MAX_AT_ONCE ? toDo : MAX_AT_ONCE;
- int index = 0;
- SourceFile[] toCompile = new SourceFile[doNow];
- while (i < toDo && index < doNow) {
- // Although it needed compiling when this method was called, it may have
- // already been compiled when it was referenced by another unit.
- SourceFile unit = units[i++];
- if (compilingFirstGroup || workQueue.isWaiting(unit)) {
- if (PHPBuilder.DEBUG)
- System.out.println("About to compile " + unit.typeLocator()); //$NON-NLS-1$
- toCompile[index++] = unit;
- }
- }
- if (index < doNow)
- System.arraycopy(toCompile, 0, toCompile = new SourceFile[index], 0, index);
- SourceFile[] additionalUnits = new SourceFile[toDo - i];
- System.arraycopy(units, i, additionalUnits, 0, additionalUnits.length);
- compilingFirstGroup = false;
- compile(toCompile, additionalUnits);
- }
- }
-}
-
-void compile(SourceFile[] units, SourceFile[] additionalUnits) {
- if (units.length == 0) return;
- notifier.aboutToCompile(units[0]); // just to change the message
-
- // extend additionalFilenames with all hierarchical problem types found during this entire build
- if (!problemSourceFiles.isEmpty()) {
- int toAdd = problemSourceFiles.size();
- int length = additionalUnits == null ? 0 : additionalUnits.length;
- if (length == 0)
- additionalUnits = new SourceFile[toAdd];
- else
- System.arraycopy(additionalUnits, 0, additionalUnits = new SourceFile[length + toAdd], 0, length);
- for (int i = 0; i < toAdd; i++)
- additionalUnits[length + i] = (SourceFile) problemSourceFiles.get(i);
- }
- String[] initialTypeNames = new String[units.length];
- for (int i = 0, l = units.length; i < l; i++)
- initialTypeNames[i] = units[i].initialTypeName;
- nameEnvironment.setNames(initialTypeNames, additionalUnits);
- notifier.checkCancel();
- try {
- inCompiler = true;
- compiler.compile(units);
- } catch (AbortCompilation ignored) {
- // ignore the AbortCompilcation coming from BuildNotifier.checkCancelWithinCompiler()
- // the Compiler failed after the user has chose to cancel... likely due to an OutOfMemory error
- } finally {
- inCompiler = false;
- }
- // Check for cancel immediately after a compile, because the compiler may
- // have been cancelled but without propagating the correct exception
- notifier.checkCancel();
-}
-
-protected void createErrorFor(IResource resource, String message) {
- try {
- IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- int severity = IMarker.SEVERITY_ERROR;
- if (message.equals(Util.bind("build.duplicateResource"))) //$NON-NLS-1$
- if (JavaCore.WARNING.equals(javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true)))
- severity = IMarker.SEVERITY_WARNING;
- marker.setAttributes(
- new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END},
- new Object[] {message, new Integer(severity), new Integer(0), new Integer(1)});
- } catch (CoreException e) {
- throw internalException(e);
- }
-}
-
-//protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName) throws CoreException {//, ArrayList definedTypeNames, ArrayList duplicateTypeNames) throws CoreException {
-// if (duplicateTypeNames == null) {
-// newState.record(sourceLocator, result.qualifiedReferences, result.simpleNameReferences, mainTypeName, definedTypeNames);
-// return;
-// }
-//
-// char[][][] qualifiedRefs = result.qualifiedReferences;
-// char[][] simpleRefs = result.simpleNameReferences;
-// // for each duplicate type p1.p2.A, add the type name A (package was already added)
-// next : for (int i = 0, l = duplicateTypeNames.size(); i < l; i++) {
-// char[][] compoundName = (char[][]) duplicateTypeNames.get(i);
-// char[] typeName = compoundName[compoundName.length - 1];
-// int sLength = simpleRefs.length;
-// for (int j = 0; j < sLength; j++)
-// if (CharOperation.equals(simpleRefs[j], typeName))
-// continue next;
-// System.arraycopy(simpleRefs, 0, simpleRefs = new char[sLength + 1][], 0, sLength);
-// simpleRefs[sLength] = typeName;
-// }
-// newState.record(sourceLocator, qualifiedRefs, simpleRefs, mainTypeName, definedTypeNames);
-//}
-
-//protected IContainer createFolder(IPath packagePath, IContainer outputFolder) throws CoreException {
-// if (packagePath.isEmpty()) return outputFolder;
-// IFolder folder = outputFolder.getFolder(packagePath);
-// if (!folder.exists()) {
-// createFolder(packagePath.removeLastSegments(1), outputFolder);
-// folder.create(true, true, null);
-// folder.setDerived(true);
-// }
-// return folder;
-//}
-
-protected RuntimeException internalException(CoreException t) {
- ImageBuilderInternalException imageBuilderException = new ImageBuilderInternalException(t);
- if (inCompiler)
- return new AbortCompilation(true, imageBuilderException);
- return imageBuilderException;
-}
-
-protected Compiler newCompiler() {
- // called once when the builder is initialized... can override if needed
- return new Compiler(
- nameEnvironment,
- DefaultErrorHandlingPolicies.proceedWithAllProblems(),
- javaBuilder.javaProject.getOptions(true),
- this,
- ProblemFactory.getProblemFactory(Locale.getDefault()));
-}
-
-protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
- // answer whether the folder should be ignored when walking the project as a source folder
- if (childPath.segmentCount() > 2) return false; // is a subfolder of a package
-
- for (int j = 0, k = sourceLocations.length; j < k; j++) {
-// if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
- if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath())) return true;
- }
- // skip default output folder which may not be used by any source folder
- return false; //childPath.equals(javaBuilder.javaProject.getOutputLocation());
-}
-
-/**
- * Creates a marker from each problem and adds it to the resource.
- * The marker is as follows:
- * - its type is T_PROBLEM
- * - its plugin ID is the JavaBuilder's plugin ID
- * - its message is the problem's message
- * - its priority reflects the severity of the problem
- * - its range is the problem's range
- * - it has an extra attribute "ID" which holds the problem's id
- */
-protected void storeProblemsFor(SourceFile sourceFile, IProblem[] problems) throws CoreException {
- if (sourceFile == null || problems == null || problems.length == 0) return;
-
-// String missingClassFile = null;
- IResource resource = sourceFile.resource;
- for (int i = 0, l = problems.length; i < l; i++) {
- IProblem problem = problems[i];
- int id = problem.getID();
- switch (id) {
- case IProblem.IsClassPathCorrect :
-// PHPBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
-// String[] args = problem.getArguments();
-// missingClassFile = args[0];
- break;
- case IProblem.SuperclassMustBeAClass :
- case IProblem.SuperInterfaceMustBeAnInterface :
- case IProblem.HierarchyCircularitySelfReference :
- case IProblem.HierarchyCircularity :
- case IProblem.HierarchyHasProblems :
- case IProblem.SuperclassNotFound :
- case IProblem.SuperclassNotVisible :
- case IProblem.SuperclassAmbiguous :
- case IProblem.SuperclassInternalNameProvided :
- case IProblem.SuperclassInheritedNameHidesEnclosingName :
- case IProblem.InterfaceNotFound :
- case IProblem.InterfaceNotVisible :
- case IProblem.InterfaceAmbiguous :
- case IProblem.InterfaceInternalNameProvided :
- case IProblem.InterfaceInheritedNameHidesEnclosingName :
- // ensure that this file is always retrieved from source for the rest of the build
- if (!problemSourceFiles.contains(sourceFile))
- problemSourceFiles.add(sourceFile);
- break;
- }
-
- if (id != IProblem.Task) {
- IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttributes(
- new String[] {
- IMarker.MESSAGE,
- IMarker.SEVERITY,
- IJavaModelMarker.ID,
- IMarker.CHAR_START,
- IMarker.CHAR_END,
- IMarker.LINE_NUMBER,
- IJavaModelMarker.ARGUMENTS},
- new Object[] {
- problem.getMessage(),
- new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
- new Integer(id),
- new Integer(problem.getSourceStart()),
- new Integer(problem.getSourceEnd() + 1),
- new Integer(problem.getSourceLineNumber()),
- Util.getProblemArgumentsForMarker(problem.getArguments())
- });
- }
-
-/* Do NOT want to populate the Java Model just to find the matching Java element.
- * Also cannot query compilation units located in folders with invalid package
- * names such as 'a/b.c.d/e'.
-
- // compute a user-friendly location
- IJavaElement element = JavaCore.create(resource);
- if (element instanceof net.sourceforge.phpdt.core.ICompilationUnit) { // try to find a finer grain element
- net.sourceforge.phpdt.core.ICompilationUnit unit = (net.sourceforge.phpdt.core.ICompilationUnit) element;
- IJavaElement fragment = unit.getElementAt(problem.getSourceStart());
- if (fragment != null) element = fragment;
- }
- String location = null;
- if (element instanceof JavaElement)
- location = ((JavaElement) element).readableName();
- if (location != null)
- marker.setAttribute(IMarker.LOCATION, location);
-*/
-
-// if (missingClassFile != null)
-// throw new MissingClassFileException(missingClassFile);
- }
-}
-
-protected void storeTasksFor(SourceFile sourceFile, IProblem[] tasks) throws CoreException {
- if (sourceFile == null || tasks == null || tasks.length == 0) return;
-
- IResource resource = sourceFile.resource;
- for (int i = 0, l = tasks.length; i < l; i++) {
- IProblem task = tasks[i];
- if (task.getID() == IProblem.Task) {
- IMarker marker = resource.createMarker(IJavaModelMarker.TASK_MARKER);
- int priority = IMarker.PRIORITY_NORMAL;
- String compilerPriority = task.getArguments()[2];
- if (JavaCore.COMPILER_TASK_PRIORITY_HIGH.equals(compilerPriority))
- priority = IMarker.PRIORITY_HIGH;
- else if (JavaCore.COMPILER_TASK_PRIORITY_LOW.equals(compilerPriority))
- priority = IMarker.PRIORITY_LOW;
- marker.setAttributes(
- new String[] {
- IMarker.MESSAGE,
- IMarker.PRIORITY,
- IMarker.DONE,
- IMarker.CHAR_START,
- IMarker.CHAR_END,
- IMarker.LINE_NUMBER,
- IMarker.USER_EDITABLE,
- },
- new Object[] {
- task.getMessage(),
- new Integer(priority),
- new Boolean(false),
- new Integer(task.getSourceStart()),
- new Integer(task.getSourceEnd() + 1),
- new Integer(task.getSourceLineNumber()),
- new Boolean(false),
- });
- }
- }
-}
-
-protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
- IProblem[] problems = result.getProblems();
- if (problems == null || problems.length == 0) return;
-
- notifier.updateProblemCounts(problems);
- storeProblemsFor(sourceFile, problems);
-}
-
-protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
- IProblem[] tasks = result.getTasks();
- if (tasks == null || tasks.length == 0) return;
-
- storeTasksFor(sourceFile, tasks);
-}
-
-//protected char[] writeClassFile(ClassFile classFile, IContainer outputFolder, boolean isSecondaryType) throws CoreException {
-// String fileName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
-// IPath filePath = new Path(fileName);
-// IContainer container = outputFolder;
-// if (filePath.segmentCount() > 1) {
-// container = createFolder(filePath.removeLastSegments(1), outputFolder);
-// filePath = new Path(filePath.lastSegment());
-// }
-//
-// IFile file = container.getFile(filePath.addFileExtension(JavaBuilder.CLASS_EXTENSION));
-// writeClassFileBytes(classFile.getBytes(), file, fileName, isSecondaryType);
-// // answer the name of the class file as in Y or Y$M
-// return filePath.lastSegment().toCharArray();
-//}
-//
-//protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType) throws CoreException {
-// if (file.exists()) {
-// // Deal with shared output folders... last one wins... no collision cases detected
-// if (JavaBuilder.DEBUG)
-// System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$
-// file.setContents(new ByteArrayInputStream(bytes), true, false, null);
-// if (!file.isDerived())
-// file.setDerived(true);
-// } else {
-// // Default implementation just writes out the bytes for the new class file...
-// if (JavaBuilder.DEBUG)
-// System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
-// file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
-// file.setDerived(true);
-// }
-//}
-}
+ throw internalException(e);
+ }
+
+ // String typeLocator = compilationUnit.typeLocator();
+ // ClassFile[] classFiles = result.getClassFiles();
+ // int length = classFiles.length;
+ // ArrayList duplicateTypeNames = null;
+ // ArrayList definedTypeNames = new ArrayList(length);
+ // for (int i = 0; i < length; i++) {
+ // ClassFile classFile = classFiles[i];
+ // char[][] compoundName = classFile.getCompoundName();
+ // char[] typeName = compoundName[compoundName.length - 1];
+ // boolean isNestedType = CharOperation.contains('$', typeName);
+ //
+ // // Look for a possible collision, if one exists, report an error but do not write the class file
+ // if (isNestedType) {
+ // String qualifiedTypeName = new String(classFile.outerMostEnclosingClassFile().fileName());
+ // if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator))
+ // continue;
+ // } else {
+ // String qualifiedTypeName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
+ // if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator)) {
+ // if (duplicateTypeNames == null)
+ // duplicateTypeNames = new ArrayList();
+ // duplicateTypeNames.add(compoundName);
+ // createErrorFor(compilationUnit.resource, ProjectPrefUtil.bind("build.duplicateClassFile", new String(typeName)));
+ // //$NON-NLS-1$
+ // continue;
+ // }
+ // newState.recordLocatorForType(qualifiedTypeName, typeLocator);
+ // }
+ // definedTypeNames.add(writeClassFile(classFile, compilationUnit.sourceLocation.binaryFolder, !isNestedType));
+ // }
+
+ // finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
+ notifier.compiled(compilationUnit);
+// } catch (CoreException e) {
+// Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
+// createErrorFor(compilationUnit.resource, Util.bind("build.inconsistentClassFile")); //$NON-NLS-1$
+// }
+ }
+ }
+
+ protected void cleanUp() {
+ this.nameEnvironment.cleanup();
+
+ this.javaBuilder = null;
+ this.nameEnvironment = null;
+ this.sourceLocations = null;
+ this.notifier = null;
+ this.compiler = null;
+ this.workQueue = null;
+ this.problemSourceFiles = null;
+ }
+
+ /*
+ * Compile the given elements, adding more elements to the work queue if they are affected by the changes.
+ */
+ protected void compile(SourceFile[] units) {
+ int toDo = units.length;
+ if (this.compiledAllAtOnce = toDo <= MAX_AT_ONCE) {
+ // do them all now
+ if (PHPBuilder.DEBUG)
+ for (int i = 0; i < toDo; i++)
+ System.out.println("About to compile " + units[i].typeLocator()); //$NON-NLS-1$
+ compile(units, null);
+ } else {
+ int i = 0;
+ boolean compilingFirstGroup = true;
+ while (i < toDo) {
+ int doNow = toDo < MAX_AT_ONCE ? toDo : MAX_AT_ONCE;
+ int index = 0;
+ SourceFile[] toCompile = new SourceFile[doNow];
+ while (i < toDo && index < doNow) {
+ // Although it needed compiling when this method was called, it may have
+ // already been compiled when it was referenced by another unit.
+ SourceFile unit = units[i++];
+ if (compilingFirstGroup || workQueue.isWaiting(unit)) {
+ if (PHPBuilder.DEBUG)
+ System.out.println("About to compile " + unit.typeLocator()); //$NON-NLS-1$
+ toCompile[index++] = unit;
+ }
+ }
+ if (index < doNow)
+ System.arraycopy(toCompile, 0, toCompile = new SourceFile[index], 0, index);
+ SourceFile[] additionalUnits = new SourceFile[toDo - i];
+ System.arraycopy(units, i, additionalUnits, 0, additionalUnits.length);
+ compilingFirstGroup = false;
+ compile(toCompile, additionalUnits);
+ }
+ }
+ }
+
+ void compile(SourceFile[] units, SourceFile[] additionalUnits) {
+ if (units.length == 0)
+ return;
+ notifier.aboutToCompile(units[0]); // just to change the message
+
+ // extend additionalFilenames with all hierarchical problem types found during this entire build
+ if (!problemSourceFiles.isEmpty()) {
+ int toAdd = problemSourceFiles.size();
+ int length = additionalUnits == null ? 0 : additionalUnits.length;
+ if (length == 0)
+ additionalUnits = new SourceFile[toAdd];
+ else
+ System.arraycopy(additionalUnits, 0, additionalUnits = new SourceFile[length + toAdd], 0, length);
+ for (int i = 0; i < toAdd; i++)
+ additionalUnits[length + i] = (SourceFile) problemSourceFiles.get(i);
+ }
+ String[] initialTypeNames = new String[units.length];
+ for (int i = 0, l = units.length; i < l; i++)
+ initialTypeNames[i] = units[i].initialTypeName;
+ nameEnvironment.setNames(initialTypeNames, additionalUnits);
+ notifier.checkCancel();
+ try {
+ inCompiler = true;
+ compiler.compile(units);
+ } catch (AbortCompilation ignored) {
+ // ignore the AbortCompilcation coming from BuildNotifier.checkCancelWithinCompiler()
+ // the Compiler failed after the user has chose to cancel... likely due to an OutOfMemory error
+ } finally {
+ inCompiler = false;
+ }
+ // Check for cancel immediately after a compile, because the compiler may
+ // have been cancelled but without propagating the correct exception
+ notifier.checkCancel();
+ }
+
+ protected void createErrorFor(IResource resource, String message) {
+ try {
+ IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
+ int severity = IMarker.SEVERITY_ERROR;
+ if (message.equals(Util.bind("build.duplicateResource"))) //$NON-NLS-1$
+ if (JavaCore.WARNING.equals(javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true)))
+ severity = IMarker.SEVERITY_WARNING;
+ marker.setAttributes(new String[] { IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END }, new Object[] {
+ message,
+ new Integer(severity),
+ new Integer(0),
+ new Integer(1) });
+ } catch (CoreException e) {
+ throw internalException(e);
+ }
+ }
+
+ //protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName) throws CoreException {//,
+ // ArrayList definedTypeNames, ArrayList duplicateTypeNames) throws CoreException {
+ // if (duplicateTypeNames == null) {
+ // newState.record(sourceLocator, result.qualifiedReferences, result.simpleNameReferences, mainTypeName, definedTypeNames);
+ // return;
+ // }
+ //
+ // char[][][] qualifiedRefs = result.qualifiedReferences;
+ // char[][] simpleRefs = result.simpleNameReferences;
+ // // for each duplicate type p1.p2.A, add the type name A (package was already added)
+ // next : for (int i = 0, l = duplicateTypeNames.size(); i < l; i++) {
+ // char[][] compoundName = (char[][]) duplicateTypeNames.get(i);
+ // char[] typeName = compoundName[compoundName.length - 1];
+ // int sLength = simpleRefs.length;
+ // for (int j = 0; j < sLength; j++)
+ // if (CharOperation.equals(simpleRefs[j], typeName))
+ // continue next;
+ // System.arraycopy(simpleRefs, 0, simpleRefs = new char[sLength + 1][], 0, sLength);
+ // simpleRefs[sLength] = typeName;
+ // }
+ // newState.record(sourceLocator, qualifiedRefs, simpleRefs, mainTypeName, definedTypeNames);
+ //}
+
+ //protected IContainer createFolder(IPath packagePath, IContainer outputFolder) throws CoreException {
+ // if (packagePath.isEmpty()) return outputFolder;
+ // IFolder folder = outputFolder.getFolder(packagePath);
+ // if (!folder.exists()) {
+ // createFolder(packagePath.removeLastSegments(1), outputFolder);
+ // folder.create(true, true, null);
+ // folder.setDerived(true);
+ // }
+ // return folder;
+ //}
+
+ protected RuntimeException internalException(CoreException t) {
+ ImageBuilderInternalException imageBuilderException = new ImageBuilderInternalException(t);
+ if (inCompiler)
+ return new AbortCompilation(true, imageBuilderException);
+ return imageBuilderException;
+ }
+
+ protected Compiler newCompiler() {
+ // called once when the builder is initialized... can override if needed
+ return new Compiler(nameEnvironment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), javaBuilder.javaProject
+ .getOptions(true), this, ProblemFactory.getProblemFactory(Locale.getDefault()));
+ }
+
+ protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
+ // answer whether the folder should be ignored when walking the project as a source folder
+ if (childPath.segmentCount() > 2)
+ return false; // is a subfolder of a package
+
+ for (int j = 0, k = sourceLocations.length; j < k; j++) {
+ // if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
+ if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath()))
+ return true;
+ }
+ // skip default output folder which may not be used by any source folder
+ return false; //childPath.equals(javaBuilder.javaProject.getOutputLocation());
+ }
+
+ /**
+ * Creates a marker from each problem and adds it to the resource. The marker is as follows: - its type is T_PROBLEM - its plugin
+ * ID is the JavaBuilder's plugin ID - its message is the problem's message - its priority reflects the severity of the problem -
+ * its range is the problem's range - it has an extra attribute "ID" which holds the problem's id
+ */
+ protected void storeProblemsFor(SourceFile sourceFile, IProblem[] problems) throws CoreException {
+ if (sourceFile == null || problems == null || problems.length == 0)
+ return;
+
+ // String missingClassFile = null;
+ IResource resource = sourceFile.resource;
+ for (int i = 0, l = problems.length; i < l; i++) {
+ IProblem problem = problems[i];
+ int id = problem.getID();
+ switch (id) {
+ case IProblem.IsClassPathCorrect:
+ // PHPBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
+ // String[] args = problem.getArguments();
+ // missingClassFile = args[0];
+ break;
+ case IProblem.SuperclassMustBeAClass:
+ case IProblem.SuperInterfaceMustBeAnInterface:
+ case IProblem.HierarchyCircularitySelfReference:
+ case IProblem.HierarchyCircularity:
+ case IProblem.HierarchyHasProblems:
+ case IProblem.SuperclassNotFound:
+ case IProblem.SuperclassNotVisible:
+ case IProblem.SuperclassAmbiguous:
+ case IProblem.SuperclassInternalNameProvided:
+ case IProblem.SuperclassInheritedNameHidesEnclosingName:
+ case IProblem.InterfaceNotFound:
+ case IProblem.InterfaceNotVisible:
+ case IProblem.InterfaceAmbiguous:
+ case IProblem.InterfaceInternalNameProvided:
+ case IProblem.InterfaceInheritedNameHidesEnclosingName:
+ // ensure that this file is always retrieved from source for the rest of the build
+ if (!problemSourceFiles.contains(sourceFile))
+ problemSourceFiles.add(sourceFile);
+ break;
+ }
+
+ if (id != IProblem.Task) {
+ IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
+ marker.setAttributes(new String[] {
+ IMarker.MESSAGE,
+ IMarker.SEVERITY,
+ IJavaModelMarker.ID,
+ IMarker.CHAR_START,
+ IMarker.CHAR_END,
+ IMarker.LINE_NUMBER,
+ IJavaModelMarker.ARGUMENTS }, new Object[] {
+ problem.getMessage(),
+ new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
+ new Integer(id),
+ new Integer(problem.getSourceStart()),
+ new Integer(problem.getSourceEnd() + 1),
+ new Integer(problem.getSourceLineNumber()),
+ Util.getProblemArgumentsForMarker(problem.getArguments()) });
+ }
+
+ /*
+ * Do NOT want to populate the Java Model just to find the matching Java element. Also cannot query compilation units located
+ * in folders with invalid package names such as 'a/b.c.d/e'.
+ * // compute a user-friendly location IJavaElement element = JavaCore.create(resource); if (element instanceof
+ * net.sourceforge.phpdt.core.ICompilationUnit) { // try to find a finer grain element
+ * net.sourceforge.phpdt.core.ICompilationUnit unit = (net.sourceforge.phpdt.core.ICompilationUnit) element; IJavaElement
+ * fragment = unit.getElementAt(problem.getSourceStart()); if (fragment != null) element = fragment; } String location = null;
+ * if (element instanceof JavaElement) location = ((JavaElement) element).readableName(); if (location != null)
+ * marker.setAttribute(IMarker.LOCATION, location);
+ */
+
+ // if (missingClassFile != null)
+ // throw new MissingClassFileException(missingClassFile);
+ }
+ }
+
+ protected void storeTasksFor(SourceFile sourceFile, IProblem[] tasks) throws CoreException {
+ if (sourceFile == null || tasks == null || tasks.length == 0)
+ return;
+
+ IResource resource = sourceFile.resource;
+ for (int i = 0, l = tasks.length; i < l; i++) {
+ IProblem task = tasks[i];
+ if (task.getID() == IProblem.Task) {
+ IMarker marker = resource.createMarker(IJavaModelMarker.TASK_MARKER);
+ int priority = IMarker.PRIORITY_NORMAL;
+ String compilerPriority = task.getArguments()[2];
+ if (JavaCore.COMPILER_TASK_PRIORITY_HIGH.equals(compilerPriority))
+ priority = IMarker.PRIORITY_HIGH;
+ else if (JavaCore.COMPILER_TASK_PRIORITY_LOW.equals(compilerPriority))
+ priority = IMarker.PRIORITY_LOW;
+ marker.setAttributes(new String[] {
+ IMarker.MESSAGE,
+ IMarker.PRIORITY,
+ IMarker.DONE,
+ IMarker.CHAR_START,
+ IMarker.CHAR_END,
+ IMarker.LINE_NUMBER,
+ IMarker.USER_EDITABLE, }, new Object[] {
+ task.getMessage(),
+ new Integer(priority),
+ new Boolean(false),
+ new Integer(task.getSourceStart()),
+ new Integer(task.getSourceEnd() + 1),
+ new Integer(task.getSourceLineNumber()),
+ new Boolean(false), });
+ }
+ }
+ }
+
+ protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
+ IProblem[] problems = result.getProblems();
+ if (problems == null || problems.length == 0)
+ return;
+ //axelcl start insert - calculate line numbers
+ for (int i = 0; i < problems.length; i++) {
+ if (problems[i].getSourceLineNumber() == 1) {
+ problems[i].setSourceLineNumber(ProblemHandler
+ .searchLineNumber(result.lineSeparatorPositions, problems[i].getSourceStart()));
+ }
+ }
+ //axelcl end insert
+ notifier.updateProblemCounts(problems);
+ storeProblemsFor(sourceFile, problems);
+ }
+
+ protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
+ IProblem[] tasks = result.getTasks();
+ if (tasks == null || tasks.length == 0)
+ return;
+
+ storeTasksFor(sourceFile, tasks);
+ }
+
+ //protected char[] writeClassFile(ClassFile classFile, IContainer outputFolder, boolean isSecondaryType) throws CoreException {
+ // String fileName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
+ // IPath filePath = new Path(fileName);
+ // IContainer container = outputFolder;
+ // if (filePath.segmentCount() > 1) {
+ // container = createFolder(filePath.removeLastSegments(1), outputFolder);
+ // filePath = new Path(filePath.lastSegment());
+ // }
+ //
+ // IFile file = container.getFile(filePath.addFileExtension(JavaBuilder.CLASS_EXTENSION));
+ // writeClassFileBytes(classFile.getBytes(), file, fileName, isSecondaryType);
+ // // answer the name of the class file as in Y or Y$M
+ // return filePath.lastSegment().toCharArray();
+ //}
+ //
+ //protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType) throws
+ // CoreException {
+ // if (file.exists()) {
+ // // Deal with shared output folders... last one wins... no collision cases detected
+ // if (JavaBuilder.DEBUG)
+ // System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$
+ // file.setContents(new ByteArrayInputStream(bytes), true, false, null);
+ // if (!file.isDerived())
+ // file.setDerived(true);
+ // } else {
+ // // Default implementation just writes out the bytes for the new class file...
+ // if (JavaBuilder.DEBUG)
+ // System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
+ // file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
+ // file.setDerived(true);
+ // }
+ //}
+}
\ No newline at end of file