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