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;
14 import net.sourceforge.phpdt.core.compiler.IProblem;
15 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
16 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
17 import net.sourceforge.phpdt.internal.core.util.Util;
18 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
19 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
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 sourceDelta.accept(new ParserVisitor(javaBuilder.currentProject, notifier.monitor));
76 if (!findSourceFiles(sourceDelta))
79 notifier.updateProgressDelta(0.10f);
80 // Object[] keyTable = deltas.keyTable;
81 // Object[] valueTable = deltas.valueTable;
82 //// final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault()
83 //// .getIndexManager(javaBuilder.currentProject);
84 // for (int i = 0, l = valueTable.length; i < l; i++) {
85 // IResourceDelta delta = (IResourceDelta) valueTable[i];
86 // if (delta != null) {
87 // IResource resource = delta.getResource();
88 // int resourceType = resource.getType();
89 // if (resourceType == IResource.FILE) {
90 // switch (delta.getKind()) {
91 // case IResourceDelta.ADDED :
92 // if ((resource.getFileExtension() != null)
93 // && PHPFileUtil.isPHPFile((IFile) resource)) {
94 // // update indexfile for the project:
95 //// indexManager.addFile((IFile) resource);
98 // case IResourceDelta.CHANGED :
99 // if ((resource.getFileExtension() != null)
100 // && PHPFileUtil.isPHPFile((IFile) resource)) {
101 // // update indexfile for the project:
102 //// indexManager.changeFile((IFile) resource);
105 // case IResourceDelta.REMOVED :
106 // if ((resource.getFileExtension() != null)
107 // && PHPFileUtil.isPHPFile((IFile) resource)) {
108 // // update indexfile for the project:
109 //// indexManager.removeFile((IFile) resource);
114 // // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[])
115 // // javaBuilder.binaryLocationsPerProject.get(keyTable[i]);
116 // // if (classFoldersAndJars != null)
117 // // if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return
121 notifier.updateProgressDelta(0.10f);
122 notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
123 addAffectedSourceFiles();
124 notifier.updateProgressDelta(0.05f);
125 this.compileLoop = 0;
126 float increment = 0.40f;
127 while (sourceFiles.size() > 0) { // added to in acceptResult
128 if (++this.compileLoop > MaxCompileLoop) {
129 if (PHPBuilder.DEBUG)
131 .println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$
134 notifier.checkCancel();
135 SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()];
136 sourceFiles.toArray(allSourceFiles);
138 workQueue.addAll(allSourceFiles);
139 notifier.setProgressPerCompilationUnit(increment
140 / allSourceFiles.length);
141 increment = increment / 2;
142 compile(allSourceFiles);
143 // removeSecondaryTypes();
144 addAffectedSourceFiles();
146 if (this.hasStructuralChanges && javaBuilder.javaProject.hasCycleMarker())
147 javaBuilder.mustPropagateStructuralChanges();
148 } catch (AbortIncrementalBuildException e) {
149 // abort the incremental build and let the batch builder handle the
151 if (PHPBuilder.DEBUG)
152 System.out.println("ABORTING incremental build... cannot find "
153 + e.qualifiedTypeName + //$NON-NLS-1$
154 ". Could have been renamed inside its existing source file."); //$NON-NLS-1$
156 } catch (CoreException e) {
157 throw internalException(e);
163 protected void addAffectedSourceFiles() {
164 if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())
166 // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
168 // char[][][] qualifiedNames = ReferenceCollection
169 // .internQualifiedNames(qualifiedStrings);
170 // if a well known qualified name was found then we can skip over these
171 // if (qualifiedNames.length < qualifiedStrings.size())
172 // qualifiedNames = null;
173 // char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
174 // if a well known name was found then we can skip over these
175 // if (simpleNames.length < simpleStrings.size())
176 // simpleNames = null;
177 // Object[] keyTable = newState.references.keyTable;
178 // Object[] valueTable = newState.references.valueTable;
179 // next : for (int i = 0, l = valueTable.length; i < l; i++) {
180 // ReferenceCollection refs = (ReferenceCollection) valueTable[i];
181 // if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
182 // String typeLocator = (String) keyTable[i];
183 // IFile file = javaBuilder.currentProject.getFile(typeLocator);
184 // if (file.exists()) {
185 // ClasspathMultiDirectory md = sourceLocations[0];
186 // if (sourceLocations.length > 1) {
187 // IPath sourceFileFullPath = file.getFullPath();
188 // for (int j = 0, m = sourceLocations.length; j < m; j++) {
189 // if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(
190 // sourceFileFullPath)) {
191 // md = sourceLocations[j];
192 // if (md.exclusionPatterns == null
193 // || !Util.isExcluded(file, md.exclusionPatterns))
198 // SourceFile sourceFile = new SourceFile(file, md, encoding);
199 // if (sourceFiles.contains(sourceFile))
201 // if (compiledAllAtOnce && previousSourceFiles != null
202 // && previousSourceFiles.contains(sourceFile))
203 // continue next; // can skip previously compiled files since already
204 // // saw hierarchy related problems
205 // if (PHPBuilder.DEBUG)
206 // System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
207 // // // update indexfile for the project:
208 // sourceFiles.add(sourceFile);
213 protected void addDependentsOf(IPath path, boolean hasStructuralChanges) {
214 if (hasStructuralChanges) {
215 newState.tagAsStructurallyChanged();
216 this.hasStructuralChanges = true;
218 // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
220 path = path.setDevice(null);
221 String packageName = path.removeLastSegments(1).toString();
222 if (!qualifiedStrings.contains(packageName))
223 qualifiedStrings.add(packageName);
224 String typeName = path.lastSegment();
225 int memberIndex = typeName.indexOf('$');
227 typeName = typeName.substring(0, memberIndex);
228 if (!simpleStrings.contains(typeName)) {
229 if (PHPBuilder.DEBUG)
230 System.out.println(" will look for dependents of " //$NON-NLS-1$
231 + typeName + " in " + packageName); //$NON-NLS-1$
232 simpleStrings.add(typeName);
235 protected void cleanUp() {
237 this.sourceFiles = null;
238 this.previousSourceFiles = null;
239 this.qualifiedStrings = null;
240 this.simpleStrings = null;
241 this.secondaryTypesToRemove = null;
242 this.hasStructuralChanges = false;
243 this.compileLoop = 0;
245 //protected boolean findAffectedSourceFiles(IResourceDelta delta,
246 // ClasspathLocation[] classFoldersAndJars) {
247 // for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
248 // ClasspathLocation bLocation = classFoldersAndJars[i];
249 // // either a .class file folder or a zip/jar file
250 // if (bLocation != null) { // skip unchanged output folder
251 // IPath p = bLocation.getProjectRelativePath();
253 // IResourceDelta binaryDelta = delta.findMember(p);
254 // if (binaryDelta != null) {
255 // if (bLocation instanceof ClasspathJar) {
256 // if (JavaBuilder.DEBUG)
257 // System.out.println("ABORTING incremental build... found delta to jar/zip
258 // file"); //$NON-NLS-1$
259 // return false; // do full build since jar file was changed (added/removed
260 // were caught as classpath change)
262 // if (binaryDelta.getKind() == IResourceDelta.ADDED || binaryDelta.getKind()
263 // == IResourceDelta.REMOVED) {
264 // if (JavaBuilder.DEBUG)
265 // System.out.println("ABORTING incremental build... found added/removed
266 // binary folder"); //$NON-NLS-1$
267 // return false; // added/removed binary folder should not make it here
268 // (classpath change), but handle anyways
270 // int segmentCount = binaryDelta.getFullPath().segmentCount();
271 // IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class
272 // files from class folder
273 // for (int j = 0, m = children.length; j < m; j++)
274 // findAffectedSourceFiles(children[j], segmentCount);
275 // notifier.checkCancel();
282 protected void findAffectedSourceFiles(IResourceDelta binaryDelta,
284 // When a package becomes a type or vice versa, expect 2 deltas,
285 // one on the folder & one on the class file
286 IResource resource = binaryDelta.getResource();
287 switch (resource.getType()) {
288 case IResource.FOLDER :
289 switch (binaryDelta.getKind()) {
290 case IResourceDelta.ADDED :
291 case IResourceDelta.REMOVED :
292 IPath packagePath = resource.getFullPath().removeFirstSegments(
294 String packageName = packagePath.toString();
295 if (binaryDelta.getKind() == IResourceDelta.ADDED) {
296 // see if any known source file is from the same package...
297 // classpath already includes new package
298 // if (!newState.isKnownPackage(packageName)) {
299 // if (PHPBuilder.DEBUG)
300 // System.out.println("Found added package " + packageName); //$NON-NLS-1$
301 // addDependentsOf(packagePath, false);
304 if (PHPBuilder.DEBUG)
305 System.out.println("Skipped dependents of added package "
306 + packageName); //$NON-NLS-1$
308 // see if the package still exists on the classpath
309 // if (!nameEnvironment.isPackage(packageName)) {
310 // if (JavaBuilder.DEBUG)
311 // System.out.println("Found removed package " + packageName);
313 // addDependentsOf(packagePath, false);
316 if (PHPBuilder.DEBUG)
317 System.out.println("Skipped dependents of removed package "
318 + packageName); //$NON-NLS-1$
320 // fall thru & traverse the sub-packages and .class files
321 case IResourceDelta.CHANGED :
322 IResourceDelta[] children = binaryDelta.getAffectedChildren();
323 for (int i = 0, l = children.length; i < l; i++)
324 findAffectedSourceFiles(children[i], segmentCount);
327 case IResource.FILE :
328 // if (Util.isClassFileName(resource.getName())) {
330 // resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
331 // switch (binaryDelta.getKind()) {
332 // case IResourceDelta.ADDED :
333 // case IResourceDelta.REMOVED :
334 // if (JavaBuilder.DEBUG)
335 // System.out.println("Found added/removed class file " + typePath);
337 // addDependentsOf(typePath, false);
339 // case IResourceDelta.CHANGED :
340 // if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0)
341 // return; // skip it since it really isn't changed
342 // if (JavaBuilder.DEBUG)
343 // System.out.println("Found changed class file " + typePath);
345 // addDependentsOf(typePath, false);
351 protected boolean findSourceFiles(IResourceDelta delta) throws CoreException {
352 for (int i = 0, l = sourceLocations.length; i < l; i++) {
353 ClasspathMultiDirectory md = sourceLocations[i];
354 if (md.sourceFolder.equals(javaBuilder.currentProject)) {
355 // skip nested source & output folders when the project is a source
357 int segmentCount = delta.getFullPath().segmentCount();
358 IResourceDelta[] children = delta.getAffectedChildren();
359 for (int j = 0, m = children.length; j < m; j++)
360 if (!isExcludedFromProject(children[j].getFullPath()))
361 findSourceFiles(children[j], md, segmentCount);
363 IResourceDelta sourceDelta = delta.findMember(md.sourceFolder
364 .getProjectRelativePath());
365 if (sourceDelta != null) {
366 if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
367 if (PHPBuilder.DEBUG)
369 .println("ABORTING incremental build... found removed source folder"); //$NON-NLS-1$
370 return false; // removed source folder should not make it here, but
371 // handle anyways (ADDED is supported)
373 int segmentCount = sourceDelta.getFullPath().segmentCount();
374 IResourceDelta[] children = sourceDelta.getAffectedChildren();
375 for (int j = 0, m = children.length; j < m; j++)
376 findSourceFiles(children[j], md, segmentCount);
379 notifier.checkCancel();
383 protected void findSourceFiles(IResourceDelta sourceDelta,
384 ClasspathMultiDirectory md, int segmentCount) throws CoreException {
385 // When a package becomes a type or vice versa, expect 2 deltas,
386 // one on the folder & one on the source file
387 IResource resource = sourceDelta.getResource();
388 if (md.exclusionPatterns != null
389 && Util.isExcluded(resource, md.exclusionPatterns))
391 switch (resource.getType()) {
392 case IResource.FOLDER :
393 switch (sourceDelta.getKind()) {
394 case IResourceDelta.ADDED :
395 IPath addedPackagePath = resource.getFullPath()
396 .removeFirstSegments(segmentCount);
397 createFolder(addedPackagePath, md.binaryFolder); // ensure package
400 // add dependents even when the package thinks it exists to be on
402 if (PHPBuilder.DEBUG)
403 System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$
404 addDependentsOf(addedPackagePath, true);
405 // fall thru & collect all the source files
406 case IResourceDelta.CHANGED :
407 IResourceDelta[] children = sourceDelta.getAffectedChildren();
408 for (int i = 0, l = children.length; i < l; i++)
409 findSourceFiles(children[i], md, segmentCount);
411 case IResourceDelta.REMOVED :
412 IPath removedPackagePath = resource.getFullPath()
413 .removeFirstSegments(segmentCount);
414 if (sourceLocations.length > 1) {
415 for (int i = 0, l = sourceLocations.length; i < l; i++) {
416 if (sourceLocations[i].sourceFolder.getFolder(
417 removedPackagePath).exists()) {
418 // only a package fragment was removed, same as removing
419 // multiple source files
420 createFolder(removedPackagePath, md.binaryFolder); // ensure
426 IResourceDelta[] removedChildren = sourceDelta
427 .getAffectedChildren();
428 for (int j = 0, m = removedChildren.length; j < m; j++)
429 findSourceFiles(removedChildren[j], md, segmentCount);
434 IFolder removedPackageFolder = md.binaryFolder
435 .getFolder(removedPackagePath);
436 if (removedPackageFolder.exists())
437 removedPackageFolder.delete(IResource.FORCE, null);
438 // add dependents even when the package thinks it does not exist to
439 // be on the safe side
440 if (PHPBuilder.DEBUG)
441 System.out.println("Found removed package " + removedPackagePath); //$NON-NLS-1$
442 addDependentsOf(removedPackagePath, true);
443 newState.removePackage(sourceDelta);
446 case IResource.FILE :
447 String resourceName = resource.getName();
448 if (net.sourceforge.phpdt.internal.compiler.util.Util.isJavaFileName(resourceName)) {
449 IPath typePath = resource.getFullPath().removeFirstSegments(
450 segmentCount).removeFileExtension();
451 String typeLocator = resource.getProjectRelativePath().toString();
452 switch (sourceDelta.getKind()) {
453 case IResourceDelta.ADDED :
454 if (PHPBuilder.DEBUG)
455 System.out.println("Compile this added source file "
456 + typeLocator); //$NON-NLS-1$
457 sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
458 String typeName = typePath.toString();
459 // if (!newState.isDuplicateLocator(typeName, typeLocator)) { // adding
466 // if (PHPBuilder.DEBUG)
467 // System.out.println("Found added source file " + typeName); //$NON-NLS-1$
468 // addDependentsOf(typePath, true);
471 case IResourceDelta.REMOVED :
472 // char[][] definedTypeNames = newState
473 // .getDefinedTypeNamesFor(typeLocator);
474 // if (definedTypeNames == null) { // defined a single type matching
476 // removeClassFile(typePath, md.binaryFolder);
477 // if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
478 // // remove problems and tasks for a compilation unit that is
479 // // being moved (to another package or renamed)
480 // // if the target file is a compilation unit, the new cu will
482 // // if the target file is a non-java resource, then markers
485 // IResource movedFile = javaBuilder.workspaceRoot
486 // .getFile(sourceDelta.getMovedToPath());
487 // PHPBuilder.removeProblemsAndTasksFor(movedFile);
490 if (PHPBuilder.DEBUG)
491 System.out.println("Found removed source file "
492 + typePath.toString()); //$NON-NLS-1$
493 addDependentsOf(typePath, true); // add dependents of the
494 // source file since it may be
495 // involved in a name
497 // if (definedTypeNames.length > 0) { // skip it if it failed to
498 // // successfully define a
500 // IPath packagePath = typePath.removeLastSegments(1);
501 // for (int i = 0, l = definedTypeNames.length; i < l; i++)
502 // removeClassFile(packagePath.append(new String(
503 // definedTypeNames[i])), md.binaryFolder);
506 // newState.removeLocator(typeLocator);
508 case IResourceDelta.CHANGED :
509 if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
510 return; // skip it since it really isn't changed
511 if (PHPBuilder.DEBUG)
512 System.out.println("Compile this changed source file "
513 + typeLocator); //$NON-NLS-1$
514 sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
517 // } else if (Util.isClassFileName(resourceName)) {
518 // return; // skip class files
519 } else if (md.hasIndependentOutputFolder) {
520 if (javaBuilder.filterExtraResource(resource))
522 // copy all other resource deltas to the output folder
523 IPath resourcePath = resource.getFullPath().removeFirstSegments(
525 IResource outputFile = md.binaryFolder.getFile(resourcePath);
526 switch (sourceDelta.getKind()) {
527 case IResourceDelta.ADDED :
528 if (outputFile.exists()) {
529 if (PHPBuilder.DEBUG)
530 System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
531 outputFile.delete(IResource.FORCE, null);
533 if (PHPBuilder.DEBUG)
534 System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$
535 createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
542 resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
543 outputFile.setDerived(true);
545 case IResourceDelta.REMOVED :
546 if (outputFile.exists()) {
547 if (PHPBuilder.DEBUG)
548 System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$
549 outputFile.delete(IResource.FORCE, null);
552 case IResourceDelta.CHANGED :
553 if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
554 return; // skip it since it really isn't changed
555 if (outputFile.exists()) {
556 if (PHPBuilder.DEBUG)
557 System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
558 outputFile.delete(IResource.FORCE, null);
560 if (PHPBuilder.DEBUG)
561 System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$
562 createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
569 resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
570 outputFile.setDerived(true);
576 protected void finishedWith(String sourceLocator, CompilationResult result,
577 char[] mainTypeName, ArrayList definedTypeNames,
578 ArrayList duplicateTypeNames) throws CoreException {
579 // char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator);
580 // if (previousTypeNames == null)
581 // previousTypeNames = new char[][]{mainTypeName};
582 // IPath packagePath = null;
583 // next : for (int i = 0, l = previousTypeNames.length; i < l; i++) {
584 // char[] previous = previousTypeNames[i];
585 // for (int j = 0, m = definedTypeNames.size(); j < m; j++)
586 // if (CharOperation.equals(previous, (char[]) definedTypeNames.get(j)))
588 // SourceFile sourceFile = (SourceFile) result.getCompilationUnit();
589 // if (packagePath == null) {
590 // int count = sourceFile.sourceLocation.sourceFolder.getFullPath()
592 // packagePath = sourceFile.resource.getFullPath().removeFirstSegments(
593 // count).removeLastSegments(1);
595 // if (secondaryTypesToRemove == null)
596 // this.secondaryTypesToRemove = new SimpleLookupTable();
597 // ArrayList types = (ArrayList) secondaryTypesToRemove
598 // .get(sourceFile.sourceLocation.binaryFolder);
599 // if (types == null)
600 // types = new ArrayList(definedTypeNames.size());
601 // types.add(packagePath.append(new String(previous)));
602 // secondaryTypesToRemove.put(sourceFile.sourceLocation.binaryFolder, types);
604 // super.finishedWith(sourceLocator, result, mainTypeName,
605 // definedTypeNames, duplicateTypeNames);
607 // protected void removeClassFile(IPath typePath, IContainer outputFolder)
608 // throws CoreException {
609 // if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type
610 // newState.removeQualifiedTypeName(typePath.toString());
611 // // add dependents even when the type thinks it does not exist to be on
613 // if (PHPBuilder.DEBUG)
614 // System.out.println("Found removed type " + typePath); //$NON-NLS-1$
615 // addDependentsOf(typePath, true); // when member types are removed, their
616 // // enclosing type is structurally
619 // IFile classFile = outputFolder.getFile(typePath
620 // .addFileExtension(PHPBuilder.CLASS_EXTENSION));
621 // if (classFile.exists()) {
622 // if (PHPBuilder.DEBUG)
623 // System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$
624 // classFile.delete(IResource.FORCE, null);
627 // protected void removeSecondaryTypes() throws CoreException {
628 // if (secondaryTypesToRemove != null) { // delayed deleting secondary types
629 // // until the end of the compile loop
630 // Object[] keyTable = secondaryTypesToRemove.keyTable;
631 // Object[] valueTable = secondaryTypesToRemove.valueTable;
632 // for (int i = 0, l = keyTable.length; i < l; i++) {
633 // IContainer outputFolder = (IContainer) keyTable[i];
634 // if (outputFolder != null) {
635 // ArrayList paths = (ArrayList) valueTable[i];
636 // for (int j = 0, m = paths.size(); j < m; j++)
637 // removeClassFile((IPath) paths.get(j), outputFolder);
640 // this.secondaryTypesToRemove = null;
641 // if (previousSourceFiles != null && previousSourceFiles.size() > 1)
642 // this.previousSourceFiles = null; // cannot optimize recompile case when
643 // // a secondary type is deleted
646 protected void resetCollections() {
647 previousSourceFiles = sourceFiles.isEmpty()
649 : (ArrayList) sourceFiles.clone();
651 qualifiedStrings.clear();
652 simpleStrings.clear();
655 protected void updateProblemsFor(SourceFile sourceFile,
656 CompilationResult result) throws CoreException {
657 IMarker[] markers = PHPBuilder.getProblemsFor(sourceFile.resource);
658 IProblem[] problems = result.getProblems();
659 if (problems == null && markers.length == 0)
661 notifier.updateProblemCounts(markers, problems);
662 PHPBuilder.removeProblemsFor(sourceFile.resource);
663 storeProblemsFor(sourceFile, problems);
665 protected void updateTasksFor(SourceFile sourceFile, CompilationResult result)
666 throws CoreException {
667 IMarker[] markers = PHPBuilder.getTasksFor(sourceFile.resource);
668 IProblem[] tasks = result.getTasks();
669 if (tasks == null && markers.length == 0)
671 PHPBuilder.removeTasksFor(sourceFile.resource);
672 storeTasksFor(sourceFile, tasks);
674 //protected void writeClassFileBytes(byte[] bytes, IFile file, String
675 // qualifiedFileName, boolean isSecondaryType) throws CoreException {
676 // // Before writing out the class file, compare it to the previous file
677 // // If structural changes occured then add dependent source files
678 // if (file.exists()) {
679 // if (writeClassFileCheck(file, qualifiedFileName, bytes)) {
680 // if (JavaBuilder.DEBUG)
681 // System.out.println("Writing changed class file " +
682 // file.getName());//$NON-NLS-1$
683 // file.setContents(new ByteArrayInputStream(bytes), true, false, null);
684 // if (!file.isDerived())
685 // file.setDerived(true);
686 // } else if (JavaBuilder.DEBUG) {
687 // System.out.println("Skipped over unchanged class file " +
688 // file.getName());//$NON-NLS-1$
691 // if (isSecondaryType)
692 // addDependentsOf(new Path(qualifiedFileName), true); // new secondary type
693 // if (JavaBuilder.DEBUG)
694 // System.out.println("Writing new class file " +
695 // file.getName());//$NON-NLS-1$
696 // file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
697 // file.setDerived(true);
700 //protected boolean writeClassFileCheck(IFile file, String fileName, byte[]
701 // newBytes) throws CoreException {
703 // byte[] oldBytes = Util.getResourceContentsAsByteArray(file);
704 // if (this.compileLoop > 1) { // only optimize files which were recompiled
705 // during the dependent pass, see 33990
706 // notEqual : if (newBytes.length == oldBytes.length) {
707 // for (int i = newBytes.length; --i >= 0;)
708 // if (newBytes[i] != oldBytes[i]) break notEqual;
709 // return false; // bytes are identical so skip them
712 // IPath location = file.getLocation();
713 // if (location == null) return false; // unable to determine location of
715 // ClassFileReader reader = new ClassFileReader(oldBytes,
716 // location.toString().toCharArray());
717 // // ignore local types since they're only visible inside a single method
718 // if (!(reader.isLocal() || reader.isAnonymous()) &&
719 // reader.hasStructuralChanges(newBytes)) {
720 // if (JavaBuilder.DEBUG)
721 // System.out.println("Type has structural changes " + fileName);
723 // addDependentsOf(new Path(fileName), true);
725 // } catch (ClassFormatException e) {
726 // addDependentsOf(new Path(fileName), true);
730 public String toString() {
731 return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
736 * static void dump(IResourceDelta delta) { StringBuffer buffer = new
737 * StringBuffer(); IPath path = delta.getFullPath(); for (int i =
738 * path.segmentCount(); --i > 0;) buffer.append(" "); switch
739 * (delta.getKind()) { case IResourceDelta.ADDED: buffer.append('+'); break;
740 * case IResourceDelta.REMOVED: buffer.append('-'); break; case
741 * IResourceDelta.CHANGED: '); break; case IResourceDelta.NO_CHANGE:
742 * buffer.append('='); break; default: buffer.append('?'); break; }
743 * buffer.append(path); System.out.println(buffer.toString());
744 * IResourceDelta[] children = delta.getAffectedChildren(); for (int i = 0, l =
745 * children.length; i < l; i++) dump(children[i]); }