63656975d3f5bc0fc30a770a82cdf0d050411c88
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / builder / IncrementalImageBuilder.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.builder;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.compiler.IProblem;
16 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
17 import net.sourceforge.phpdt.internal.compiler.problem.ProblemHandler;
18 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
19 import net.sourceforge.phpdt.internal.core.util.Util;
20
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IFolder;
23 import org.eclipse.core.resources.IMarker;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.resources.IResourceDelta;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IPath;
28
29 /**
30  * The incremental image builder
31  */
32 public class IncrementalImageBuilder extends AbstractImageBuilder {
33   protected ArrayList sourceFiles;
34
35   protected ArrayList previousSourceFiles;
36
37   protected ArrayList qualifiedStrings;
38
39   protected ArrayList simpleStrings;
40
41   protected SimpleLookupTable secondaryTypesToRemove;
42
43   protected boolean hasStructuralChanges;
44
45   protected int compileLoop;
46
47   public static int MaxCompileLoop = 5; // perform a full build if it takes
48
49   // more than ? incremental compile
50   // loops
51   protected IncrementalImageBuilder(PHPBuilder javaBuilder) {
52     super(javaBuilder);
53     this.nameEnvironment.isIncrementalBuild = true;
54     this.newState.copyFrom(javaBuilder.lastState);
55     this.sourceFiles = new ArrayList(33);
56     this.previousSourceFiles = null;
57     this.qualifiedStrings = new ArrayList(33);
58     this.simpleStrings = new ArrayList(33);
59     this.hasStructuralChanges = false;
60     this.compileLoop = 0;
61   }
62
63   public boolean build(SimpleLookupTable deltas) {
64     // initialize builder
65     // walk this project's deltas, find changed source files
66     // walk prereq projects' deltas, find changed class files & add affected
67     // source files
68     //   use the build state # to skip the deltas for certain prereq projects
69     //   ignore changed zip/jar files since they caused a full build
70     // compile the source files & acceptResult()
71     // compare the produced class files against the existing ones on disk
72     // recompile all dependent source files of any type with structural changes
73     // or new/removed secondary type
74     // keep a loop counter to abort & perform a full build
75     if (PHPBuilder.DEBUG)
76       System.out.println("INCREMENTAL build"); //$NON-NLS-1$
77     try {
78       resetCollections();
79       notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$
80       IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject);
81       if (sourceDelta != null) {
82         sourceDelta.accept(new ParserVisitor(javaBuilder.currentProject, notifier.monitor));
83
84         if (!findSourceFiles(sourceDelta))
85           return false;
86       }
87       notifier.updateProgressDelta(0.10f);
88       //      Object[] keyTable = deltas.keyTable;
89       //      Object[] valueTable = deltas.valueTable;
90       //// final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault()
91       //// .getIndexManager(javaBuilder.currentProject);
92       //      for (int i = 0, l = valueTable.length; i < l; i++) {
93       //        IResourceDelta delta = (IResourceDelta) valueTable[i];
94       //        if (delta != null) {
95       //          IResource resource = delta.getResource();
96       //          int resourceType = resource.getType();
97       //          if (resourceType == IResource.FILE) {
98       //            switch (delta.getKind()) {
99       //              case IResourceDelta.ADDED :
100       //                if ((resource.getFileExtension() != null)
101       //                    && PHPFileUtil.isPHPFile((IFile) resource)) {
102       //                  // update indexfile for the project:
103       //// indexManager.addFile((IFile) resource);
104       //                }
105       //                break;
106       //              case IResourceDelta.CHANGED :
107       //                if ((resource.getFileExtension() != null)
108       //                    && PHPFileUtil.isPHPFile((IFile) resource)) {
109       //                  // update indexfile for the project:
110       //// indexManager.changeFile((IFile) resource);
111       //                }
112       //                break;
113       //              case IResourceDelta.REMOVED :
114       //                if ((resource.getFileExtension() != null)
115       //                    && PHPFileUtil.isPHPFile((IFile) resource)) {
116       //                  // update indexfile for the project:
117       //// indexManager.removeFile((IFile) resource);
118       //                }
119       //                break;
120       //            }
121       //          }
122       //          // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[])
123       //          // javaBuilder.binaryLocationsPerProject.get(keyTable[i]);
124       //          // if (classFoldersAndJars != null)
125       //          // if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return
126       //          // false;
127       //        }
128       //      }
129       notifier.updateProgressDelta(0.10f);
130       notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
131       addAffectedSourceFiles();
132       notifier.updateProgressDelta(0.05f);
133       this.compileLoop = 0;
134       float increment = 0.40f;
135       while (sourceFiles.size() > 0) { // added to in acceptResult
136         if (++this.compileLoop > MaxCompileLoop) {
137           if (PHPBuilder.DEBUG)
138             System.out.println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$
139           return false;
140         }
141         notifier.checkCancel();
142         SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()];
143         sourceFiles.toArray(allSourceFiles);
144         resetCollections();
145         workQueue.addAll(allSourceFiles);
146         notifier.setProgressPerCompilationUnit(increment / allSourceFiles.length);
147         increment = increment / 2;
148         compile(allSourceFiles);
149         //        removeSecondaryTypes();
150         addAffectedSourceFiles();
151       }
152       if (this.hasStructuralChanges && javaBuilder.javaProject.hasCycleMarker())
153         javaBuilder.mustPropagateStructuralChanges();
154     } catch (AbortIncrementalBuildException e) {
155       // abort the incremental build and let the batch builder handle the
156       // problem
157       if (PHPBuilder.DEBUG)
158         System.out.println("ABORTING incremental build... cannot find " + e.qualifiedTypeName + //$NON-NLS-1$
159             ". Could have been renamed inside its existing source file."); //$NON-NLS-1$
160       return false;
161     } catch (CoreException e) {
162       throw internalException(e);
163     } finally {
164       cleanUp();
165     }
166     return true;
167   }
168
169   protected void addAffectedSourceFiles() {
170     if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())
171       return;
172     // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
173     // just 'X'
174     //    char[][][] qualifiedNames = ReferenceCollection
175     //        .internQualifiedNames(qualifiedStrings);
176     // if a well known qualified name was found then we can skip over these
177     //    if (qualifiedNames.length < qualifiedStrings.size())
178     //      qualifiedNames = null;
179     //    char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
180     // if a well known name was found then we can skip over these
181     //    if (simpleNames.length < simpleStrings.size())
182     //      simpleNames = null;
183     //    Object[] keyTable = newState.references.keyTable;
184     //    Object[] valueTable = newState.references.valueTable;
185     //    next : for (int i = 0, l = valueTable.length; i < l; i++) {
186     //      ReferenceCollection refs = (ReferenceCollection) valueTable[i];
187     //      if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
188     //        String typeLocator = (String) keyTable[i];
189     //        IFile file = javaBuilder.currentProject.getFile(typeLocator);
190     //        if (file.exists()) {
191     //          ClasspathMultiDirectory md = sourceLocations[0];
192     //          if (sourceLocations.length > 1) {
193     //            IPath sourceFileFullPath = file.getFullPath();
194     //            for (int j = 0, m = sourceLocations.length; j < m; j++) {
195     //              if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(
196     //                  sourceFileFullPath)) {
197     //                md = sourceLocations[j];
198     //                if (md.exclusionPatterns == null
199     //                    || !ProjectPrefUtil.isExcluded(file, md.exclusionPatterns))
200     //                  break;
201     //              }
202     //            }
203     //          }
204     //          SourceFile sourceFile = new SourceFile(file, md, encoding);
205     //          if (sourceFiles.contains(sourceFile))
206     //            continue next;
207     //          if (compiledAllAtOnce && previousSourceFiles != null
208     //              && previousSourceFiles.contains(sourceFile))
209     //            continue next; // can skip previously compiled files since already
210     //          // saw hierarchy related problems
211     //          if (PHPBuilder.DEBUG)
212     //            System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
213     //          // // update indexfile for the project:
214     //          sourceFiles.add(sourceFile);
215     //        }
216     //      }
217     //    }
218   }
219
220   protected void addDependentsOf(IPath path, boolean hasStructuralChanges) {
221     if (hasStructuralChanges) {
222       newState.tagAsStructurallyChanged();
223       this.hasStructuralChanges = true;
224     }
225     // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
226     // just 'X'
227     path = path.setDevice(null);
228     String packageName = path.removeLastSegments(1).toString();
229     if (!qualifiedStrings.contains(packageName))
230       qualifiedStrings.add(packageName);
231     String typeName = path.lastSegment();
232     int memberIndex = typeName.indexOf('$');
233     if (memberIndex > 0)
234       typeName = typeName.substring(0, memberIndex);
235     if (!simpleStrings.contains(typeName)) {
236       if (PHPBuilder.DEBUG)
237         System.out.println("  will look for dependents of " //$NON-NLS-1$
238             + typeName + " in " + packageName); //$NON-NLS-1$
239       simpleStrings.add(typeName);
240     }
241   }
242
243   protected void cleanUp() {
244     super.cleanUp();
245     this.sourceFiles = null;
246     this.previousSourceFiles = null;
247     this.qualifiedStrings = null;
248     this.simpleStrings = null;
249     this.secondaryTypesToRemove = null;
250     this.hasStructuralChanges = false;
251     this.compileLoop = 0;
252   }
253
254   //protected boolean findAffectedSourceFiles(IResourceDelta delta,
255   // ClasspathLocation[] classFoldersAndJars) {
256   //    for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
257   //            ClasspathLocation bLocation = classFoldersAndJars[i];
258   //            // either a .class file folder or a zip/jar file
259   //            if (bLocation != null) { // skip unchanged output folder
260   //                    IPath p = bLocation.getProjectRelativePath();
261   //                    if (p != null) {
262   //                            IResourceDelta binaryDelta = delta.findMember(p);
263   //                            if (binaryDelta != null) {
264   //                                    if (bLocation instanceof ClasspathJar) {
265   //                                            if (JavaBuilder.DEBUG)
266   //                                                    System.out.println("ABORTING incremental build... found delta to jar/zip
267   // file"); //$NON-NLS-1$
268   //                                            return false; // do full build since jar file was changed (added/removed
269   // were caught as classpath change)
270   //                                    }
271   //                                    if (binaryDelta.getKind() == IResourceDelta.ADDED || binaryDelta.getKind()
272   // == IResourceDelta.REMOVED) {
273   //                                            if (JavaBuilder.DEBUG)
274   //                                                    System.out.println("ABORTING incremental build... found added/removed
275   // binary folder"); //$NON-NLS-1$
276   //                                            return false; // added/removed binary folder should not make it here
277   // (classpath change), but handle anyways
278   //                                    }
279   //                                    int segmentCount = binaryDelta.getFullPath().segmentCount();
280   //                                    IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class
281   // files from class folder
282   //                                    for (int j = 0, m = children.length; j < m; j++)
283   //                                            findAffectedSourceFiles(children[j], segmentCount);
284   //                                    notifier.checkCancel();
285   //                            }
286   //                    }
287   //            }
288   //    }
289   //    return true;
290   //}
291   protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount) {
292     // When a package becomes a type or vice versa, expect 2 deltas,
293     // one on the folder & one on the class file
294     IResource resource = binaryDelta.getResource();
295     switch (resource.getType()) {
296     case IResource.FOLDER:
297       switch (binaryDelta.getKind()) {
298       case IResourceDelta.ADDED:
299       case IResourceDelta.REMOVED:
300         IPath packagePath = resource.getFullPath().removeFirstSegments(segmentCount);
301         String packageName = packagePath.toString();
302         if (binaryDelta.getKind() == IResourceDelta.ADDED) {
303           // see if any known source file is from the same package...
304           // classpath already includes new package
305           //              if (!newState.isKnownPackage(packageName)) {
306           //                if (PHPBuilder.DEBUG)
307           //                  System.out.println("Found added package " + packageName); //$NON-NLS-1$
308           //                addDependentsOf(packagePath, false);
309           //                return;
310           //              }
311           if (PHPBuilder.DEBUG)
312             System.out.println("Skipped dependents of added package " + packageName); //$NON-NLS-1$
313         } else {
314           // see if the package still exists on the classpath
315           //                                            if (!nameEnvironment.isPackage(packageName)) {
316           //                                                    if (JavaBuilder.DEBUG)
317           //                                                            System.out.println("Found removed package " + packageName);
318           // //$NON-NLS-1$
319           //                                                    addDependentsOf(packagePath, false);
320           //                                                    return;
321           //                                            }
322           if (PHPBuilder.DEBUG)
323             System.out.println("Skipped dependents of removed package " + packageName); //$NON-NLS-1$
324         }
325       // fall thru & traverse the sub-packages and .class files
326       case IResourceDelta.CHANGED:
327         IResourceDelta[] children = binaryDelta.getAffectedChildren();
328         for (int i = 0, l = children.length; i < l; i++)
329           findAffectedSourceFiles(children[i], segmentCount);
330       }
331       return;
332     case IResource.FILE:
333     //                  if (ProjectPrefUtil.isClassFileName(resource.getName())) {
334     //                          IPath typePath =
335     // resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
336     //                          switch (binaryDelta.getKind()) {
337     //                                  case IResourceDelta.ADDED :
338     //                                  case IResourceDelta.REMOVED :
339     //                                          if (JavaBuilder.DEBUG)
340     //                                                  System.out.println("Found added/removed class file " + typePath);
341     // //$NON-NLS-1$
342     //                                          addDependentsOf(typePath, false);
343     //                                          return;
344     //                                  case IResourceDelta.CHANGED :
345     //                                          if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0)
346     //                                                  return; // skip it since it really isn't changed
347     //                                          if (JavaBuilder.DEBUG)
348     //                                                  System.out.println("Found changed class file " + typePath);
349     // //$NON-NLS-1$
350     //                                          addDependentsOf(typePath, false);
351     //                          }
352     //                          return;
353     //                  }
354     }
355   }
356
357   protected boolean findSourceFiles(IResourceDelta delta) throws CoreException {
358     for (int i = 0, l = sourceLocations.length; i < l; i++) {
359       ClasspathMultiDirectory md = sourceLocations[i];
360       if (md.sourceFolder.equals(javaBuilder.currentProject)) {
361         // skip nested source & output folders when the project is a source
362         // folder
363         int segmentCount = delta.getFullPath().segmentCount();
364         IResourceDelta[] children = delta.getAffectedChildren();
365         for (int j = 0, m = children.length; j < m; j++)
366           if (!isExcludedFromProject(children[j].getFullPath()))
367             findSourceFiles(children[j], md, segmentCount);
368       } else {
369         IResourceDelta sourceDelta = delta.findMember(md.sourceFolder.getProjectRelativePath());
370         if (sourceDelta != null) {
371           if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
372             if (PHPBuilder.DEBUG)
373               System.out.println("ABORTING incremental build... found removed source folder"); //$NON-NLS-1$
374             return false; // removed source folder should not make it here, but
375             // handle anyways (ADDED is supported)
376           }
377           int segmentCount = sourceDelta.getFullPath().segmentCount();
378           IResourceDelta[] children = sourceDelta.getAffectedChildren();
379           for (int j = 0, m = children.length; j < m; j++)
380             findSourceFiles(children[j], md, segmentCount);
381         }
382       }
383       notifier.checkCancel();
384     }
385     return true;
386   }
387
388   protected void findSourceFiles(IResourceDelta sourceDelta, ClasspathMultiDirectory md, int segmentCount) throws CoreException {
389     // When a package becomes a type or vice versa, expect 2 deltas,
390     // one on the folder & one on the source file
391     IResource resource = sourceDelta.getResource();
392     if (md.exclusionPatterns != null && Util.isExcluded(resource, md.exclusionPatterns))
393       return;
394     switch (resource.getType()) {
395     case IResource.FOLDER:
396       switch (sourceDelta.getKind()) {
397       case IResourceDelta.ADDED:
398         IPath addedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount);
399         // createFolder(addedPackagePath, md.binaryFolder); // ensure package
400         // exists in the
401         // output folder
402         // add dependents even when the package thinks it exists to be on
403         // the safe side
404         if (PHPBuilder.DEBUG)
405           System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$
406         addDependentsOf(addedPackagePath, true);
407       // fall thru & collect all the source files
408       case IResourceDelta.CHANGED:
409         IResourceDelta[] children = sourceDelta.getAffectedChildren();
410         for (int i = 0, l = children.length; i < l; i++)
411           findSourceFiles(children[i], md, segmentCount);
412         return;
413       case IResourceDelta.REMOVED:
414         IPath removedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount);
415         if (sourceLocations.length > 1) {
416           for (int i = 0, l = sourceLocations.length; i < l; i++) {
417             if (sourceLocations[i].sourceFolder.getFolder(removedPackagePath).exists()) {
418               // only a package fragment was removed, same as removing
419               // multiple source files
420               //                  createFolder(removedPackagePath, md.binaryFolder); // ensure
421               // package
422               // exists
423               // in the
424               // output
425               // folder
426               IResourceDelta[] removedChildren = sourceDelta.getAffectedChildren();
427               for (int j = 0, m = removedChildren.length; j < m; j++)
428                 findSourceFiles(removedChildren[j], md, segmentCount);
429               return;
430             }
431           }
432         }
433         //            IFolder removedPackageFolder = md.binaryFolder
434         //                .getFolder(removedPackagePath);
435         //            if (removedPackageFolder.exists())
436         //              removedPackageFolder.delete(IResource.FORCE, null);
437         // add dependents even when the package thinks it does not exist to
438         // be on the safe side
439         if (PHPBuilder.DEBUG)
440           System.out.println("Found removed package " + removedPackagePath); //$NON-NLS-1$
441         addDependentsOf(removedPackagePath, true);
442         newState.removePackage(sourceDelta);
443       }
444       return;
445     case IResource.FILE:
446       String resourceName = resource.getName();
447       if (net.sourceforge.phpdt.internal.compiler.util.Util.isJavaFileName(resourceName)) {
448         IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
449         String typeLocator = resource.getProjectRelativePath().toString();
450         switch (sourceDelta.getKind()) {
451         case IResourceDelta.ADDED:
452           if (PHPBuilder.DEBUG)
453             System.out.println("Compile this added source file " + 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
457           //                // dependents
458           //                // results
459           //                // in
460           //                // 2
461           //                // duplicate
462           //                // errors
463           //                if (PHPBuilder.DEBUG)
464           //                  System.out.println("Found added source file " + typeName); //$NON-NLS-1$
465           //                addDependentsOf(typePath, true);
466           //              }
467           return;
468         case IResourceDelta.REMOVED:
469           //              char[][] definedTypeNames = newState
470           //                  .getDefinedTypeNamesFor(typeLocator);
471           //              if (definedTypeNames == null) { // defined a single type matching
472           //                // typePath
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
478           //                  // be recompiled
479           //                  // if the target file is a non-java resource, then markers
480           //                  // are removed
481           //                  // see bug 2857
482           //                  IResource movedFile = javaBuilder.workspaceRoot
483           //                      .getFile(sourceDelta.getMovedToPath());
484           //                  PHPBuilder.removeProblemsAndTasksFor(movedFile);
485           //                }
486           //              } else {
487           if (PHPBuilder.DEBUG)
488             System.out.println("Found removed source file " + typePath.toString()); //$NON-NLS-1$
489           addDependentsOf(typePath, true); // add dependents of the
490           // source file since it may be
491           // involved in a name
492           // collision
493           //                if (definedTypeNames.length > 0) { // skip it if it failed to
494           //                  // successfully define a
495           //                  // type
496           //                  IPath packagePath = typePath.removeLastSegments(1);
497           //                  for (int i = 0, l = definedTypeNames.length; i < l; i++)
498           //                    removeClassFile(packagePath.append(new String(
499           //                        definedTypeNames[i])), md.binaryFolder);
500           //                }
501           //              }
502           //              newState.removeLocator(typeLocator);
503           return;
504         case IResourceDelta.CHANGED:
505           if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
506             return; // skip it since it really isn't changed
507           if (PHPBuilder.DEBUG)
508             System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$
509           sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
510         }
511         return;
512         //                      } else if (ProjectPrefUtil.isClassFileName(resourceName)) {
513         //                              return; // skip class files
514       } else if (md.hasIndependentOutputFolder) {
515         if (javaBuilder.filterExtraResource(resource))
516           return;
517         // copy all other resource deltas to the output folder
518         IPath resourcePath = resource.getFullPath().removeFirstSegments(segmentCount);
519         //          IResource outputFile = md.binaryFolder.getFile(resourcePath);
520         switch (sourceDelta.getKind()) {
521         case IResourceDelta.ADDED:
522           //              if (outputFile.exists()) {
523           //                if (PHPBuilder.DEBUG)
524           //                  System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
525           //                outputFile.delete(IResource.FORCE, null);
526           //              }
527           if (PHPBuilder.DEBUG)
528             System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$
529             //              createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
530           // package
531           // exists
532           // in
533           // the
534           // output
535           // folder
536           //              resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
537           //              outputFile.setDerived(true);
538           return;
539         case IResourceDelta.REMOVED:
540           //              if (outputFile.exists()) {
541           //                if (PHPBuilder.DEBUG)
542           //                  System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$
543           //                outputFile.delete(IResource.FORCE, null);
544           //              }
545           return;
546         case IResourceDelta.CHANGED:
547           if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0)
548             return; // skip it since it really isn't changed
549             //              if (outputFile.exists()) {
550             //                if (PHPBuilder.DEBUG)
551             //                  System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
552             //                outputFile.delete(IResource.FORCE, null);
553             //              }
554           if (PHPBuilder.DEBUG)
555             System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$
556         //  createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
557         // package
558         // exists
559         // in
560         // the
561         // output
562         // folder
563         //              resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
564         //              outputFile.setDerived(true);
565         }
566         return;
567       }
568     }
569   }
570
571   protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames,
572       ArrayList duplicateTypeNames) throws CoreException {
573     //    char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator);
574     //    if (previousTypeNames == null)
575     //      previousTypeNames = new char[][]{mainTypeName};
576     //    IPath packagePath = null;
577     //    next : for (int i = 0, l = previousTypeNames.length; i < l; i++) {
578     //      char[] previous = previousTypeNames[i];
579     //      for (int j = 0, m = definedTypeNames.size(); j < m; j++)
580     //        if (CharOperation.equals(previous, (char[]) definedTypeNames.get(j)))
581     //          continue next;
582     //      SourceFile sourceFile = (SourceFile) result.getCompilationUnit();
583     //      if (packagePath == null) {
584     //        int count = sourceFile.sourceLocation.sourceFolder.getFullPath()
585     //            .segmentCount();
586     //        packagePath = sourceFile.resource.getFullPath().removeFirstSegments(
587     //            count).removeLastSegments(1);
588     //      }
589     //      if (secondaryTypesToRemove == null)
590     //        this.secondaryTypesToRemove = new SimpleLookupTable();
591     //      ArrayList types = (ArrayList) secondaryTypesToRemove
592     //          .get(sourceFile.sourceLocation.binaryFolder);
593     //      if (types == null)
594     //        types = new ArrayList(definedTypeNames.size());
595     //      types.add(packagePath.append(new String(previous)));
596     //      secondaryTypesToRemove.put(sourceFile.sourceLocation.binaryFolder, types);
597     //    }
598     //  super.finishedWith(sourceLocator, result, mainTypeName,
599     // definedTypeNames, duplicateTypeNames);
600   }
601
602   //  protected void removeClassFile(IPath typePath, IContainer outputFolder)
603   //      throws CoreException {
604   //    if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type
605   //      newState.removeQualifiedTypeName(typePath.toString());
606   //      // add dependents even when the type thinks it does not exist to be on
607   //      // the safe side
608   //      if (PHPBuilder.DEBUG)
609   //        System.out.println("Found removed type " + typePath); //$NON-NLS-1$
610   //      addDependentsOf(typePath, true); // when member types are removed, their
611   //      // enclosing type is structurally
612   //      // changed
613   //    }
614   //    IFile classFile = outputFolder.getFile(typePath
615   //        .addFileExtension(PHPBuilder.CLASS_EXTENSION));
616   //    if (classFile.exists()) {
617   //      if (PHPBuilder.DEBUG)
618   //        System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$
619   //      classFile.delete(IResource.FORCE, null);
620   //    }
621   //  }
622   //  protected void removeSecondaryTypes() throws CoreException {
623   //    if (secondaryTypesToRemove != null) { // delayed deleting secondary types
624   //      // until the end of the compile loop
625   //      Object[] keyTable = secondaryTypesToRemove.keyTable;
626   //      Object[] valueTable = secondaryTypesToRemove.valueTable;
627   //      for (int i = 0, l = keyTable.length; i < l; i++) {
628   //        IContainer outputFolder = (IContainer) keyTable[i];
629   //        if (outputFolder != null) {
630   //          ArrayList paths = (ArrayList) valueTable[i];
631   //          for (int j = 0, m = paths.size(); j < m; j++)
632   //            removeClassFile((IPath) paths.get(j), outputFolder);
633   //        }
634   //      }
635   //      this.secondaryTypesToRemove = null;
636   //      if (previousSourceFiles != null && previousSourceFiles.size() > 1)
637   //        this.previousSourceFiles = null; // cannot optimize recompile case when
638   //      // a secondary type is deleted
639   //    }
640   //  }
641   protected void resetCollections() {
642     previousSourceFiles = sourceFiles.isEmpty() ? null : (ArrayList) sourceFiles.clone();
643     sourceFiles.clear();
644     qualifiedStrings.clear();
645     simpleStrings.clear();
646     workQueue.clear();
647   }
648
649   protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
650     IMarker[] markers = PHPBuilder.getProblemsFor(sourceFile.resource);
651     IProblem[] problems = result.getProblems();
652     if (problems == null && markers.length == 0)
653       return;
654
655     //  axelcl start insert - calculate line numbers
656     if (problems != null) {
657       for (int i = 0; i < problems.length; i++) {
658         if (problems[i].getSourceLineNumber() == 1) {
659           problems[i].setSourceLineNumber(ProblemHandler.searchLineNumber(result.lineSeparatorPositions, problems[i]
660               .getSourceStart()));
661         }
662       }
663     }
664     //axelcl end insert
665
666     notifier.updateProblemCounts(markers, problems);
667     PHPBuilder.removeProblemsFor(sourceFile.resource);
668     storeProblemsFor(sourceFile, problems);
669   }
670
671   protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
672     IMarker[] markers = PHPBuilder.getTasksFor(sourceFile.resource);
673     IProblem[] tasks = result.getTasks();
674     if (tasks == null && markers.length == 0)
675       return;
676     PHPBuilder.removeTasksFor(sourceFile.resource);
677     storeTasksFor(sourceFile, tasks);
678   }
679
680   //protected void writeClassFileBytes(byte[] bytes, IFile file, String
681   // qualifiedFileName, boolean isSecondaryType) throws CoreException {
682   //    // Before writing out the class file, compare it to the previous file
683   //    // If structural changes occured then add dependent source files
684   //    if (file.exists()) {
685   //            if (writeClassFileCheck(file, qualifiedFileName, bytes)) {
686   //                    if (JavaBuilder.DEBUG)
687   //                            System.out.println("Writing changed class file " +
688   // file.getName());//$NON-NLS-1$
689   //                    file.setContents(new ByteArrayInputStream(bytes), true, false, null);
690   //                    if (!file.isDerived())
691   //                            file.setDerived(true);
692   //            } else if (JavaBuilder.DEBUG) {
693   //                    System.out.println("Skipped over unchanged class file " +
694   // file.getName());//$NON-NLS-1$
695   //            }
696   //    } else {
697   //            if (isSecondaryType)
698   //                    addDependentsOf(new Path(qualifiedFileName), true); // new secondary type
699   //            if (JavaBuilder.DEBUG)
700   //                    System.out.println("Writing new class file " +
701   // file.getName());//$NON-NLS-1$
702   //            file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
703   //            file.setDerived(true);
704   //    }
705   //}
706   //protected boolean writeClassFileCheck(IFile file, String fileName, byte[]
707   // newBytes) throws CoreException {
708   //    try {
709   //            byte[] oldBytes = ProjectPrefUtil.getResourceContentsAsByteArray(file);
710   //            if (this.compileLoop > 1) { // only optimize files which were recompiled
711   // during the dependent pass, see 33990
712   //                    notEqual : if (newBytes.length == oldBytes.length) {
713   //                            for (int i = newBytes.length; --i >= 0;)
714   //                                    if (newBytes[i] != oldBytes[i]) break notEqual;
715   //                            return false; // bytes are identical so skip them
716   //                    }
717   //            }
718   //            IPath location = file.getLocation();
719   //            if (location == null) return false; // unable to determine location of
720   // this class file
721   //            ClassFileReader reader = new ClassFileReader(oldBytes,
722   // location.toString().toCharArray());
723   //            // ignore local types since they're only visible inside a single method
724   //            if (!(reader.isLocal() || reader.isAnonymous()) &&
725   // reader.hasStructuralChanges(newBytes)) {
726   //                    if (JavaBuilder.DEBUG)
727   //                            System.out.println("Type has structural changes " + fileName);
728   // //$NON-NLS-1$
729   //                    addDependentsOf(new Path(fileName), true);
730   //            }
731   //    } catch (ClassFormatException e) {
732   //            addDependentsOf(new Path(fileName), true);
733   //    }
734   //    return true;
735   //}
736   public String toString() {
737     return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
738   }
739   /*
740    * Debug helper
741    * 
742    * static void dump(IResourceDelta delta) { StringBuffer buffer = new StringBuffer(); IPath path = delta.getFullPath(); for (int i =
743    * path.segmentCount(); --i > 0;) buffer.append(" "); switch (delta.getKind()) { case IResourceDelta.ADDED: buffer.append('+');
744    * break; case IResourceDelta.REMOVED: buffer.append('-'); break; case IResourceDelta.CHANGED: '); break; case
745    * IResourceDelta.NO_CHANGE: buffer.append('='); break; default: buffer.append('?'); break; } buffer.append(path);
746    * System.out.println(buffer.toString()); IResourceDelta[] children = delta.getAffectedChildren(); for (int i = 0, l =
747    * children.length; i < l; i++) dump(children[i]); }
748    */
749 }