1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.builder;
12 import java.util.ArrayList;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.core.compiler.IProblem;
15 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
16 import net.sourceforge.phpdt.internal.core.Util;
17 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
18 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
19 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
21 import org.eclipse.core.resources.IContainer;
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.resources.IFolder;
24 import org.eclipse.core.resources.IMarker;
25 import org.eclipse.core.resources.IResource;
26 import org.eclipse.core.resources.IResourceDelta;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
30 * The incremental image builder
32 public class IncrementalImageBuilder extends AbstractImageBuilder {
33 protected ArrayList sourceFiles;
34 protected ArrayList previousSourceFiles;
35 protected ArrayList qualifiedStrings;
36 protected ArrayList simpleStrings;
37 protected SimpleLookupTable secondaryTypesToRemove;
38 protected boolean hasStructuralChanges;
39 protected int compileLoop;
40 public static int MaxCompileLoop = 5; // perform a full build if it takes
41 // more than ? incremental compile
43 protected IncrementalImageBuilder(PHPBuilder javaBuilder) {
45 this.nameEnvironment.isIncrementalBuild = true;
46 this.newState.copyFrom(javaBuilder.lastState);
47 this.sourceFiles = new ArrayList(33);
48 this.previousSourceFiles = null;
49 this.qualifiedStrings = new ArrayList(33);
50 this.simpleStrings = new ArrayList(33);
51 this.hasStructuralChanges = false;
54 public boolean build(SimpleLookupTable deltas) {
56 // walk this project's deltas, find changed source files
57 // walk prereq projects' deltas, find changed class files & add affected
59 // use the build state # to skip the deltas for certain prereq projects
60 // ignore changed zip/jar files since they caused a full build
61 // compile the source files & acceptResult()
62 // compare the produced class files against the existing ones on disk
63 // recompile all dependent source files of any type with structural changes
64 // or new/removed secondary type
65 // keep a loop counter to abort & perform a full build
67 System.out.println("INCREMENTAL build"); //$NON-NLS-1$
70 notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$
71 IResourceDelta sourceDelta = (IResourceDelta) deltas
72 .get(javaBuilder.currentProject);
73 if (sourceDelta != null)
74 if (!findSourceFiles(sourceDelta))
76 notifier.updateProgressDelta(0.10f);
77 Object[] keyTable = deltas.keyTable;
78 Object[] valueTable = deltas.valueTable;
79 final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault()
80 .getIndexManager(javaBuilder.currentProject);
81 for (int i = 0, l = valueTable.length; i < l; i++) {
82 IResourceDelta delta = (IResourceDelta) valueTable[i];
84 IResource resource = delta.getResource();
85 int resourceType = resource.getType();
86 if (resourceType == IResource.FILE) {
87 switch (delta.getKind()) {
88 case IResourceDelta.ADDED :
89 if ((resource.getFileExtension() != null)
90 && PHPFileUtil.isPHPFile((IFile) resource)) {
91 // update indexfile for the project:
92 indexManager.addFile((IFile) resource);
95 case IResourceDelta.CHANGED :
96 if ((resource.getFileExtension() != null)
97 && PHPFileUtil.isPHPFile((IFile) resource)) {
98 // update indexfile for the project:
99 indexManager.changeFile((IFile) resource);
102 case IResourceDelta.REMOVED :
103 if ((resource.getFileExtension() != null)
104 && PHPFileUtil.isPHPFile((IFile) resource)) {
105 // update indexfile for the project:
106 indexManager.removeFile((IFile) resource);
111 // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[])
112 // javaBuilder.binaryLocationsPerProject.get(keyTable[i]);
113 // if (classFoldersAndJars != null)
114 // if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return
118 notifier.updateProgressDelta(0.10f);
119 notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
120 addAffectedSourceFiles();
121 notifier.updateProgressDelta(0.05f);
122 this.compileLoop = 0;
123 float increment = 0.40f;
124 while (sourceFiles.size() > 0) { // added to in acceptResult
125 if (++this.compileLoop > MaxCompileLoop) {
126 if (PHPBuilder.DEBUG)
128 .println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$
131 notifier.checkCancel();
132 SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()];
133 sourceFiles.toArray(allSourceFiles);
135 workQueue.addAll(allSourceFiles);
136 notifier.setProgressPerCompilationUnit(increment
137 / allSourceFiles.length);
138 increment = increment / 2;
139 compile(allSourceFiles);
140 removeSecondaryTypes();
141 addAffectedSourceFiles();
143 if (this.hasStructuralChanges && javaBuilder.javaProject.hasCycleMarker())
144 javaBuilder.mustPropagateStructuralChanges();
145 } catch (AbortIncrementalBuildException e) {
146 // abort the incremental build and let the batch builder handle the
148 if (PHPBuilder.DEBUG)
149 System.out.println("ABORTING incremental build... cannot find "
150 + e.qualifiedTypeName + //$NON-NLS-1$
151 ". Could have been renamed inside its existing source file."); //$NON-NLS-1$
153 } catch (CoreException e) {
154 throw internalException(e);
160 protected void addAffectedSourceFiles() {
161 if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())
163 // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
165 char[][][] qualifiedNames = ReferenceCollection
166 .internQualifiedNames(qualifiedStrings);
167 // if a well known qualified name was found then we can skip over these
168 if (qualifiedNames.length < qualifiedStrings.size())
169 qualifiedNames = null;
170 char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
171 // if a well known name was found then we can skip over these
172 if (simpleNames.length < simpleStrings.size())
174 Object[] keyTable = newState.references.keyTable;
175 Object[] valueTable = newState.references.valueTable;
176 next : for (int i = 0, l = valueTable.length; i < l; i++) {
177 ReferenceCollection refs = (ReferenceCollection) valueTable[i];
178 if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
179 String typeLocator = (String) keyTable[i];
180 IFile file = javaBuilder.currentProject.getFile(typeLocator);
182 ClasspathMultiDirectory md = sourceLocations[0];
183 if (sourceLocations.length > 1) {
184 IPath sourceFileFullPath = file.getFullPath();
185 for (int j = 0, m = sourceLocations.length; j < m; j++) {
186 if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(
187 sourceFileFullPath)) {
188 md = sourceLocations[j];
189 if (md.exclusionPatterns == null
190 || !Util.isExcluded(file, md.exclusionPatterns))
195 SourceFile sourceFile = new SourceFile(file, md, encoding);
196 if (sourceFiles.contains(sourceFile))
198 if (compiledAllAtOnce && previousSourceFiles != null
199 && previousSourceFiles.contains(sourceFile))
200 continue next; // can skip previously compiled files since already
201 // saw hierarchy related problems
202 if (PHPBuilder.DEBUG)
203 System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
204 // // update indexfile for the project:
205 sourceFiles.add(sourceFile);
210 protected void addDependentsOf(IPath path, boolean hasStructuralChanges) {
211 if (hasStructuralChanges) {
212 newState.tagAsStructurallyChanged();
213 this.hasStructuralChanges = true;
215 // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
217 path = path.setDevice(null);
218 String packageName = path.removeLastSegments(1).toString();
219 if (!qualifiedStrings.contains(packageName))
220 qualifiedStrings.add(packageName);
221 String typeName = path.lastSegment();
222 int memberIndex = typeName.indexOf('$');
224 typeName = typeName.substring(0, memberIndex);
225 if (!simpleStrings.contains(typeName)) {
226 if (PHPBuilder.DEBUG)
227 System.out.println(" will look for dependents of " //$NON-NLS-1$
228 + typeName + " in " + packageName); //$NON-NLS-1$
229 simpleStrings.add(typeName);
232 protected void cleanUp() {
234 this.sourceFiles = null;
235 this.previousSourceFiles = null;
236 this.qualifiedStrings = null;
237 this.simpleStrings = null;
238 this.secondaryTypesToRemove = null;
239 this.hasStructuralChanges = false;
240 this.compileLoop = 0;
242 //protected boolean findAffectedSourceFiles(IResourceDelta delta,
243 // ClasspathLocation[] classFoldersAndJars) {
244 // for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
245 // ClasspathLocation bLocation = classFoldersAndJars[i];
246 // // either a .class file folder or a zip/jar file
247 // if (bLocation != null) { // skip unchanged output folder
248 // IPath p = bLocation.getProjectRelativePath();
250 // IResourceDelta binaryDelta = delta.findMember(p);
251 // if (binaryDelta != null) {
252 // if (bLocation instanceof ClasspathJar) {
253 // if (JavaBuilder.DEBUG)
254 // System.out.println("ABORTING incremental build... found delta to jar/zip
255 // file"); //$NON-NLS-1$
256 // return false; // do full build since jar file was changed (added/removed
257 // were caught as classpath change)
259 // if (binaryDelta.getKind() == IResourceDelta.ADDED || binaryDelta.getKind()
260 // == IResourceDelta.REMOVED) {
261 // if (JavaBuilder.DEBUG)
262 // System.out.println("ABORTING incremental build... found added/removed
263 // binary folder"); //$NON-NLS-1$
264 // return false; // added/removed binary folder should not make it here
265 // (classpath change), but handle anyways
267 // int segmentCount = binaryDelta.getFullPath().segmentCount();
268 // IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class
269 // files from class folder
270 // for (int j = 0, m = children.length; j < m; j++)
271 // findAffectedSourceFiles(children[j], segmentCount);
272 // notifier.checkCancel();
279 protected void findAffectedSourceFiles(IResourceDelta binaryDelta,
281 // When a package becomes a type or vice versa, expect 2 deltas,
282 // one on the folder & one on the class file
283 IResource resource = binaryDelta.getResource();
284 switch (resource.getType()) {
285 case IResource.FOLDER :
286 switch (binaryDelta.getKind()) {
287 case IResourceDelta.ADDED :
288 case IResourceDelta.REMOVED :
289 IPath packagePath = resource.getFullPath().removeFirstSegments(
291 String packageName = packagePath.toString();
292 if (binaryDelta.getKind() == IResourceDelta.ADDED) {
293 // see if any known source file is from the same package...
294 // classpath already includes new package
295 if (!newState.isKnownPackage(packageName)) {
296 if (PHPBuilder.DEBUG)
297 System.out.println("Found added package " + packageName); //$NON-NLS-1$
298 addDependentsOf(packagePath, false);
301 if (PHPBuilder.DEBUG)
302 System.out.println("Skipped dependents of added package "
303 + packageName); //$NON-NLS-1$
305 // see if the package still exists on the classpath
306 // if (!nameEnvironment.isPackage(packageName)) {
307 // if (JavaBuilder.DEBUG)
308 // System.out.println("Found removed package " + packageName);
310 // addDependentsOf(packagePath, false);
313 if (PHPBuilder.DEBUG)
314 System.out.println("Skipped dependents of removed package "
315 + packageName); //$NON-NLS-1$
317 // fall thru & traverse the sub-packages and .class files
318 case IResourceDelta.CHANGED :
319 IResourceDelta[] children = binaryDelta.getAffectedChildren();
320 for (int i = 0, l = children.length; i < l; i++)
321 findAffectedSourceFiles(children[i], segmentCount);
324 case IResource.FILE :
325 // if (Util.isClassFileName(resource.getName())) {
327 // resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
328 // switch (binaryDelta.getKind()) {
329 // case IResourceDelta.ADDED :
330 // case IResourceDelta.REMOVED :
331 // if (JavaBuilder.DEBUG)
332 // System.out.println("Found added/removed class file " + typePath);
334 // addDependentsOf(typePath, false);
336 // case IResourceDelta.CHANGED :
337 // if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0)
338 // return; // skip it since it really isn't changed
339 // if (JavaBuilder.DEBUG)
340 // System.out.println("Found changed class file " + typePath);
342 // addDependentsOf(typePath, false);
348 protected boolean findSourceFiles(IResourceDelta delta) throws CoreException {
349 for (int i = 0, l = sourceLocations.length; i < l; i++) {
350 ClasspathMultiDirectory md = sourceLocations[i];
351 if (md.sourceFolder.equals(javaBuilder.currentProject)) {
352 // skip nested source & output folders when the project is a source
354 int segmentCount = delta.getFullPath().segmentCount();
355 IResourceDelta[] children = delta.getAffectedChildren();
356 for (int j = 0, m = children.length; j < m; j++)
357 if (!isExcludedFromProject(children[j].getFullPath()))
358 findSourceFiles(children[j], md, segmentCount);
360 IResourceDelta sourceDelta = delta.findMember(md.sourceFolder
361 .getProjectRelativePath());
362 if (sourceDelta != null) {
363 if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
364 if (PHPBuilder.DEBUG)
366 .println("ABORTING incremental build... found removed source folder"); //$NON-NLS-1$
367 return false; // removed source folder should not make it here, but
368 // handle anyways (ADDED is supported)
370 int segmentCount = sourceDelta.getFullPath().segmentCount();
371 IResourceDelta[] children = sourceDelta.getAffectedChildren();
372 for (int j = 0, m = children.length; j < m; j++)
373 findSourceFiles(children[j], md, segmentCount);
376 notifier.checkCancel();
380 protected void findSourceFiles(IResourceDelta sourceDelta,
381 ClasspathMultiDirectory md, int segmentCount) throws CoreException {
382 // When a package becomes a type or vice versa, expect 2 deltas,
383 // one on the folder & one on the source file
384 IResource resource = sourceDelta.getResource();
385 if (md.exclusionPatterns != null
386 && Util.isExcluded(resource, md.exclusionPatterns))
388 switch (resource.getType()) {
389 case IResource.FOLDER :
390 switch (sourceDelta.getKind()) {
391 case IResourceDelta.ADDED :
392 IPath addedPackagePath = resource.getFullPath()
393 .removeFirstSegments(segmentCount);
394 createFolder(addedPackagePath, md.binaryFolder); // ensure package
397 // add dependents even when the package thinks it exists to be on
399 if (PHPBuilder.DEBUG)
400 System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$
401 addDependentsOf(addedPackagePath, true);
402 // fall thru & collect all the source files
403 case IResourceDelta.CHANGED :
404 IResourceDelta[] children = sourceDelta.getAffectedChildren();
405 for (int i = 0, l = children.length; i < l; i++)
406 findSourceFiles(children[i], md, segmentCount);
408 case IResourceDelta.REMOVED :
409 IPath removedPackagePath = resource.getFullPath()
410 .removeFirstSegments(segmentCount);
411 if (sourceLocations.length > 1) {
412 for (int i = 0, l = sourceLocations.length; i < l; i++) {
413 if (sourceLocations[i].sourceFolder.getFolder(
414 removedPackagePath).exists()) {
415 // only a package fragment was removed, same as removing
416 // multiple source files
417 createFolder(removedPackagePath, md.binaryFolder); // ensure
423 IResourceDelta[] removedChildren = sourceDelta
424 .getAffectedChildren();
425 for (int j = 0, m = removedChildren.length; j < m; j++)
426 findSourceFiles(removedChildren[j], md, segmentCount);
431 IFolder removedPackageFolder = md.binaryFolder
432 .getFolder(removedPackagePath);
433 if (removedPackageFolder.exists())
434 removedPackageFolder.delete(IResource.FORCE, null);
435 // add dependents even when the package thinks it does not exist to
436 // be on the safe side
437 if (PHPBuilder.DEBUG)
438 System.out.println("Found removed package " + removedPackagePath); //$NON-NLS-1$
439 addDependentsOf(removedPackagePath, true);
440 newState.removePackage(sourceDelta);
443 case IResource.FILE :
444 String resourceName = resource.getName();
445 if (Util.isJavaFileName(resourceName)) {
446 IPath typePath = resource.getFullPath().removeFirstSegments(
447 segmentCount).removeFileExtension();
448 String typeLocator = resource.getProjectRelativePath().toString();
449 switch (sourceDelta.getKind()) {
450 case IResourceDelta.ADDED :
451 if (PHPBuilder.DEBUG)
452 System.out.println("Compile this added source file "
453 + typeLocator); //$NON-NLS-1$
454 sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
455 String typeName = typePath.toString();
456 if (!newState.isDuplicateLocator(typeName, typeLocator)) { // adding
463 if (PHPBuilder.DEBUG)
464 System.out.println("Found added source file " + typeName); //$NON-NLS-1$
465 addDependentsOf(typePath, true);
468 case IResourceDelta.REMOVED :
469 char[][] definedTypeNames = newState
470 .getDefinedTypeNamesFor(typeLocator);
471 if (definedTypeNames == null) { // defined a single type matching
473 removeClassFile(typePath, md.binaryFolder);
474 if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
475 // remove problems and tasks for a compilation unit that is
476 // being moved (to another package or renamed)
477 // if the target file is a compilation unit, the new cu will
479 // if the target file is a non-java resource, then markers
482 IResource movedFile = javaBuilder.workspaceRoot
483 .getFile(sourceDelta.getMovedToPath());
484 PHPBuilder.removeProblemsAndTasksFor(movedFile);
487 if (PHPBuilder.DEBUG)
488 System.out.println("Found removed source file "
489 + typePath.toString()); //$NON-NLS-1$
490 addDependentsOf(typePath, true); // add dependents of the
491 // source file since it may be
492 // involved in a name
494 if (definedTypeNames.length > 0) { // skip it if it failed to
495 // successfully define a
497 IPath packagePath = typePath.removeLastSegments(1);
498 for (int i = 0, l = definedTypeNames.length; i < l; i++)
499 removeClassFile(packagePath.append(new String(
500 definedTypeNames[i])), md.binaryFolder);
503 newState.removeLocator(typeLocator);
505 case IResourceDelta.CHANGED :
506 if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
507 return; // skip it since it really isn't changed
508 if (PHPBuilder.DEBUG)
509 System.out.println("Compile this changed source file "
510 + typeLocator); //$NON-NLS-1$
511 sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
514 // } else if (Util.isClassFileName(resourceName)) {
515 // return; // skip class files
516 } else if (md.hasIndependentOutputFolder) {
517 if (javaBuilder.filterExtraResource(resource))
519 // copy all other resource deltas to the output folder
520 IPath resourcePath = resource.getFullPath().removeFirstSegments(
522 IResource outputFile = md.binaryFolder.getFile(resourcePath);
523 switch (sourceDelta.getKind()) {
524 case IResourceDelta.ADDED :
525 if (outputFile.exists()) {
526 if (PHPBuilder.DEBUG)
527 System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
528 outputFile.delete(IResource.FORCE, null);
530 if (PHPBuilder.DEBUG)
531 System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$
532 createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
539 resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
540 outputFile.setDerived(true);
542 case IResourceDelta.REMOVED :
543 if (outputFile.exists()) {
544 if (PHPBuilder.DEBUG)
545 System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$
546 outputFile.delete(IResource.FORCE, null);
549 case IResourceDelta.CHANGED :
550 if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
551 return; // skip it since it really isn't changed
552 if (outputFile.exists()) {
553 if (PHPBuilder.DEBUG)
554 System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
555 outputFile.delete(IResource.FORCE, null);
557 if (PHPBuilder.DEBUG)
558 System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$
559 createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
566 resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
567 outputFile.setDerived(true);
573 protected void finishedWith(String sourceLocator, CompilationResult result,
574 char[] mainTypeName, ArrayList definedTypeNames,
575 ArrayList duplicateTypeNames) throws CoreException {
576 char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator);
577 if (previousTypeNames == null)
578 previousTypeNames = new char[][]{mainTypeName};
579 IPath packagePath = null;
580 next : for (int i = 0, l = previousTypeNames.length; i < l; i++) {
581 char[] previous = previousTypeNames[i];
582 for (int j = 0, m = definedTypeNames.size(); j < m; j++)
583 if (CharOperation.equals(previous, (char[]) definedTypeNames.get(j)))
585 SourceFile sourceFile = (SourceFile) result.getCompilationUnit();
586 if (packagePath == null) {
587 int count = sourceFile.sourceLocation.sourceFolder.getFullPath()
589 packagePath = sourceFile.resource.getFullPath().removeFirstSegments(
590 count).removeLastSegments(1);
592 if (secondaryTypesToRemove == null)
593 this.secondaryTypesToRemove = new SimpleLookupTable();
594 ArrayList types = (ArrayList) secondaryTypesToRemove
595 .get(sourceFile.sourceLocation.binaryFolder);
597 types = new ArrayList(definedTypeNames.size());
598 types.add(packagePath.append(new String(previous)));
599 secondaryTypesToRemove.put(sourceFile.sourceLocation.binaryFolder, types);
601 // super.finishedWith(sourceLocator, result, mainTypeName,
602 // definedTypeNames, duplicateTypeNames);
604 protected void removeClassFile(IPath typePath, IContainer outputFolder)
605 throws CoreException {
606 if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type
607 newState.removeQualifiedTypeName(typePath.toString());
608 // add dependents even when the type thinks it does not exist to be on
610 if (PHPBuilder.DEBUG)
611 System.out.println("Found removed type " + typePath); //$NON-NLS-1$
612 addDependentsOf(typePath, true); // when member types are removed, their
613 // enclosing type is structurally
616 IFile classFile = outputFolder.getFile(typePath
617 .addFileExtension(PHPBuilder.CLASS_EXTENSION));
618 if (classFile.exists()) {
619 if (PHPBuilder.DEBUG)
620 System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$
621 classFile.delete(IResource.FORCE, null);
624 protected void removeSecondaryTypes() throws CoreException {
625 if (secondaryTypesToRemove != null) { // delayed deleting secondary types
626 // until the end of the compile loop
627 Object[] keyTable = secondaryTypesToRemove.keyTable;
628 Object[] valueTable = secondaryTypesToRemove.valueTable;
629 for (int i = 0, l = keyTable.length; i < l; i++) {
630 IContainer outputFolder = (IContainer) keyTable[i];
631 if (outputFolder != null) {
632 ArrayList paths = (ArrayList) valueTable[i];
633 for (int j = 0, m = paths.size(); j < m; j++)
634 removeClassFile((IPath) paths.get(j), outputFolder);
637 this.secondaryTypesToRemove = null;
638 if (previousSourceFiles != null && previousSourceFiles.size() > 1)
639 this.previousSourceFiles = null; // cannot optimize recompile case when
640 // a secondary type is deleted
643 protected void resetCollections() {
644 previousSourceFiles = sourceFiles.isEmpty()
646 : (ArrayList) sourceFiles.clone();
648 qualifiedStrings.clear();
649 simpleStrings.clear();
652 protected void updateProblemsFor(SourceFile sourceFile,
653 CompilationResult result) throws CoreException {
654 IMarker[] markers = PHPBuilder.getProblemsFor(sourceFile.resource);
655 IProblem[] problems = result.getProblems();
656 if (problems == null && markers.length == 0)
658 notifier.updateProblemCounts(markers, problems);
659 PHPBuilder.removeProblemsFor(sourceFile.resource);
660 storeProblemsFor(sourceFile, problems);
662 protected void updateTasksFor(SourceFile sourceFile, CompilationResult result)
663 throws CoreException {
664 IMarker[] markers = PHPBuilder.getTasksFor(sourceFile.resource);
665 IProblem[] tasks = result.getTasks();
666 if (tasks == null && markers.length == 0)
668 PHPBuilder.removeTasksFor(sourceFile.resource);
669 storeTasksFor(sourceFile, tasks);
671 //protected void writeClassFileBytes(byte[] bytes, IFile file, String
672 // qualifiedFileName, boolean isSecondaryType) throws CoreException {
673 // // Before writing out the class file, compare it to the previous file
674 // // If structural changes occured then add dependent source files
675 // if (file.exists()) {
676 // if (writeClassFileCheck(file, qualifiedFileName, bytes)) {
677 // if (JavaBuilder.DEBUG)
678 // System.out.println("Writing changed class file " +
679 // file.getName());//$NON-NLS-1$
680 // file.setContents(new ByteArrayInputStream(bytes), true, false, null);
681 // if (!file.isDerived())
682 // file.setDerived(true);
683 // } else if (JavaBuilder.DEBUG) {
684 // System.out.println("Skipped over unchanged class file " +
685 // file.getName());//$NON-NLS-1$
688 // if (isSecondaryType)
689 // addDependentsOf(new Path(qualifiedFileName), true); // new secondary type
690 // if (JavaBuilder.DEBUG)
691 // System.out.println("Writing new class file " +
692 // file.getName());//$NON-NLS-1$
693 // file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
694 // file.setDerived(true);
697 //protected boolean writeClassFileCheck(IFile file, String fileName, byte[]
698 // newBytes) throws CoreException {
700 // byte[] oldBytes = Util.getResourceContentsAsByteArray(file);
701 // if (this.compileLoop > 1) { // only optimize files which were recompiled
702 // during the dependent pass, see 33990
703 // notEqual : if (newBytes.length == oldBytes.length) {
704 // for (int i = newBytes.length; --i >= 0;)
705 // if (newBytes[i] != oldBytes[i]) break notEqual;
706 // return false; // bytes are identical so skip them
709 // IPath location = file.getLocation();
710 // if (location == null) return false; // unable to determine location of
712 // ClassFileReader reader = new ClassFileReader(oldBytes,
713 // location.toString().toCharArray());
714 // // ignore local types since they're only visible inside a single method
715 // if (!(reader.isLocal() || reader.isAnonymous()) &&
716 // reader.hasStructuralChanges(newBytes)) {
717 // if (JavaBuilder.DEBUG)
718 // System.out.println("Type has structural changes " + fileName);
720 // addDependentsOf(new Path(fileName), true);
722 // } catch (ClassFormatException e) {
723 // addDependentsOf(new Path(fileName), true);
727 public String toString() {
728 return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
733 * static void dump(IResourceDelta delta) { StringBuffer buffer = new
734 * StringBuffer(); IPath path = delta.getFullPath(); for (int i =
735 * path.segmentCount(); --i > 0;) buffer.append(" "); switch
736 * (delta.getKind()) { case IResourceDelta.ADDED: buffer.append('+'); break;
737 * case IResourceDelta.REMOVED: buffer.append('-'); break; case
738 * IResourceDelta.CHANGED: '); break; case IResourceDelta.NO_CHANGE:
739 * buffer.append('='); break; default: buffer.append('?'); break; }
740 * buffer.append(path); System.out.println(buffer.toString());
741 * IResourceDelta[] children = delta.getAffectedChildren(); for (int i = 0, l =
742 * children.length; i < l; i++) dump(children[i]); }