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