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