1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.core.builder;
 
  12 import java.util.ArrayList;
 
  14 import net.sourceforge.phpdt.core.compiler.IProblem;
 
  15 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
 
  16 import net.sourceforge.phpdt.internal.compiler.problem.ProblemHandler;
 
  17 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
 
  18 import net.sourceforge.phpdt.internal.core.util.Util;
 
  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;
 
  28  * The incremental image builder
 
  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
 
  41   protected IncrementalImageBuilder(PHPBuilder 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;
 
  52   public boolean build(SimpleLookupTable deltas) {
 
  54     // walk this project's deltas, find changed source files
 
  55     // walk prereq projects' deltas, find changed class files & add affected
 
  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
 
  65       System.out.println("INCREMENTAL build"); //$NON-NLS-1$
 
  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));
 
  74         if (!findSourceFiles(sourceDelta))
 
  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);
 
  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);
 
 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);
 
 112 //          //                          ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[])
 
 113 //          // javaBuilder.binaryLocationsPerProject.get(keyTable[i]);
 
 114 //          //                          if (classFoldersAndJars != null)
 
 115 //          //                                  if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return
 
 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)
 
 129                 .println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$
 
 132         notifier.checkCancel();
 
 133         SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()];
 
 134         sourceFiles.toArray(allSourceFiles);
 
 136         workQueue.addAll(allSourceFiles);
 
 137         notifier.setProgressPerCompilationUnit(increment
 
 138             / allSourceFiles.length);
 
 139         increment = increment / 2;
 
 140         compile(allSourceFiles);
 
 141 //        removeSecondaryTypes();
 
 142         addAffectedSourceFiles();
 
 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
 
 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$
 
 154     } catch (CoreException e) {
 
 155       throw internalException(e);
 
 161   protected void addAffectedSourceFiles() {
 
 162     if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())
 
 164     // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
 
 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))
 
 196 //          SourceFile sourceFile = new SourceFile(file, md, encoding);
 
 197 //          if (sourceFiles.contains(sourceFile))
 
 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);
 
 211   protected void addDependentsOf(IPath path, boolean hasStructuralChanges) {
 
 212     if (hasStructuralChanges) {
 
 213       newState.tagAsStructurallyChanged();
 
 214       this.hasStructuralChanges = true;
 
 216     // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are
 
 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('$');
 
 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);
 
 233   protected void 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;
 
 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();
 
 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)
 
 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
 
 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();
 
 280   protected void findAffectedSourceFiles(IResourceDelta binaryDelta,
 
 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(
 
 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);
 
 302               if (PHPBuilder.DEBUG)
 
 303                 System.out.println("Skipped dependents of added package "
 
 304                     + packageName); //$NON-NLS-1$
 
 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);
 
 311               //                                                        addDependentsOf(packagePath, false);
 
 314               if (PHPBuilder.DEBUG)
 
 315                 System.out.println("Skipped dependents of removed package "
 
 316                     + packageName); //$NON-NLS-1$
 
 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);
 
 325       case IResource.FILE :
 
 326     //                  if (ProjectPrefUtil.isClassFileName(resource.getName())) {
 
 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);
 
 335     //                                          addDependentsOf(typePath, false);
 
 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);
 
 343     //                                          addDependentsOf(typePath, false);
 
 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
 
 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);
 
 361         IResourceDelta sourceDelta = delta.findMember(md.sourceFolder
 
 362             .getProjectRelativePath());
 
 363         if (sourceDelta != null) {
 
 364           if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
 
 365             if (PHPBuilder.DEBUG)
 
 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)
 
 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);
 
 377       notifier.checkCancel();
 
 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))
 
 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
 
 398             // add dependents even when the package thinks it exists to be on
 
 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);
 
 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
 
 424                   IResourceDelta[] removedChildren = sourceDelta
 
 425                       .getAffectedChildren();
 
 426                   for (int j = 0, m = removedChildren.length; j < m; j++)
 
 427                     findSourceFiles(removedChildren[j], md, segmentCount);
 
 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);
 
 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
 
 464 //                if (PHPBuilder.DEBUG)
 
 465 //                  System.out.println("Found added source file " + typeName); //$NON-NLS-1$
 
 466 //                addDependentsOf(typePath, true);
 
 469             case IResourceDelta.REMOVED :
 
 470 //              char[][] definedTypeNames = newState
 
 471 //                  .getDefinedTypeNamesFor(typeLocator);
 
 472 //              if (definedTypeNames == null) { // defined a single type matching
 
 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
 
 480 //                  // if the target file is a non-java resource, then markers
 
 483 //                  IResource movedFile = javaBuilder.workspaceRoot
 
 484 //                      .getFile(sourceDelta.getMovedToPath());
 
 485 //                  PHPBuilder.removeProblemsAndTasksFor(movedFile);
 
 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
 
 495 //                if (definedTypeNames.length > 0) { // skip it if it failed to
 
 496 //                  // successfully define a
 
 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);
 
 504 //              newState.removeLocator(typeLocator);
 
 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));
 
 515           //                    } else if (ProjectPrefUtil.isClassFileName(resourceName)) {
 
 516           //                            return; // skip class files
 
 517         } else if (md.hasIndependentOutputFolder) {
 
 518           if (javaBuilder.filterExtraResource(resource))
 
 520           // copy all other resource deltas to the output folder
 
 521           IPath resourcePath = resource.getFullPath().removeFirstSegments(
 
 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);
 
 531               if (PHPBuilder.DEBUG)
 
 532                 System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$
 
 533 //              createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
 
 540 //              resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
 
 541 //              outputFile.setDerived(true);
 
 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);
 
 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);
 
 558               if (PHPBuilder.DEBUG)
 
 559                 System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$
 
 560             //  createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure
 
 567 //              resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
 
 568 //              outputFile.setDerived(true);
 
 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)))
 
 586 //      SourceFile sourceFile = (SourceFile) result.getCompilationUnit();
 
 587 //      if (packagePath == null) {
 
 588 //        int count = sourceFile.sourceLocation.sourceFolder.getFullPath()
 
 590 //        packagePath = sourceFile.resource.getFullPath().removeFirstSegments(
 
 591 //            count).removeLastSegments(1);
 
 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);
 
 602     //  super.finishedWith(sourceLocator, result, mainTypeName,
 
 603     // definedTypeNames, duplicateTypeNames);
 
 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
 
 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
 
 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);
 
 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);
 
 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
 
 644   protected void resetCollections() {
 
 645     previousSourceFiles = sourceFiles.isEmpty()
 
 647         : (ArrayList) sourceFiles.clone();
 
 649     qualifiedStrings.clear();
 
 650     simpleStrings.clear();
 
 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)
 
 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()));
 
 669     notifier.updateProblemCounts(markers, problems);
 
 670     PHPBuilder.removeProblemsFor(sourceFile.resource);
 
 671     storeProblemsFor(sourceFile, problems);
 
 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)
 
 679     PHPBuilder.removeTasksFor(sourceFile.resource);
 
 680     storeTasksFor(sourceFile, tasks);
 
 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$
 
 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);
 
 708   //protected boolean writeClassFileCheck(IFile file, String fileName, byte[]
 
 709   // newBytes) throws CoreException {
 
 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
 
 720   //            IPath location = file.getLocation();
 
 721   //            if (location == null) return false; // unable to determine location of
 
 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);
 
 731   //                    addDependentsOf(new Path(fileName), true);
 
 733   //    } catch (ClassFormatException e) {
 
 734   //            addDependentsOf(new Path(fileName), true);
 
 738   public String toString() {
 
 739     return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
 
 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]); }