From 4849b0415316698eca02d421be394d57b37c172e Mon Sep 17 00:00:00 2001 From: khartlage Date: Wed, 3 Mar 2004 20:54:32 +0000 Subject: [PATCH] added index manager to the new builder; "define" is no keyword anymore --- .../phpdt/core/compiler/ITerminalSymbols.java | 2 +- .../phpdt/internal/compiler/parser/Parser.java | 65 +- .../phpdt/internal/compiler/parser/Scanner.java | 26 +- .../internal/core/builder/BatchImageBuilder.java | 3 + .../core/builder/IncrementalImageBuilder.java | 1333 +++++++++++--------- .../phpdt/internal/core/builder/PHPBuilder.java | 498 +++++--- .../phpeclipse/builder/IdentifierIndexManager.java | 277 +++-- 7 files changed, 1215 insertions(+), 989 deletions(-) diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java index 120f6b1..d9e97af 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java @@ -126,7 +126,7 @@ public interface ITerminalSymbols { public final static int TokenNamebreak = 1012; public final static int TokenNamecontinue = 1013; public final static int TokenNamereturn = 1014; - public final static int TokenNamedefine = 1015; +// public final static int TokenNamedefine = 1015; public final static int TokenNameinclude = 1016; public final static int TokenNameinclude_once = 1017; public final static int TokenNamerequire = 1018; diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java index dceae31..271c3d6 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java @@ -1222,38 +1222,38 @@ public class Parser //extends PHPParserSuperclass // getNextToken(); // } // return; - } else if (token == TokenNamedefine) { - getNextToken(); - if (token == TokenNameLPAREN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'define' keyword."); - } - expr(); - if (token == TokenNameCOMMA) { - getNextToken(); - } else { - throwSyntaxError("',' expected after first 'define' constant."); - } - expr(); - if (token == TokenNameCOMMA) { - getNextToken(); - expr(); - } - if (token == TokenNameRPAREN) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'define' statement."); - } - if (token == TokenNameSEMICOLON) { - getNextToken(); - } else { - if (token != TokenNameStopPHP) { - throwSyntaxError("';' expected after 'define' statement."); - } - getNextToken(); - } - return; +// } else if (token == TokenNamedefine) { +// getNextToken(); +// if (token == TokenNameLPAREN) { +// getNextToken(); +// } else { +// throwSyntaxError("'(' expected after 'define' keyword."); +// } +// expr(); +// if (token == TokenNameCOMMA) { +// getNextToken(); +// } else { +// throwSyntaxError("',' expected after first 'define' constant."); +// } +// expr(); +// if (token == TokenNameCOMMA) { +// getNextToken(); +// expr(); +// } +// if (token == TokenNameRPAREN) { +// getNextToken(); +// } else { +// throwSyntaxError("')' expected after 'define' statement."); +// } +// if (token == TokenNameSEMICOLON) { +// getNextToken(); +// } else { +// if (token != TokenNameStopPHP) { +// throwSyntaxError("';' expected after 'define' statement."); +// } +// getNextToken(); +// } +// return; } else if (token == TokenNamefunction) { MethodDeclaration methodDecl = new MethodDeclaration( this.compilationUnit.compilationResult); @@ -1431,6 +1431,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } else if (token == TokenNamefinal) { checkAndSetModifiers(AccFinal); + getNextToken(); if (token != TokenNameclass) { throwSyntaxError("Keyword 'class' expected after keyword 'final'."); } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java index f870539..83ca372 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java @@ -160,7 +160,7 @@ public class Scanner implements IScanner, ITerminalSymbols { public char[][] taskTags = null; public char[][] taskPriorities = null; - public static final boolean DEBUG = true; + public static final boolean DEBUG = false; public Scanner() { this(false, false); @@ -2664,7 +2664,7 @@ public class Scanner implements IScanner, ITerminalSymbols { return TokenNameIdentifier; } - case 'd' : //define declare default do die + case 'd' : // declare default do die // TODO delete define ==> no keyword ! switch (length) { case 2 : @@ -2672,15 +2672,15 @@ public class Scanner implements IScanner, ITerminalSymbols { return TokenNamedo; else return TokenNameIdentifier; - case 6 : - if ((data[++index] == 'e') - && (data[++index] == 'f') - && (data[++index] == 'i') - && (data[++index] == 'n') - && (data[++index] == 'e')) - return TokenNamedefine; - else - return TokenNameIdentifier; +// case 6 : +// if ((data[++index] == 'e') +// && (data[++index] == 'f') +// && (data[++index] == 'i') +// && (data[++index] == 'n') +// && (data[++index] == 'e')) +// return TokenNamedefine; +// else +// return TokenNameIdentifier; case 7 : if ((data[++index] == 'e') && (data[++index] == 'c') @@ -3406,8 +3406,8 @@ public class Scanner implements IScanner, ITerminalSymbols { return "continue"; //$NON-NLS-1$ case TokenNamedefault : return "default"; //$NON-NLS-1$ - case TokenNamedefine : - return "define"; //$NON-NLS-1$ +// case TokenNamedefine : +// return "define"; //$NON-NLS-1$ case TokenNamedo : return "do"; //$NON-NLS-1$ case TokenNameecho : diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/BatchImageBuilder.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/BatchImageBuilder.java index 8743da1..2be5495 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/BatchImageBuilder.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/BatchImageBuilder.java @@ -15,6 +15,8 @@ import java.util.ArrayList; import net.sourceforge.phpdt.internal.core.JavaModelManager; import net.sourceforge.phpdt.internal.core.Util; import net.sourceforge.phpeclipse.PHPCore; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.builder.IdentifierIndexManager; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -66,6 +68,7 @@ public void build() { } protected void addAllSourceFiles(final ArrayList sourceFiles) throws CoreException { + for (int i = 0, l = sourceLocations.length; i < l; i++) { final ClasspathMultiDirectory sourceLocation = sourceLocations[i]; final char[][] exclusionPatterns = sourceLocation.exclusionPatterns; diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/IncrementalImageBuilder.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/IncrementalImageBuilder.java index 694bcd9..635ac56 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/IncrementalImageBuilder.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/IncrementalImageBuilder.java @@ -9,15 +9,15 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core.builder; - import java.util.ArrayList; - import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.compiler.IProblem; import net.sourceforge.phpdt.internal.compiler.CompilationResult; import net.sourceforge.phpdt.internal.core.Util; import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable; - +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.builder.IdentifierIndexManager; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -26,624 +26,719 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; - /** * The incremental image builder */ public class IncrementalImageBuilder extends AbstractImageBuilder { - -protected ArrayList sourceFiles; -protected ArrayList previousSourceFiles; -protected ArrayList qualifiedStrings; -protected ArrayList simpleStrings; -protected SimpleLookupTable secondaryTypesToRemove; -protected boolean hasStructuralChanges; -protected int compileLoop; - -public static int MaxCompileLoop = 5; // perform a full build if it takes more than ? incremental compile loops - -protected IncrementalImageBuilder(PHPBuilder javaBuilder) { - super(javaBuilder); - this.nameEnvironment.isIncrementalBuild = true; - this.newState.copyFrom(javaBuilder.lastState); - - this.sourceFiles = new ArrayList(33); - this.previousSourceFiles = null; - this.qualifiedStrings = new ArrayList(33); - this.simpleStrings = new ArrayList(33); - this.hasStructuralChanges = false; - this.compileLoop = 0; -} - -public boolean build(SimpleLookupTable deltas) { - // initialize builder - // walk this project's deltas, find changed source files - // walk prereq projects' deltas, find changed class files & add affected source files - // use the build state # to skip the deltas for certain prereq projects - // ignore changed zip/jar files since they caused a full build - // compile the source files & acceptResult() - // compare the produced class files against the existing ones on disk - // recompile all dependent source files of any type with structural changes or new/removed secondary type - // keep a loop counter to abort & perform a full build - - if (PHPBuilder.DEBUG) - System.out.println("INCREMENTAL build"); //$NON-NLS-1$ - - try { - resetCollections(); - - notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$ - IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject); - if (sourceDelta != null) - if (!findSourceFiles(sourceDelta)) return false; - notifier.updateProgressDelta(0.10f); - - Object[] keyTable = deltas.keyTable; - Object[] valueTable = deltas.valueTable; - for (int i = 0, l = valueTable.length; i < l; i++) { - IResourceDelta delta = (IResourceDelta) valueTable[i]; - if (delta != null) { -// ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) javaBuilder.binaryLocationsPerProject.get(keyTable[i]); -// if (classFoldersAndJars != null) -// if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return false; - } - } - notifier.updateProgressDelta(0.10f); - - notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$ - addAffectedSourceFiles(); - notifier.updateProgressDelta(0.05f); - - this.compileLoop = 0; - float increment = 0.40f; - while (sourceFiles.size() > 0) { // added to in acceptResult - if (++this.compileLoop > MaxCompileLoop) { - if (PHPBuilder.DEBUG) - System.out.println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$ - return false; - } - notifier.checkCancel(); - - SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()]; - sourceFiles.toArray(allSourceFiles); - resetCollections(); - - workQueue.addAll(allSourceFiles); - notifier.setProgressPerCompilationUnit(increment / allSourceFiles.length); - increment = increment / 2; - compile(allSourceFiles); - removeSecondaryTypes(); - addAffectedSourceFiles(); - } - if (this.hasStructuralChanges && javaBuilder.javaProject.hasCycleMarker()) - javaBuilder.mustPropagateStructuralChanges(); - } catch (AbortIncrementalBuildException e) { - // abort the incremental build and let the batch builder handle the problem - if (PHPBuilder.DEBUG) - System.out.println("ABORTING incremental build... cannot find " + e.qualifiedTypeName + //$NON-NLS-1$ - ". Could have been renamed inside its existing source file."); //$NON-NLS-1$ - return false; - } catch (CoreException e) { - throw internalException(e); - } finally { - cleanUp(); - } - return true; -} - -protected void addAffectedSourceFiles() { - if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty()) return; - - // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' - char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedStrings); - // if a well known qualified name was found then we can skip over these - if (qualifiedNames.length < qualifiedStrings.size()) - qualifiedNames = null; - char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings); - // if a well known name was found then we can skip over these - if (simpleNames.length < simpleStrings.size()) - simpleNames = null; - - Object[] keyTable = newState.references.keyTable; - Object[] valueTable = newState.references.valueTable; - next : for (int i = 0, l = valueTable.length; i < l; i++) { - ReferenceCollection refs = (ReferenceCollection) valueTable[i]; - if (refs != null && refs.includes(qualifiedNames, simpleNames)) { - String typeLocator = (String) keyTable[i]; - IFile file = javaBuilder.currentProject.getFile(typeLocator); - if (file.exists()) { - ClasspathMultiDirectory md = sourceLocations[0]; - if (sourceLocations.length > 1) { - IPath sourceFileFullPath = file.getFullPath(); - for (int j = 0, m = sourceLocations.length; j < m; j++) { - if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(sourceFileFullPath)) { - md = sourceLocations[j]; - if (md.exclusionPatterns == null || !Util.isExcluded(file, md.exclusionPatterns)) - break; - } - } - } - SourceFile sourceFile = new SourceFile(file, md, encoding); - if (sourceFiles.contains(sourceFile)) continue next; - if (compiledAllAtOnce && previousSourceFiles != null && previousSourceFiles.contains(sourceFile)) - continue next; // can skip previously compiled files since already saw hierarchy related problems - - if (PHPBuilder.DEBUG) - System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$ - sourceFiles.add(sourceFile); - } - } - } -} - -protected void addDependentsOf(IPath path, boolean hasStructuralChanges) { - if (hasStructuralChanges) { - newState.tagAsStructurallyChanged(); - this.hasStructuralChanges = true; - } - // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' - path = path.setDevice(null); - String packageName = path.removeLastSegments(1).toString(); - if (!qualifiedStrings.contains(packageName)) - qualifiedStrings.add(packageName); - String typeName = path.lastSegment(); - int memberIndex = typeName.indexOf('$'); - if (memberIndex > 0) - typeName = typeName.substring(0, memberIndex); - if (!simpleStrings.contains(typeName)) { - if (PHPBuilder.DEBUG) - System.out.println(" will look for dependents of " //$NON-NLS-1$ - + typeName + " in " + packageName); //$NON-NLS-1$ - simpleStrings.add(typeName); - } -} - -protected void cleanUp() { - super.cleanUp(); - - this.sourceFiles = null; - this.previousSourceFiles = null; - this.qualifiedStrings = null; - this.simpleStrings = null; - this.secondaryTypesToRemove = null; - this.hasStructuralChanges = false; - this.compileLoop = 0; -} - -//protected boolean findAffectedSourceFiles(IResourceDelta delta, ClasspathLocation[] classFoldersAndJars) { -// for (int i = 0, l = classFoldersAndJars.length; i < l; i++) { -// ClasspathLocation bLocation = classFoldersAndJars[i]; -// // either a .class file folder or a zip/jar file -// if (bLocation != null) { // skip unchanged output folder -// IPath p = bLocation.getProjectRelativePath(); -// if (p != null) { -// IResourceDelta binaryDelta = delta.findMember(p); -// if (binaryDelta != null) { -// if (bLocation instanceof ClasspathJar) { -// if (JavaBuilder.DEBUG) -// System.out.println("ABORTING incremental build... found delta to jar/zip file"); //$NON-NLS-1$ -// return false; // do full build since jar file was changed (added/removed were caught as classpath change) -// } -// if (binaryDelta.getKind() == IResourceDelta.ADDED || binaryDelta.getKind() == IResourceDelta.REMOVED) { -// if (JavaBuilder.DEBUG) -// System.out.println("ABORTING incremental build... found added/removed binary folder"); //$NON-NLS-1$ -// return false; // added/removed binary folder should not make it here (classpath change), but handle anyways -// } -// int segmentCount = binaryDelta.getFullPath().segmentCount(); -// IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class files from class folder -// for (int j = 0, m = children.length; j < m; j++) -// findAffectedSourceFiles(children[j], segmentCount); -// notifier.checkCancel(); -// } -// } -// } -// } -// return true; -//} - -protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount) { - // When a package becomes a type or vice versa, expect 2 deltas, - // one on the folder & one on the class file - IResource resource = binaryDelta.getResource(); - switch(resource.getType()) { - case IResource.FOLDER : - switch (binaryDelta.getKind()) { - case IResourceDelta.ADDED : - case IResourceDelta.REMOVED : - IPath packagePath = resource.getFullPath().removeFirstSegments(segmentCount); - String packageName = packagePath.toString(); - if (binaryDelta.getKind() == IResourceDelta.ADDED) { - // see if any known source file is from the same package... classpath already includes new package - if (!newState.isKnownPackage(packageName)) { - if (PHPBuilder.DEBUG) - System.out.println("Found added package " + packageName); //$NON-NLS-1$ - addDependentsOf(packagePath, false); - return; - } - if (PHPBuilder.DEBUG) - System.out.println("Skipped dependents of added package " + packageName); //$NON-NLS-1$ - } else { - // see if the package still exists on the classpath -// if (!nameEnvironment.isPackage(packageName)) { -// if (JavaBuilder.DEBUG) -// System.out.println("Found removed package " + packageName); //$NON-NLS-1$ -// addDependentsOf(packagePath, false); -// return; -// } - if (PHPBuilder.DEBUG) - System.out.println("Skipped dependents of removed package " + packageName); //$NON-NLS-1$ - } - // fall thru & traverse the sub-packages and .class files - case IResourceDelta.CHANGED : - IResourceDelta[] children = binaryDelta.getAffectedChildren(); - for (int i = 0, l = children.length; i < l; i++) - findAffectedSourceFiles(children[i], segmentCount); - } - return; - case IResource.FILE : -// if (Util.isClassFileName(resource.getName())) { -// IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension(); -// switch (binaryDelta.getKind()) { -// case IResourceDelta.ADDED : -// case IResourceDelta.REMOVED : -// if (JavaBuilder.DEBUG) -// System.out.println("Found added/removed class file " + typePath); //$NON-NLS-1$ -// addDependentsOf(typePath, false); -// return; -// case IResourceDelta.CHANGED : -// if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0) -// return; // skip it since it really isn't changed -// if (JavaBuilder.DEBUG) -// System.out.println("Found changed class file " + typePath); //$NON-NLS-1$ -// addDependentsOf(typePath, false); -// } -// return; -// } - } -} - -protected boolean findSourceFiles(IResourceDelta delta) throws CoreException { - for (int i = 0, l = sourceLocations.length; i < l; i++) { - ClasspathMultiDirectory md = sourceLocations[i]; - if (md.sourceFolder.equals(javaBuilder.currentProject)) { - // skip nested source & output folders when the project is a source folder - int segmentCount = delta.getFullPath().segmentCount(); - IResourceDelta[] children = delta.getAffectedChildren(); - for (int j = 0, m = children.length; j < m; j++) - if (!isExcludedFromProject(children[j].getFullPath())) - findSourceFiles(children[j], md, segmentCount); - } else { - IResourceDelta sourceDelta = delta.findMember(md.sourceFolder.getProjectRelativePath()); - - if (sourceDelta != null) { - if (sourceDelta.getKind() == IResourceDelta.REMOVED) { - if (PHPBuilder.DEBUG) - System.out.println("ABORTING incremental build... found removed source folder"); //$NON-NLS-1$ - return false; // removed source folder should not make it here, but handle anyways (ADDED is supported) - } - int segmentCount = sourceDelta.getFullPath().segmentCount(); - IResourceDelta[] children = sourceDelta.getAffectedChildren(); - for (int j = 0, m = children.length; j < m; j++) - findSourceFiles(children[j], md, segmentCount); - } - } - notifier.checkCancel(); - } - return true; -} - -protected void findSourceFiles(IResourceDelta sourceDelta, ClasspathMultiDirectory md, int segmentCount) throws CoreException { - // When a package becomes a type or vice versa, expect 2 deltas, - // one on the folder & one on the source file - IResource resource = sourceDelta.getResource(); - if (md.exclusionPatterns != null && Util.isExcluded(resource, md.exclusionPatterns)) return; - switch(resource.getType()) { - case IResource.FOLDER : - switch (sourceDelta.getKind()) { - case IResourceDelta.ADDED : - IPath addedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount); - createFolder(addedPackagePath, md.binaryFolder); // ensure package exists in the output folder - // add dependents even when the package thinks it exists to be on the safe side - if (PHPBuilder.DEBUG) - System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$ - addDependentsOf(addedPackagePath, true); - // fall thru & collect all the source files - case IResourceDelta.CHANGED : - IResourceDelta[] children = sourceDelta.getAffectedChildren(); - for (int i = 0, l = children.length; i < l; i++) - findSourceFiles(children[i], md, segmentCount); - return; - case IResourceDelta.REMOVED : - IPath removedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount); - if (sourceLocations.length > 1) { - for (int i = 0, l = sourceLocations.length; i < l; i++) { - if (sourceLocations[i].sourceFolder.getFolder(removedPackagePath).exists()) { - // only a package fragment was removed, same as removing multiple source files - createFolder(removedPackagePath, md.binaryFolder); // ensure package exists in the output folder - IResourceDelta[] removedChildren = sourceDelta.getAffectedChildren(); - for (int j = 0, m = removedChildren.length; j < m; j++) - findSourceFiles(removedChildren[j], md, segmentCount); - return; - } - } - } - IFolder removedPackageFolder = md.binaryFolder.getFolder(removedPackagePath); - if (removedPackageFolder.exists()) - removedPackageFolder.delete(IResource.FORCE, null); - // add dependents even when the package thinks it does not exist to be on the safe side - if (PHPBuilder.DEBUG) - System.out.println("Found removed package " + removedPackagePath); //$NON-NLS-1$ - addDependentsOf(removedPackagePath, true); - newState.removePackage(sourceDelta); - } - return; - case IResource.FILE : - String resourceName = resource.getName(); - if (Util.isJavaFileName(resourceName)) { - IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension(); - String typeLocator = resource.getProjectRelativePath().toString(); - switch (sourceDelta.getKind()) { - case IResourceDelta.ADDED : - if (PHPBuilder.DEBUG) - System.out.println("Compile this added source file " + typeLocator); //$NON-NLS-1$ - sourceFiles.add(new SourceFile((IFile) resource, md, encoding)); - String typeName = typePath.toString(); - if (!newState.isDuplicateLocator(typeName, typeLocator)) { // adding dependents results in 2 duplicate errors - if (PHPBuilder.DEBUG) - System.out.println("Found added source file " + typeName); //$NON-NLS-1$ - addDependentsOf(typePath, true); - } - return; - case IResourceDelta.REMOVED : - char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator); - if (definedTypeNames == null) { // defined a single type matching typePath - removeClassFile(typePath, md.binaryFolder); - if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) { - // remove problems and tasks for a compilation unit that is being moved (to another package or renamed) - // if the target file is a compilation unit, the new cu will be recompiled - // if the target file is a non-java resource, then markers are removed - // see bug 2857 - IResource movedFile = javaBuilder.workspaceRoot.getFile(sourceDelta.getMovedToPath()); - PHPBuilder.removeProblemsAndTasksFor(movedFile); - } - } else { - if (PHPBuilder.DEBUG) - System.out.println("Found removed source file " + typePath.toString()); //$NON-NLS-1$ - addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision - if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type - IPath packagePath = typePath.removeLastSegments(1); - for (int i = 0, l = definedTypeNames.length; i < l; i++) - removeClassFile(packagePath.append(new String(definedTypeNames[i])), md.binaryFolder); - } - } - newState.removeLocator(typeLocator); - return; - case IResourceDelta.CHANGED : - if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0) - return; // skip it since it really isn't changed - if (PHPBuilder.DEBUG) - System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$ - sourceFiles.add(new SourceFile((IFile) resource, md, encoding)); - } - return; -// } else if (Util.isClassFileName(resourceName)) { -// return; // skip class files - } else if (md.hasIndependentOutputFolder) { - if (javaBuilder.filterExtraResource(resource)) return; - - // copy all other resource deltas to the output folder - IPath resourcePath = resource.getFullPath().removeFirstSegments(segmentCount); - IResource outputFile = md.binaryFolder.getFile(resourcePath); - switch (sourceDelta.getKind()) { - case IResourceDelta.ADDED : - if (outputFile.exists()) { - if (PHPBuilder.DEBUG) - System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$ - outputFile.delete(IResource.FORCE, null); - } - if (PHPBuilder.DEBUG) - System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$ - createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder - resource.copy(outputFile.getFullPath(), IResource.FORCE, null); - outputFile.setDerived(true); - return; - case IResourceDelta.REMOVED : - if (outputFile.exists()) { - if (PHPBuilder.DEBUG) - System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$ - outputFile.delete(IResource.FORCE, null); - } - return; - case IResourceDelta.CHANGED : - if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0) - return; // skip it since it really isn't changed - if (outputFile.exists()) { - if (PHPBuilder.DEBUG) - System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$ - outputFile.delete(IResource.FORCE, null); - } - if (PHPBuilder.DEBUG) - System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$ - createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder - resource.copy(outputFile.getFullPath(), IResource.FORCE, null); - outputFile.setDerived(true); - } - return; - } - } -} - -protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) throws CoreException { - char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator); - if (previousTypeNames == null) - previousTypeNames = new char[][] {mainTypeName}; - IPath packagePath = null; - next : for (int i = 0, l = previousTypeNames.length; i < l; i++) { - char[] previous = previousTypeNames[i]; - for (int j = 0, m = definedTypeNames.size(); j < m; j++) - if (CharOperation.equals(previous, (char[]) definedTypeNames.get(j))) - continue next; - - SourceFile sourceFile = (SourceFile) result.getCompilationUnit(); - if (packagePath == null) { - int count = sourceFile.sourceLocation.sourceFolder.getFullPath().segmentCount(); - packagePath = sourceFile.resource.getFullPath().removeFirstSegments(count).removeLastSegments(1); - } - if (secondaryTypesToRemove == null) - this.secondaryTypesToRemove = new SimpleLookupTable(); - ArrayList types = (ArrayList) secondaryTypesToRemove.get(sourceFile.sourceLocation.binaryFolder); - if (types == null) - types = new ArrayList(definedTypeNames.size()); - types.add(packagePath.append(new String(previous))); - secondaryTypesToRemove.put(sourceFile.sourceLocation.binaryFolder, types); - } -// super.finishedWith(sourceLocator, result, mainTypeName, definedTypeNames, duplicateTypeNames); -} - -protected void removeClassFile(IPath typePath, IContainer outputFolder) throws CoreException { - if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type - newState.removeQualifiedTypeName(typePath.toString()); - // add dependents even when the type thinks it does not exist to be on the safe side - if (PHPBuilder.DEBUG) - System.out.println("Found removed type " + typePath); //$NON-NLS-1$ - addDependentsOf(typePath, true); // when member types are removed, their enclosing type is structurally changed - } - IFile classFile = outputFolder.getFile(typePath.addFileExtension(PHPBuilder.CLASS_EXTENSION)); - if (classFile.exists()) { - if (PHPBuilder.DEBUG) - System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$ - classFile.delete(IResource.FORCE, null); - } -} - -protected void removeSecondaryTypes() throws CoreException { - if (secondaryTypesToRemove != null) { // delayed deleting secondary types until the end of the compile loop - Object[] keyTable = secondaryTypesToRemove.keyTable; - Object[] valueTable = secondaryTypesToRemove.valueTable; - for (int i = 0, l = keyTable.length; i < l; i++) { - IContainer outputFolder = (IContainer) keyTable[i]; - if (outputFolder != null) { - ArrayList paths = (ArrayList) valueTable[i]; - for (int j = 0, m = paths.size(); j < m; j++) - removeClassFile((IPath) paths.get(j), outputFolder); - } - } - this.secondaryTypesToRemove = null; - if (previousSourceFiles != null && previousSourceFiles.size() > 1) - this.previousSourceFiles = null; // cannot optimize recompile case when a secondary type is deleted - } -} - -protected void resetCollections() { - previousSourceFiles = sourceFiles.isEmpty() ? null : (ArrayList) sourceFiles.clone(); - - sourceFiles.clear(); - qualifiedStrings.clear(); - simpleStrings.clear(); - workQueue.clear(); -} - -protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException { - IMarker[] markers = PHPBuilder.getProblemsFor(sourceFile.resource); - IProblem[] problems = result.getProblems(); - if (problems == null && markers.length == 0) return; - - notifier.updateProblemCounts(markers, problems); - PHPBuilder.removeProblemsFor(sourceFile.resource); - storeProblemsFor(sourceFile, problems); -} - -protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException { - IMarker[] markers = PHPBuilder.getTasksFor(sourceFile.resource); - IProblem[] tasks = result.getTasks(); - if (tasks == null && markers.length == 0) return; - - PHPBuilder.removeTasksFor(sourceFile.resource); - storeTasksFor(sourceFile, tasks); -} - -//protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType) throws CoreException { -// // Before writing out the class file, compare it to the previous file -// // If structural changes occured then add dependent source files -// if (file.exists()) { -// if (writeClassFileCheck(file, qualifiedFileName, bytes)) { -// if (JavaBuilder.DEBUG) -// System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$ -// file.setContents(new ByteArrayInputStream(bytes), true, false, null); -// if (!file.isDerived()) -// file.setDerived(true); -// } else if (JavaBuilder.DEBUG) { -// System.out.println("Skipped over unchanged class file " + file.getName());//$NON-NLS-1$ -// } -// } else { -// if (isSecondaryType) -// addDependentsOf(new Path(qualifiedFileName), true); // new secondary type -// if (JavaBuilder.DEBUG) -// System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$ -// file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null); -// file.setDerived(true); -// } -//} - -//protected boolean writeClassFileCheck(IFile file, String fileName, byte[] newBytes) throws CoreException { -// try { -// byte[] oldBytes = Util.getResourceContentsAsByteArray(file); -// if (this.compileLoop > 1) { // only optimize files which were recompiled during the dependent pass, see 33990 -// notEqual : if (newBytes.length == oldBytes.length) { -// for (int i = newBytes.length; --i >= 0;) -// if (newBytes[i] != oldBytes[i]) break notEqual; -// return false; // bytes are identical so skip them -// } -// } -// IPath location = file.getLocation(); -// if (location == null) return false; // unable to determine location of this class file -// ClassFileReader reader = new ClassFileReader(oldBytes, location.toString().toCharArray()); -// // ignore local types since they're only visible inside a single method -// if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) { -// if (JavaBuilder.DEBUG) -// System.out.println("Type has structural changes " + fileName); //$NON-NLS-1$ -// addDependentsOf(new Path(fileName), true); -// } -// } catch (ClassFormatException e) { -// addDependentsOf(new Path(fileName), true); -// } -// return true; -//} - -public String toString() { - return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$ -} - - -/* Debug helper - -static void dump(IResourceDelta delta) { - StringBuffer buffer = new StringBuffer(); - IPath path = delta.getFullPath(); - for (int i = path.segmentCount(); --i > 0;) - buffer.append(" "); - switch (delta.getKind()) { - case IResourceDelta.ADDED: - buffer.append('+'); - break; - case IResourceDelta.REMOVED: - buffer.append('-'); - break; - case IResourceDelta.CHANGED: - buffer.append('*'); - break; - case IResourceDelta.NO_CHANGE: - buffer.append('='); - break; - default: - buffer.append('?'); - break; - } - buffer.append(path); - System.out.println(buffer.toString()); - IResourceDelta[] children = delta.getAffectedChildren(); - for (int i = 0, l = children.length; i < l; i++) - dump(children[i]); -} -*/ + protected ArrayList sourceFiles; + protected ArrayList previousSourceFiles; + protected ArrayList qualifiedStrings; + protected ArrayList simpleStrings; + protected SimpleLookupTable secondaryTypesToRemove; + protected boolean hasStructuralChanges; + protected int compileLoop; + public static int MaxCompileLoop = 5; // perform a full build if it takes + // more than ? incremental compile + // loops + protected IncrementalImageBuilder(PHPBuilder javaBuilder) { + super(javaBuilder); + this.nameEnvironment.isIncrementalBuild = true; + this.newState.copyFrom(javaBuilder.lastState); + this.sourceFiles = new ArrayList(33); + this.previousSourceFiles = null; + this.qualifiedStrings = new ArrayList(33); + this.simpleStrings = new ArrayList(33); + this.hasStructuralChanges = false; + this.compileLoop = 0; + } + public boolean build(SimpleLookupTable deltas) { + // initialize builder + // walk this project's deltas, find changed source files + // walk prereq projects' deltas, find changed class files & add affected + // source files + // use the build state # to skip the deltas for certain prereq projects + // ignore changed zip/jar files since they caused a full build + // compile the source files & acceptResult() + // compare the produced class files against the existing ones on disk + // recompile all dependent source files of any type with structural changes + // or new/removed secondary type + // keep a loop counter to abort & perform a full build + if (PHPBuilder.DEBUG) + System.out.println("INCREMENTAL build"); //$NON-NLS-1$ + try { + resetCollections(); + notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$ + IResourceDelta sourceDelta = (IResourceDelta) deltas + .get(javaBuilder.currentProject); + if (sourceDelta != null) + if (!findSourceFiles(sourceDelta)) + return false; + notifier.updateProgressDelta(0.10f); + Object[] keyTable = deltas.keyTable; + Object[] valueTable = deltas.valueTable; + final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault() + .getIndexManager(javaBuilder.currentProject); + for (int i = 0, l = valueTable.length; i < l; i++) { + IResourceDelta delta = (IResourceDelta) valueTable[i]; + if (delta != null) { + IResource resource = delta.getResource(); + int resourceType = resource.getType(); + if (resourceType == IResource.FILE) { + switch (delta.getKind()) { + case IResourceDelta.ADDED : + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + // update indexfile for the project: + indexManager.addFile((IFile) resource); + } + break; + case IResourceDelta.CHANGED : + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + // update indexfile for the project: + indexManager.changeFile((IFile) resource); + } + break; + case IResourceDelta.REMOVED : + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + // update indexfile for the project: + indexManager.removeFile((IFile) resource); + } + break; + } + } + // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) + // javaBuilder.binaryLocationsPerProject.get(keyTable[i]); + // if (classFoldersAndJars != null) + // if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return + // false; + } + } + notifier.updateProgressDelta(0.10f); + notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$ + addAffectedSourceFiles(); + notifier.updateProgressDelta(0.05f); + this.compileLoop = 0; + float increment = 0.40f; + while (sourceFiles.size() > 0) { // added to in acceptResult + if (++this.compileLoop > MaxCompileLoop) { + if (PHPBuilder.DEBUG) + System.out + .println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$ + return false; + } + notifier.checkCancel(); + SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()]; + sourceFiles.toArray(allSourceFiles); + resetCollections(); + workQueue.addAll(allSourceFiles); + notifier.setProgressPerCompilationUnit(increment + / allSourceFiles.length); + increment = increment / 2; + compile(allSourceFiles); + removeSecondaryTypes(); + addAffectedSourceFiles(); + } + if (this.hasStructuralChanges && javaBuilder.javaProject.hasCycleMarker()) + javaBuilder.mustPropagateStructuralChanges(); + } catch (AbortIncrementalBuildException e) { + // abort the incremental build and let the batch builder handle the + // problem + if (PHPBuilder.DEBUG) + System.out.println("ABORTING incremental build... cannot find " + + e.qualifiedTypeName + //$NON-NLS-1$ + ". Could have been renamed inside its existing source file."); //$NON-NLS-1$ + return false; + } catch (CoreException e) { + throw internalException(e); + } finally { + cleanUp(); + } + return true; + } + protected void addAffectedSourceFiles() { + if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty()) + return; + // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are + // just 'X' + char[][][] qualifiedNames = ReferenceCollection + .internQualifiedNames(qualifiedStrings); + // if a well known qualified name was found then we can skip over these + if (qualifiedNames.length < qualifiedStrings.size()) + qualifiedNames = null; + char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings); + // if a well known name was found then we can skip over these + if (simpleNames.length < simpleStrings.size()) + simpleNames = null; + Object[] keyTable = newState.references.keyTable; + Object[] valueTable = newState.references.valueTable; + next : for (int i = 0, l = valueTable.length; i < l; i++) { + ReferenceCollection refs = (ReferenceCollection) valueTable[i]; + if (refs != null && refs.includes(qualifiedNames, simpleNames)) { + String typeLocator = (String) keyTable[i]; + IFile file = javaBuilder.currentProject.getFile(typeLocator); + if (file.exists()) { + ClasspathMultiDirectory md = sourceLocations[0]; + if (sourceLocations.length > 1) { + IPath sourceFileFullPath = file.getFullPath(); + for (int j = 0, m = sourceLocations.length; j < m; j++) { + if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf( + sourceFileFullPath)) { + md = sourceLocations[j]; + if (md.exclusionPatterns == null + || !Util.isExcluded(file, md.exclusionPatterns)) + break; + } + } + } + SourceFile sourceFile = new SourceFile(file, md, encoding); + if (sourceFiles.contains(sourceFile)) + continue next; + if (compiledAllAtOnce && previousSourceFiles != null + && previousSourceFiles.contains(sourceFile)) + continue next; // can skip previously compiled files since already + // saw hierarchy related problems + if (PHPBuilder.DEBUG) + System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$ + // // update indexfile for the project: + sourceFiles.add(sourceFile); + } + } + } + } + protected void addDependentsOf(IPath path, boolean hasStructuralChanges) { + if (hasStructuralChanges) { + newState.tagAsStructurallyChanged(); + this.hasStructuralChanges = true; + } + // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are + // just 'X' + path = path.setDevice(null); + String packageName = path.removeLastSegments(1).toString(); + if (!qualifiedStrings.contains(packageName)) + qualifiedStrings.add(packageName); + String typeName = path.lastSegment(); + int memberIndex = typeName.indexOf('$'); + if (memberIndex > 0) + typeName = typeName.substring(0, memberIndex); + if (!simpleStrings.contains(typeName)) { + if (PHPBuilder.DEBUG) + System.out.println(" will look for dependents of " //$NON-NLS-1$ + + typeName + " in " + packageName); //$NON-NLS-1$ + simpleStrings.add(typeName); + } + } + protected void cleanUp() { + super.cleanUp(); + this.sourceFiles = null; + this.previousSourceFiles = null; + this.qualifiedStrings = null; + this.simpleStrings = null; + this.secondaryTypesToRemove = null; + this.hasStructuralChanges = false; + this.compileLoop = 0; + } + //protected boolean findAffectedSourceFiles(IResourceDelta delta, + // ClasspathLocation[] classFoldersAndJars) { + // for (int i = 0, l = classFoldersAndJars.length; i < l; i++) { + // ClasspathLocation bLocation = classFoldersAndJars[i]; + // // either a .class file folder or a zip/jar file + // if (bLocation != null) { // skip unchanged output folder + // IPath p = bLocation.getProjectRelativePath(); + // if (p != null) { + // IResourceDelta binaryDelta = delta.findMember(p); + // if (binaryDelta != null) { + // if (bLocation instanceof ClasspathJar) { + // if (JavaBuilder.DEBUG) + // System.out.println("ABORTING incremental build... found delta to jar/zip + // file"); //$NON-NLS-1$ + // return false; // do full build since jar file was changed (added/removed + // were caught as classpath change) + // } + // if (binaryDelta.getKind() == IResourceDelta.ADDED || binaryDelta.getKind() + // == IResourceDelta.REMOVED) { + // if (JavaBuilder.DEBUG) + // System.out.println("ABORTING incremental build... found added/removed + // binary folder"); //$NON-NLS-1$ + // return false; // added/removed binary folder should not make it here + // (classpath change), but handle anyways + // } + // int segmentCount = binaryDelta.getFullPath().segmentCount(); + // IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class + // files from class folder + // for (int j = 0, m = children.length; j < m; j++) + // findAffectedSourceFiles(children[j], segmentCount); + // notifier.checkCancel(); + // } + // } + // } + // } + // return true; + //} + protected void findAffectedSourceFiles(IResourceDelta binaryDelta, + int segmentCount) { + // When a package becomes a type or vice versa, expect 2 deltas, + // one on the folder & one on the class file + IResource resource = binaryDelta.getResource(); + switch (resource.getType()) { + case IResource.FOLDER : + switch (binaryDelta.getKind()) { + case IResourceDelta.ADDED : + case IResourceDelta.REMOVED : + IPath packagePath = resource.getFullPath().removeFirstSegments( + segmentCount); + String packageName = packagePath.toString(); + if (binaryDelta.getKind() == IResourceDelta.ADDED) { + // see if any known source file is from the same package... + // classpath already includes new package + if (!newState.isKnownPackage(packageName)) { + if (PHPBuilder.DEBUG) + System.out.println("Found added package " + packageName); //$NON-NLS-1$ + addDependentsOf(packagePath, false); + return; + } + if (PHPBuilder.DEBUG) + System.out.println("Skipped dependents of added package " + + packageName); //$NON-NLS-1$ + } else { + // see if the package still exists on the classpath + // if (!nameEnvironment.isPackage(packageName)) { + // if (JavaBuilder.DEBUG) + // System.out.println("Found removed package " + packageName); + // //$NON-NLS-1$ + // addDependentsOf(packagePath, false); + // return; + // } + if (PHPBuilder.DEBUG) + System.out.println("Skipped dependents of removed package " + + packageName); //$NON-NLS-1$ + } + // fall thru & traverse the sub-packages and .class files + case IResourceDelta.CHANGED : + IResourceDelta[] children = binaryDelta.getAffectedChildren(); + for (int i = 0, l = children.length; i < l; i++) + findAffectedSourceFiles(children[i], segmentCount); + } + return; + case IResource.FILE : + // if (Util.isClassFileName(resource.getName())) { + // IPath typePath = + // resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension(); + // switch (binaryDelta.getKind()) { + // case IResourceDelta.ADDED : + // case IResourceDelta.REMOVED : + // if (JavaBuilder.DEBUG) + // System.out.println("Found added/removed class file " + typePath); + // //$NON-NLS-1$ + // addDependentsOf(typePath, false); + // return; + // case IResourceDelta.CHANGED : + // if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0) + // return; // skip it since it really isn't changed + // if (JavaBuilder.DEBUG) + // System.out.println("Found changed class file " + typePath); + // //$NON-NLS-1$ + // addDependentsOf(typePath, false); + // } + // return; + // } + } + } + protected boolean findSourceFiles(IResourceDelta delta) throws CoreException { + for (int i = 0, l = sourceLocations.length; i < l; i++) { + ClasspathMultiDirectory md = sourceLocations[i]; + if (md.sourceFolder.equals(javaBuilder.currentProject)) { + // skip nested source & output folders when the project is a source + // folder + int segmentCount = delta.getFullPath().segmentCount(); + IResourceDelta[] children = delta.getAffectedChildren(); + for (int j = 0, m = children.length; j < m; j++) + if (!isExcludedFromProject(children[j].getFullPath())) + findSourceFiles(children[j], md, segmentCount); + } else { + IResourceDelta sourceDelta = delta.findMember(md.sourceFolder + .getProjectRelativePath()); + if (sourceDelta != null) { + if (sourceDelta.getKind() == IResourceDelta.REMOVED) { + if (PHPBuilder.DEBUG) + System.out + .println("ABORTING incremental build... found removed source folder"); //$NON-NLS-1$ + return false; // removed source folder should not make it here, but + // handle anyways (ADDED is supported) + } + int segmentCount = sourceDelta.getFullPath().segmentCount(); + IResourceDelta[] children = sourceDelta.getAffectedChildren(); + for (int j = 0, m = children.length; j < m; j++) + findSourceFiles(children[j], md, segmentCount); + } + } + notifier.checkCancel(); + } + return true; + } + protected void findSourceFiles(IResourceDelta sourceDelta, + ClasspathMultiDirectory md, int segmentCount) throws CoreException { + // When a package becomes a type or vice versa, expect 2 deltas, + // one on the folder & one on the source file + IResource resource = sourceDelta.getResource(); + if (md.exclusionPatterns != null + && Util.isExcluded(resource, md.exclusionPatterns)) + return; + switch (resource.getType()) { + case IResource.FOLDER : + switch (sourceDelta.getKind()) { + case IResourceDelta.ADDED : + IPath addedPackagePath = resource.getFullPath() + .removeFirstSegments(segmentCount); + createFolder(addedPackagePath, md.binaryFolder); // ensure package + // exists in the + // output folder + // add dependents even when the package thinks it exists to be on + // the safe side + if (PHPBuilder.DEBUG) + System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$ + addDependentsOf(addedPackagePath, true); + // fall thru & collect all the source files + case IResourceDelta.CHANGED : + IResourceDelta[] children = sourceDelta.getAffectedChildren(); + for (int i = 0, l = children.length; i < l; i++) + findSourceFiles(children[i], md, segmentCount); + return; + case IResourceDelta.REMOVED : + IPath removedPackagePath = resource.getFullPath() + .removeFirstSegments(segmentCount); + if (sourceLocations.length > 1) { + for (int i = 0, l = sourceLocations.length; i < l; i++) { + if (sourceLocations[i].sourceFolder.getFolder( + removedPackagePath).exists()) { + // only a package fragment was removed, same as removing + // multiple source files + createFolder(removedPackagePath, md.binaryFolder); // ensure + // package + // exists + // in the + // output + // folder + IResourceDelta[] removedChildren = sourceDelta + .getAffectedChildren(); + for (int j = 0, m = removedChildren.length; j < m; j++) + findSourceFiles(removedChildren[j], md, segmentCount); + return; + } + } + } + IFolder removedPackageFolder = md.binaryFolder + .getFolder(removedPackagePath); + if (removedPackageFolder.exists()) + removedPackageFolder.delete(IResource.FORCE, null); + // add dependents even when the package thinks it does not exist to + // be on the safe side + if (PHPBuilder.DEBUG) + System.out.println("Found removed package " + removedPackagePath); //$NON-NLS-1$ + addDependentsOf(removedPackagePath, true); + newState.removePackage(sourceDelta); + } + return; + case IResource.FILE : + String resourceName = resource.getName(); + if (Util.isJavaFileName(resourceName)) { + IPath typePath = resource.getFullPath().removeFirstSegments( + segmentCount).removeFileExtension(); + String typeLocator = resource.getProjectRelativePath().toString(); + switch (sourceDelta.getKind()) { + case IResourceDelta.ADDED : + if (PHPBuilder.DEBUG) + System.out.println("Compile this added source file " + + typeLocator); //$NON-NLS-1$ + sourceFiles.add(new SourceFile((IFile) resource, md, encoding)); + String typeName = typePath.toString(); + if (!newState.isDuplicateLocator(typeName, typeLocator)) { // adding + // dependents + // results + // in + // 2 + // duplicate + // errors + if (PHPBuilder.DEBUG) + System.out.println("Found added source file " + typeName); //$NON-NLS-1$ + addDependentsOf(typePath, true); + } + return; + case IResourceDelta.REMOVED : + char[][] definedTypeNames = newState + .getDefinedTypeNamesFor(typeLocator); + if (definedTypeNames == null) { // defined a single type matching + // typePath + removeClassFile(typePath, md.binaryFolder); + if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) { + // remove problems and tasks for a compilation unit that is + // being moved (to another package or renamed) + // if the target file is a compilation unit, the new cu will + // be recompiled + // if the target file is a non-java resource, then markers + // are removed + // see bug 2857 + IResource movedFile = javaBuilder.workspaceRoot + .getFile(sourceDelta.getMovedToPath()); + PHPBuilder.removeProblemsAndTasksFor(movedFile); + } + } else { + if (PHPBuilder.DEBUG) + System.out.println("Found removed source file " + + typePath.toString()); //$NON-NLS-1$ + addDependentsOf(typePath, true); // add dependents of the + // source file since it may be + // involved in a name + // collision + if (definedTypeNames.length > 0) { // skip it if it failed to + // successfully define a + // type + IPath packagePath = typePath.removeLastSegments(1); + for (int i = 0, l = definedTypeNames.length; i < l; i++) + removeClassFile(packagePath.append(new String( + definedTypeNames[i])), md.binaryFolder); + } + } + newState.removeLocator(typeLocator); + return; + case IResourceDelta.CHANGED : + if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0) + return; // skip it since it really isn't changed + if (PHPBuilder.DEBUG) + System.out.println("Compile this changed source file " + + typeLocator); //$NON-NLS-1$ + sourceFiles.add(new SourceFile((IFile) resource, md, encoding)); + } + return; + // } else if (Util.isClassFileName(resourceName)) { + // return; // skip class files + } else if (md.hasIndependentOutputFolder) { + if (javaBuilder.filterExtraResource(resource)) + return; + // copy all other resource deltas to the output folder + IPath resourcePath = resource.getFullPath().removeFirstSegments( + segmentCount); + IResource outputFile = md.binaryFolder.getFile(resourcePath); + switch (sourceDelta.getKind()) { + case IResourceDelta.ADDED : + if (outputFile.exists()) { + if (PHPBuilder.DEBUG) + System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$ + outputFile.delete(IResource.FORCE, null); + } + if (PHPBuilder.DEBUG) + System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$ + createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure + // package + // exists + // in + // the + // output + // folder + resource.copy(outputFile.getFullPath(), IResource.FORCE, null); + outputFile.setDerived(true); + return; + case IResourceDelta.REMOVED : + if (outputFile.exists()) { + if (PHPBuilder.DEBUG) + System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$ + outputFile.delete(IResource.FORCE, null); + } + return; + case IResourceDelta.CHANGED : + if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0) + return; // skip it since it really isn't changed + if (outputFile.exists()) { + if (PHPBuilder.DEBUG) + System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$ + outputFile.delete(IResource.FORCE, null); + } + if (PHPBuilder.DEBUG) + System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$ + createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure + // package + // exists + // in + // the + // output + // folder + resource.copy(outputFile.getFullPath(), IResource.FORCE, null); + outputFile.setDerived(true); + } + return; + } + } + } + protected void finishedWith(String sourceLocator, CompilationResult result, + char[] mainTypeName, ArrayList definedTypeNames, + ArrayList duplicateTypeNames) throws CoreException { + char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator); + if (previousTypeNames == null) + previousTypeNames = new char[][]{mainTypeName}; + IPath packagePath = null; + next : for (int i = 0, l = previousTypeNames.length; i < l; i++) { + char[] previous = previousTypeNames[i]; + for (int j = 0, m = definedTypeNames.size(); j < m; j++) + if (CharOperation.equals(previous, (char[]) definedTypeNames.get(j))) + continue next; + SourceFile sourceFile = (SourceFile) result.getCompilationUnit(); + if (packagePath == null) { + int count = sourceFile.sourceLocation.sourceFolder.getFullPath() + .segmentCount(); + packagePath = sourceFile.resource.getFullPath().removeFirstSegments( + count).removeLastSegments(1); + } + if (secondaryTypesToRemove == null) + this.secondaryTypesToRemove = new SimpleLookupTable(); + ArrayList types = (ArrayList) secondaryTypesToRemove + .get(sourceFile.sourceLocation.binaryFolder); + if (types == null) + types = new ArrayList(definedTypeNames.size()); + types.add(packagePath.append(new String(previous))); + secondaryTypesToRemove.put(sourceFile.sourceLocation.binaryFolder, types); + } + // super.finishedWith(sourceLocator, result, mainTypeName, + // definedTypeNames, duplicateTypeNames); + } + protected void removeClassFile(IPath typePath, IContainer outputFolder) + throws CoreException { + if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type + newState.removeQualifiedTypeName(typePath.toString()); + // add dependents even when the type thinks it does not exist to be on + // the safe side + if (PHPBuilder.DEBUG) + System.out.println("Found removed type " + typePath); //$NON-NLS-1$ + addDependentsOf(typePath, true); // when member types are removed, their + // enclosing type is structurally + // changed + } + IFile classFile = outputFolder.getFile(typePath + .addFileExtension(PHPBuilder.CLASS_EXTENSION)); + if (classFile.exists()) { + if (PHPBuilder.DEBUG) + System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$ + classFile.delete(IResource.FORCE, null); + } + } + protected void removeSecondaryTypes() throws CoreException { + if (secondaryTypesToRemove != null) { // delayed deleting secondary types + // until the end of the compile loop + Object[] keyTable = secondaryTypesToRemove.keyTable; + Object[] valueTable = secondaryTypesToRemove.valueTable; + for (int i = 0, l = keyTable.length; i < l; i++) { + IContainer outputFolder = (IContainer) keyTable[i]; + if (outputFolder != null) { + ArrayList paths = (ArrayList) valueTable[i]; + for (int j = 0, m = paths.size(); j < m; j++) + removeClassFile((IPath) paths.get(j), outputFolder); + } + } + this.secondaryTypesToRemove = null; + if (previousSourceFiles != null && previousSourceFiles.size() > 1) + this.previousSourceFiles = null; // cannot optimize recompile case when + // a secondary type is deleted + } + } + protected void resetCollections() { + previousSourceFiles = sourceFiles.isEmpty() + ? null + : (ArrayList) sourceFiles.clone(); + sourceFiles.clear(); + qualifiedStrings.clear(); + simpleStrings.clear(); + workQueue.clear(); + } + protected void updateProblemsFor(SourceFile sourceFile, + CompilationResult result) throws CoreException { + IMarker[] markers = PHPBuilder.getProblemsFor(sourceFile.resource); + IProblem[] problems = result.getProblems(); + if (problems == null && markers.length == 0) + return; + notifier.updateProblemCounts(markers, problems); + PHPBuilder.removeProblemsFor(sourceFile.resource); + storeProblemsFor(sourceFile, problems); + } + protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) + throws CoreException { + IMarker[] markers = PHPBuilder.getTasksFor(sourceFile.resource); + IProblem[] tasks = result.getTasks(); + if (tasks == null && markers.length == 0) + return; + PHPBuilder.removeTasksFor(sourceFile.resource); + storeTasksFor(sourceFile, tasks); + } + //protected void writeClassFileBytes(byte[] bytes, IFile file, String + // qualifiedFileName, boolean isSecondaryType) throws CoreException { + // // Before writing out the class file, compare it to the previous file + // // If structural changes occured then add dependent source files + // if (file.exists()) { + // if (writeClassFileCheck(file, qualifiedFileName, bytes)) { + // if (JavaBuilder.DEBUG) + // System.out.println("Writing changed class file " + + // file.getName());//$NON-NLS-1$ + // file.setContents(new ByteArrayInputStream(bytes), true, false, null); + // if (!file.isDerived()) + // file.setDerived(true); + // } else if (JavaBuilder.DEBUG) { + // System.out.println("Skipped over unchanged class file " + + // file.getName());//$NON-NLS-1$ + // } + // } else { + // if (isSecondaryType) + // addDependentsOf(new Path(qualifiedFileName), true); // new secondary type + // if (JavaBuilder.DEBUG) + // System.out.println("Writing new class file " + + // file.getName());//$NON-NLS-1$ + // file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null); + // file.setDerived(true); + // } + //} + //protected boolean writeClassFileCheck(IFile file, String fileName, byte[] + // newBytes) throws CoreException { + // try { + // byte[] oldBytes = Util.getResourceContentsAsByteArray(file); + // if (this.compileLoop > 1) { // only optimize files which were recompiled + // during the dependent pass, see 33990 + // notEqual : if (newBytes.length == oldBytes.length) { + // for (int i = newBytes.length; --i >= 0;) + // if (newBytes[i] != oldBytes[i]) break notEqual; + // return false; // bytes are identical so skip them + // } + // } + // IPath location = file.getLocation(); + // if (location == null) return false; // unable to determine location of + // this class file + // ClassFileReader reader = new ClassFileReader(oldBytes, + // location.toString().toCharArray()); + // // ignore local types since they're only visible inside a single method + // if (!(reader.isLocal() || reader.isAnonymous()) && + // reader.hasStructuralChanges(newBytes)) { + // if (JavaBuilder.DEBUG) + // System.out.println("Type has structural changes " + fileName); + // //$NON-NLS-1$ + // addDependentsOf(new Path(fileName), true); + // } + // } catch (ClassFormatException e) { + // addDependentsOf(new Path(fileName), true); + // } + // return true; + //} + public String toString() { + return "incremental image builder for:\n\tnew state: " + newState; //$NON-NLS-1$ + } + /* + * Debug helper + * + * static void dump(IResourceDelta delta) { StringBuffer buffer = new + * StringBuffer(); IPath path = delta.getFullPath(); for (int i = + * path.segmentCount(); --i > 0;) buffer.append(" "); switch + * (delta.getKind()) { case IResourceDelta.ADDED: buffer.append('+'); break; + * case IResourceDelta.REMOVED: buffer.append('-'); break; case + * IResourceDelta.CHANGED: '); break; case IResourceDelta.NO_CHANGE: + * buffer.append('='); break; default: buffer.append('?'); break; } + * buffer.append(path); System.out.println(buffer.toString()); + * IResourceDelta[] children = delta.getAffectedChildren(); for (int i = 0, l = + * children.length; i < l; i++) dump(children[i]); } + */ } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/PHPBuilder.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/PHPBuilder.java index ee59f34..575bb44 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/PHPBuilder.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/PHPBuilder.java @@ -9,7 +9,6 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core.builder; - import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -18,7 +17,6 @@ import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Map; - import net.sourceforge.phpdt.core.IClasspathEntry; import net.sourceforge.phpdt.core.IJavaModelMarker; import net.sourceforge.phpdt.core.JavaModelException; @@ -28,130 +26,136 @@ import net.sourceforge.phpdt.internal.core.JavaModelManager; import net.sourceforge.phpdt.internal.core.JavaProject; import net.sourceforge.phpdt.internal.core.Util; import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable; +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; import net.sourceforge.phpeclipse.PHPCore; - +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.builder.IdentifierIndexManager; +import net.sourceforge.phpeclipse.phpeditor.PHPParserAction; +import net.sourceforge.phpeclipse.resourcesview.PHPProject; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; - +import org.eclipse.core.runtime.OperationCanceledException; public class PHPBuilder extends IncrementalProjectBuilder { - IProject currentProject; JavaProject javaProject; IWorkspaceRoot workspaceRoot; NameEnvironment nameEnvironment; - SimpleLookupTable binaryLocationsPerProject; // maps a project to its binary resources (output folders, class folders, zip/jar files) + SimpleLookupTable binaryLocationsPerProject; // maps a project to its binary + // resources (output folders, + // class folders, zip/jar files) State lastState; BuildNotifier notifier; char[][] extraResourceFileFilters; String[] extraResourceFolderFilters; - public static final String CLASS_EXTENSION = "class"; //$NON-NLS-1$ - public static boolean DEBUG = true; - /** - * A list of project names that have been built. - * This list is used to reset the JavaModel.existingExternalFiles cache when a build cycle begins - * so that deleted external jars are discovered. + * A list of project names that have been built. This list is used to reset + * the JavaModel.existingExternalFiles cache when a build cycle begins so + * that deleted external jars are discovered. */ static ArrayList builtProjects = null; - public static IMarker[] getProblemsFor(IResource resource) { try { if (resource != null && resource.exists()) - return resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); + return resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, + false, IResource.DEPTH_INFINITE); } catch (CoreException e) { } // assume there are no problems return new IMarker[0]; } - public static IMarker[] getTasksFor(IResource resource) { try { if (resource != null && resource.exists()) - return resource.findMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE); + return resource.findMarkers(IJavaModelMarker.TASK_MARKER, false, + IResource.DEPTH_INFINITE); } catch (CoreException e) { } // assume there are no tasks return new IMarker[0]; } - public static void finishedBuilding(IResourceChangeEvent event) { BuildNotifier.resetProblemCounters(); } - public static void removeProblemsFor(IResource resource) { try { if (resource != null && resource.exists()) - resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); + resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, + false, IResource.DEPTH_INFINITE); } catch (CoreException e) { } // assume there were no problems } - public static void removeTasksFor(IResource resource) { try { if (resource != null && resource.exists()) - resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE); + resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, + IResource.DEPTH_INFINITE); } catch (CoreException e) { } // assume there were no problems } - public static void removeProblemsAndTasksFor(IResource resource) { try { if (resource != null && resource.exists()) { - resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); - resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE); + resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, + false, IResource.DEPTH_INFINITE); + resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, + IResource.DEPTH_INFINITE); } } catch (CoreException e) { } // assume there were no problems } - - public static State readState(IProject project, DataInputStream in) throws IOException { + public static State readState(IProject project, DataInputStream in) + throws IOException { return State.read(project, in); } - - public static void writeState(Object state, DataOutputStream out) throws IOException { + public static void writeState(Object state, DataOutputStream out) + throws IOException { ((State) state).write(out); } - public PHPBuilder() { } - - protected IProject[] build(int kind, Map ignored, IProgressMonitor monitor) throws CoreException { + protected IProject[] build(int kind, Map ignored, IProgressMonitor monitor) + throws CoreException { this.currentProject = getProject(); if (currentProject == null || !currentProject.isAccessible()) return new IProject[0]; - if (DEBUG) System.out.println("\nStarting build of " + currentProject.getName() //$NON-NLS-1$ - +" @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ + + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ this.notifier = new BuildNotifier(monitor, currentProject); notifier.begin(); boolean ok = false; try { notifier.checkCancel(); initializeBuilder(); - if (isWorthBuilding()) { if (kind == FULL_BUILD) { + processFullPHPIndex(currentProject, monitor); buildAll(); } else { if ((this.lastState = getLastState(currentProject)) == null) { if (DEBUG) - System.out.println("Performing full build since last saved state was not found"); //$NON-NLS-1$ - buildAll(); - } else if (hasClasspathChanged()) { - // if the output location changes, do not delete the binary files from old location - // the user may be trying something + System.out + .println("Performing full build since last saved state was not found"); //$NON-NLS-1$ + processFullPHPIndex(currentProject, monitor); buildAll(); +// } else if (hasClasspathChanged()) { +// // if the output location changes, do not delete the binary files +// // from old location +// // the user may be trying something +// buildAll(); } else if (nameEnvironment.sourceLocations.length > 0) { - // if there is no source to compile & no classpath changes then we are done + // if there is no source to compile & no classpath changes then we + // are done SimpleLookupTable deltas = findDeltas(); if (deltas == null) buildAll(); @@ -160,11 +164,14 @@ public class PHPBuilder extends IncrementalProjectBuilder { else if (DEBUG) System.out.println("Nothing to build since deltas were empty"); //$NON-NLS-1$ } else { - if (hasStructuralDelta()) { // double check that a jar file didn't get replaced in a binary project + if (hasStructuralDelta()) { // double check that a jar file didn't + // get replaced in a binary project + processFullPHPIndex(currentProject, monitor); buildAll(); } else { if (DEBUG) - System.out.println("Nothing to build since there are no source folders and no deltas"); //$NON-NLS-1$ + System.out + .println("Nothing to build since there are no source folders and no deltas"); //$NON-NLS-1$ lastState.tagAsNoopBuild(); } } @@ -173,32 +180,47 @@ public class PHPBuilder extends IncrementalProjectBuilder { } } catch (CoreException e) { Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$ - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, Util.bind("build.inconsistentProject", e.getLocalizedMessage())); //$NON-NLS-1$ + IMarker marker = currentProject + .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, Util.bind( + "build.inconsistentProject", e.getLocalizedMessage())); //$NON-NLS-1$ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); } catch (ImageBuilderInternalException e) { - Util.log(e.getThrowable(), "JavaBuilder handling ImageBuilderInternalException"); //$NON-NLS-1$ - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, Util.bind("build.inconsistentProject", e.coreException.getLocalizedMessage())); //$NON-NLS-1$ + Util.log(e.getThrowable(), + "JavaBuilder handling ImageBuilderInternalException"); //$NON-NLS-1$ + IMarker marker = currentProject + .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, Util.bind( + "build.inconsistentProject", e.coreException.getLocalizedMessage())); //$NON-NLS-1$ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); } catch (MissingClassFileException e) { - // do not log this exception since its thrown to handle aborted compiles because of missing class files + // do not log this exception since its thrown to handle aborted compiles + // because of missing class files if (DEBUG) - System.out.println(Util.bind("build.incompleteClassPath", e.missingClassFile)); //$NON-NLS-1$ - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, Util.bind("build.incompleteClassPath", e.missingClassFile)); //$NON-NLS-1$ + System.out.println(Util.bind("build.incompleteClassPath", + e.missingClassFile)); //$NON-NLS-1$ + IMarker marker = currentProject + .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, Util.bind( + "build.incompleteClassPath", e.missingClassFile)); //$NON-NLS-1$ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); } catch (MissingSourceFileException e) { - // do not log this exception since its thrown to handle aborted compiles because of missing source files + // do not log this exception since its thrown to handle aborted compiles + // because of missing source files if (DEBUG) - System.out.println(Util.bind("build.missingSourceFile", e.missingSourceFile)); //$NON-NLS-1$ - removeProblemsAndTasksFor(currentProject); // make this the only problem for this project - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, Util.bind("build.missingSourceFile", e.missingSourceFile)); //$NON-NLS-1$ + System.out.println(Util.bind("build.missingSourceFile", + e.missingSourceFile)); //$NON-NLS-1$ + removeProblemsAndTasksFor(currentProject); // make this the only problem + // for this project + IMarker marker = currentProject + .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, Util.bind("build.missingSourceFile", + e.missingSourceFile)); //$NON-NLS-1$ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); } finally { if (!ok) - // If the build failed, clear the previously built state, forcing a full build next time. + // If the build failed, clear the previously built state, forcing a + // full build next time. clearLastState(); notifier.done(); cleanup(); @@ -206,10 +228,52 @@ public class PHPBuilder extends IncrementalProjectBuilder { IProject[] requiredProjects = getRequiredProjects(true); if (DEBUG) System.out.println("Finished build of " + currentProject.getName() //$NON-NLS-1$ - +" @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ + + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ return requiredProjects; } - + /** + * Performs a FULL_BUILD by visiting all nodes in the resource + * tree under the specified project. + * + * @param iProject + */ + private void processFullPHPIndex(final IProject iProject, + final IProgressMonitor monitor) { + final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault() + .getIndexManager(iProject); + // Create resource visitor logic + IResourceVisitor myVisitor = new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + monitor.worked(1); + monitor.subTask("Parsing: " + resource.getFullPath()); + // update indexfile for the project: +// PHPProject nature = (PHPProject) iProject +// .getNature(PHPeclipsePlugin.PHP_NATURE_ID); + indexManager.addFile((IFile) resource); + } + } + return true; + } + }; + // Process the project using the visitor just created + try { + // if (iProject.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) { + // thePHPProject = new PHPProject(); + // thePHPProject.setProject(iProject); + // } + indexManager.initialize(); + iProject.accept(myVisitor); + indexManager.writeFile(); + } catch (CoreException e) { + e.printStackTrace(); + } + } private void buildAll() { notifier.checkCancel(); notifier.subTask(Util.bind("build.preparingBuild")); //$NON-NLS-1$ @@ -220,20 +284,21 @@ public class PHPBuilder extends IncrementalProjectBuilder { imageBuilder.build(); recordNewState(imageBuilder.newState); } - private void buildDeltas(SimpleLookupTable deltas) { notifier.checkCancel(); notifier.subTask(Util.bind("build.preparingBuild")); //$NON-NLS-1$ if (DEBUG && lastState != null) System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$ - clearLastState(); // clear the previously built state so if the build fails, a full build will occur next time + clearLastState(); // clear the previously built state so if the build + // fails, a full build will occur next time IncrementalImageBuilder imageBuilder = new IncrementalImageBuilder(this); if (imageBuilder.build(deltas)) recordNewState(imageBuilder.newState); - else + else { + processFullPHPIndex(currentProject, notifier.monitor); buildAll(); + } } - private void cleanup() { this.nameEnvironment = null; this.binaryLocationsPerProject = null; @@ -242,11 +307,10 @@ public class PHPBuilder extends IncrementalProjectBuilder { this.extraResourceFileFilters = null; this.extraResourceFolderFilters = null; } - private void clearLastState() { - JavaModelManager.getJavaModelManager().setLastBuiltState(currentProject, null); + JavaModelManager.getJavaModelManager().setLastBuiltState(currentProject, + null); } - boolean filterExtraResource(IResource resource) { if (extraResourceFileFilters != null) { char[] name = resource.getName().toCharArray(); @@ -268,7 +332,6 @@ public class PHPBuilder extends IncrementalProjectBuilder { } return false; } - private SimpleLookupTable findDeltas() { notifier.subTask(Util.bind("build.readingDelta", currentProject.getName())); //$NON-NLS-1$ IResourceDelta delta = getDelta(currentProject); @@ -276,7 +339,8 @@ public class PHPBuilder extends IncrementalProjectBuilder { if (delta != null) { if (delta.getKind() != IResourceDelta.NO_CHANGE) { if (DEBUG) - System.out.println("Found source delta for: " + currentProject.getName()); //$NON-NLS-1$ + System.out.println("Found source delta for: " + + currentProject.getName()); //$NON-NLS-1$ deltas.put(currentProject, delta); } } else { @@ -285,28 +349,31 @@ public class PHPBuilder extends IncrementalProjectBuilder { notifier.subTask(""); //$NON-NLS-1$ return null; } - Object[] keyTable = binaryLocationsPerProject.keyTable; Object[] valueTable = binaryLocationsPerProject.valueTable; nextProject : for (int i = 0, l = keyTable.length; i < l; i++) { IProject p = (IProject) keyTable[i]; if (p != null && p != currentProject) { State s = getLastState(p); - if (!lastState.wasStructurallyChanged(p, s)) { // see if we can skip its delta + if (!lastState.wasStructurallyChanged(p, s)) { // see if we can skip + // its delta if (s.wasNoopBuild()) - continue nextProject; // project has no source folders and can be skipped - // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) valueTable[i]; + continue nextProject; // project has no source folders and can be + // skipped + // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) + // valueTable[i]; boolean canSkip = true; // for (int j = 0, m = classFoldersAndJars.length; j < m; j++) { // if (classFoldersAndJars[j].isOutputFolder()) - // classFoldersAndJars[j] = null; // can ignore output folder since project was not structurally changed + // classFoldersAndJars[j] = null; // can ignore output folder since + // project was not structurally changed // else // canSkip = false; // } if (canSkip) - continue nextProject; // project has no structural changes in its output folders + continue nextProject; // project has no structural changes in its + // output folders } - notifier.subTask(Util.bind("build.readingDelta", p.getName())); //$NON-NLS-1$ delta = getDelta(p); if (delta != null) { @@ -326,21 +393,21 @@ public class PHPBuilder extends IncrementalProjectBuilder { notifier.subTask(""); //$NON-NLS-1$ return deltas; } - private State getLastState(IProject project) { - return (State) JavaModelManager.getJavaModelManager().getLastBuiltState(project, notifier.monitor); + return (State) JavaModelManager.getJavaModelManager().getLastBuiltState( + project, notifier.monitor); } - - /* Return the list of projects for which it requires a resource delta. This builder's project - * is implicitly included and need not be specified. Builders must re-specify the list - * of interesting projects every time they are run as this is not carried forward - * beyond the next build. Missing projects should be specified but will be ignored until - * they are added to the workspace. - */ + /* + * Return the list of projects for which it requires a resource delta. This + * builder's project is implicitly included and need not be specified. + * Builders must re-specify the list of interesting projects every time they + * are run as this is not carried forward beyond the next build. Missing + * projects should be specified but will be ignored until they are added to + * the workspace. + */ private IProject[] getRequiredProjects(boolean includeBinaryPrerequisites) { if (javaProject == null || workspaceRoot == null) return new IProject[0]; - ArrayList projects = new ArrayList(); try { IClasspathEntry[] entries = javaProject.getExpandedClasspath(true); @@ -350,11 +417,14 @@ public class PHPBuilder extends IncrementalProjectBuilder { IProject p = null; switch (entry.getEntryKind()) { case IClasspathEntry.CPE_PROJECT : - p = workspaceRoot.getProject(path.lastSegment()); // missing projects are considered too + p = workspaceRoot.getProject(path.lastSegment()); // missing + // projects are + // considered too break; case IClasspathEntry.CPE_LIBRARY : if (includeBinaryPrerequisites && path.segmentCount() > 1) { - // some binary resources on the class path can come from projects that are not included in the project references + // some binary resources on the class path can come from projects + // that are not included in the project references IResource resource = workspaceRoot.findMember(path.segment(0)); if (resource instanceof IProject) p = (IProject) resource; @@ -370,76 +440,89 @@ public class PHPBuilder extends IncrementalProjectBuilder { projects.toArray(result); return result; } - - private boolean hasClasspathChanged() { - ClasspathMultiDirectory[] newSourceLocations = nameEnvironment.sourceLocations; - ClasspathMultiDirectory[] oldSourceLocations = lastState.sourceLocations; - int newLength = newSourceLocations.length; - int oldLength = oldSourceLocations.length; - int n, o; - for (n = o = 0; n < newLength && o < oldLength; n++, o++) { - if (newSourceLocations[n].equals(oldSourceLocations[o])) - continue; // checks source & output folders - try { - if (newSourceLocations[n].sourceFolder.members().length == 0) { // added new empty source folder - o--; - continue; - } - } catch (CoreException ignore) { - } - if (DEBUG) - System.out.println(newSourceLocations[n] + " != " + oldSourceLocations[o]); //$NON-NLS-1$ - return true; - } - while (n < newLength) { - try { - if (newSourceLocations[n].sourceFolder.members().length == 0) { // added new empty source folder - n++; - continue; - } - } catch (CoreException ignore) { - } - if (DEBUG) - System.out.println("Added non-empty source folder"); //$NON-NLS-1$ - return true; - } - if (o < oldLength) { - if (DEBUG) - System.out.println("Removed source folder"); //$NON-NLS-1$ - return true; - } - - // ClasspathLocation[] newBinaryLocations = nameEnvironment.binaryLocations; - // ClasspathLocation[] oldBinaryLocations = lastState.binaryLocations; - // newLength = newBinaryLocations.length; - // oldLength = oldBinaryLocations.length; - // for (n = o = 0; n < newLength && o < oldLength; n++, o++) { - // if (newBinaryLocations[n].equals(oldBinaryLocations[o])) continue; - // if (DEBUG) - // System.out.println(newBinaryLocations[n] + " != " + oldBinaryLocations[o]); //$NON-NLS-1$ - // return true; - // } - // if (n < newLength || o < oldLength) { - // if (DEBUG) - // System.out.println("Number of binary folders/jar files has changed"); //$NON-NLS-1$ - // return true; - // } - return false; - } - +// private boolean hasClasspathChanged() { +// ClasspathMultiDirectory[] newSourceLocations = nameEnvironment.sourceLocations; +// ClasspathMultiDirectory[] oldSourceLocations = lastState.sourceLocations; +// int newLength = newSourceLocations.length; +// int oldLength = oldSourceLocations.length; +// int n, o; +// for (n = o = 0; n < newLength && o < oldLength; n++, o++) { +// if (newSourceLocations[n].equals(oldSourceLocations[o])) +// continue; // checks source & output folders +// try { +// if (newSourceLocations[n].sourceFolder.members().length == 0) { // added +// // new +// // empty +// // source +// // folder +// o--; +// continue; +// } +// } catch (CoreException ignore) { +// } +// if (DEBUG) +// System.out.println(newSourceLocations[n] + " != " +// + oldSourceLocations[o]); //$NON-NLS-1$ +// return true; +// } +// while (n < newLength) { +// try { +// if (newSourceLocations[n].sourceFolder.members().length == 0) { // added +// // new +// // empty +// // source +// // folder +// n++; +// continue; +// } +// } catch (CoreException ignore) { +// } +// if (DEBUG) +// System.out.println("Added non-empty source folder"); //$NON-NLS-1$ +// return true; +// } +// if (o < oldLength) { +// if (DEBUG) +// System.out.println("Removed source folder"); //$NON-NLS-1$ +// return true; +// } +// // ClasspathLocation[] newBinaryLocations = +// // nameEnvironment.binaryLocations; +// // ClasspathLocation[] oldBinaryLocations = lastState.binaryLocations; +// // newLength = newBinaryLocations.length; +// // oldLength = oldBinaryLocations.length; +// // for (n = o = 0; n < newLength && o < oldLength; n++, o++) { +// // if (newBinaryLocations[n].equals(oldBinaryLocations[o])) continue; +// // if (DEBUG) +// // System.out.println(newBinaryLocations[n] + " != " + +// // oldBinaryLocations[o]); //$NON-NLS-1$ +// // return true; +// // } +// // if (n < newLength || o < oldLength) { +// // if (DEBUG) +// // System.out.println("Number of binary folders/jar files has changed"); +// // //$NON-NLS-1$ +// // return true; +// // } +// return false; +// } private boolean hasStructuralDelta() { - // handle case when currentProject has only .class file folders and/or jar files... no source/output folders + // handle case when currentProject has only .class file folders and/or jar + // files... no source/output folders IResourceDelta delta = getDelta(currentProject); if (delta != null && delta.getKind() != IResourceDelta.NO_CHANGE) { - // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) binaryLocationsPerProject.get(currentProject); + // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) + // binaryLocationsPerProject.get(currentProject); // if (classFoldersAndJars != null) { // for (int i = 0, l = classFoldersAndJars.length; i < l; i++) { - // ClasspathLocation classFolderOrJar = classFoldersAndJars[i]; // either a .class file folder or a zip/jar file + // ClasspathLocation classFolderOrJar = classFoldersAndJars[i]; // either + // a .class file folder or a zip/jar file // if (classFolderOrJar != null) { // IPath p = classFolderOrJar.getProjectRelativePath(); // if (p != null) { // IResourceDelta binaryDelta = delta.findMember(p); - // if (binaryDelta != null && binaryDelta.getKind() != IResourceDelta.NO_CHANGE) + // if (binaryDelta != null && binaryDelta.getKind() != + // IResourceDelta.NO_CHANGE) // return true; // } // } @@ -448,24 +531,25 @@ public class PHPBuilder extends IncrementalProjectBuilder { } return false; } - private void initializeBuilder() throws CoreException { this.javaProject = (JavaProject) PHPCore.create(currentProject); this.workspaceRoot = currentProject.getWorkspace().getRoot(); - - // Flush the existing external files cache if this is the beginning of a build cycle + // Flush the existing external files cache if this is the beginning of a + // build cycle String projectName = currentProject.getName(); if (builtProjects == null || builtProjects.contains(projectName)) { JavaModel.flushExternalFileCache(); builtProjects = new ArrayList(); } builtProjects.add(projectName); - this.binaryLocationsPerProject = new SimpleLookupTable(3); - this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject, binaryLocationsPerProject); - - String filterSequence = javaProject.getOption(PHPCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true); - char[][] filters = filterSequence != null && filterSequence.length() > 0 ? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray()) : null; + this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject, + binaryLocationsPerProject); + String filterSequence = javaProject.getOption( + PHPCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true); + char[][] filters = filterSequence != null && filterSequence.length() > 0 + ? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray()) + : null; if (filters == null) { this.extraResourceFileFilters = null; this.extraResourceFolderFilters = null; @@ -487,112 +571,126 @@ public class PHPBuilder extends IncrementalProjectBuilder { if (f.length == 0) continue; if (f[f.length - 1] == '/') - extraResourceFolderFilters[--folderCount] = new String(CharOperation.subarray(f, 0, f.length - 1)); + extraResourceFolderFilters[--folderCount] = new String(CharOperation + .subarray(f, 0, f.length - 1)); else extraResourceFileFilters[--fileCount] = f; } } } - - private boolean isClasspathBroken(IClasspathEntry[] classpath, IProject p) throws CoreException { - if (classpath == JavaProject.INVALID_CLASSPATH) // the .classpath file could not be read + private boolean isClasspathBroken(IClasspathEntry[] classpath, IProject p) + throws CoreException { + if (classpath == JavaProject.INVALID_CLASSPATH) // the .classpath file + // could not be read return true; - - IMarker[] markers = p.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); + IMarker[] markers = p.findMarkers( + IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); for (int i = 0, l = markers.length; i < l; i++) if (((Integer) markers[i].getAttribute(IMarker.SEVERITY)).intValue() == IMarker.SEVERITY_ERROR) return true; return false; } - private boolean isWorthBuilding() throws CoreException { - boolean abortBuilds = PHPCore.ABORT.equals(javaProject.getOption(PHPCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, true)); + boolean abortBuilds = PHPCore.ABORT.equals(javaProject.getOption( + PHPCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, true)); if (!abortBuilds) return true; - // Abort build only if there are classpath errors -// if (isClasspathBroken(javaProject.getRawClasspath(), currentProject)) { -// if (DEBUG) -// System.out.println("Aborted build because project has classpath errors (incomplete or involved in cycle)"); //$NON-NLS-1$ -// -// JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(javaProject); -// -// removeProblemsAndTasksFor(currentProject); // remove all compilation problems -// -// IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); -// marker.setAttribute(IMarker.MESSAGE, Util.bind("build.abortDueToClasspathProblems")); //$NON-NLS-1$ -// marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); -// return false; -// } - - // make sure all prereq projects have valid build states... only when aborting builds since projects in cycles do not have build states + // if (isClasspathBroken(javaProject.getRawClasspath(), currentProject)) { + // if (DEBUG) + // System.out.println("Aborted build because project has classpath errors + // (incomplete or involved in cycle)"); //$NON-NLS-1$ + // + // JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(javaProject); + // + // removeProblemsAndTasksFor(currentProject); // remove all compilation + // problems + // + // IMarker marker = + // currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + // marker.setAttribute(IMarker.MESSAGE, + // Util.bind("build.abortDueToClasspathProblems")); //$NON-NLS-1$ + // marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); + // return false; + // } + // make sure all prereq projects have valid build states... only when + // aborting builds since projects in cycles do not have build states // except for projects involved in a 'warning' cycle (see below) IProject[] requiredProjects = getRequiredProjects(false); next : for (int i = 0, l = requiredProjects.length; i < l; i++) { IProject p = requiredProjects[i]; if (getLastState(p) == null) { - // The prereq project has no build state: if this prereq project has a 'warning' cycle marker then allow build (see bug id 23357) + // The prereq project has no build state: if this prereq project has a + // 'warning' cycle marker then allow build (see bug id 23357) JavaProject prereq = (JavaProject) PHPCore.create(p); - if (prereq.hasCycleMarker() && PHPCore.WARNING.equals(javaProject.getOption(PHPCore.CORE_CIRCULAR_CLASSPATH, true))) + if (prereq.hasCycleMarker() + && PHPCore.WARNING.equals(javaProject.getOption( + PHPCore.CORE_CIRCULAR_CLASSPATH, true))) continue; if (DEBUG) - System.out.println("Aborted build because prereq project " + p.getName() //$NON-NLS-1$ - +" was not built"); //$NON-NLS-1$ - - removeProblemsAndTasksFor(currentProject); // make this the only problem for this project - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, isClasspathBroken(prereq.getRawClasspath(), p) ? Util.bind("build.prereqProjectHasClasspathProblems", p.getName()) //$NON-NLS-1$ - : Util.bind("build.prereqProjectMustBeRebuilt", p.getName())); //$NON-NLS-1$ + System.out.println("Aborted build because prereq project " + + p.getName() //$NON-NLS-1$ + + " was not built"); //$NON-NLS-1$ + removeProblemsAndTasksFor(currentProject); // make this the only + // problem for this project + IMarker marker = currentProject + .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, isClasspathBroken(prereq + .getRawClasspath(), p) ? Util.bind( + "build.prereqProjectHasClasspathProblems", p.getName()) //$NON-NLS-1$ + : Util.bind("build.prereqProjectMustBeRebuilt", p.getName())); //$NON-NLS-1$ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); return false; } } return true; } - /* * Instruct the build manager that this project is involved in a cycle and * needs to propagate structural changes to the other projects in the cycle. */ void mustPropagateStructuralChanges() { HashSet cycleParticipants = new HashSet(3); - javaProject.updateCycleParticipants(null, new ArrayList(), cycleParticipants, workspaceRoot, new HashSet(3)); + javaProject.updateCycleParticipants(null, new ArrayList(), + cycleParticipants, workspaceRoot, new HashSet(3)); IPath currentPath = javaProject.getPath(); Iterator i = cycleParticipants.iterator(); while (i.hasNext()) { IPath participantPath = (IPath) i.next(); if (participantPath != currentPath) { - IProject project = this.workspaceRoot.getProject(participantPath.segment(0)); + IProject project = this.workspaceRoot.getProject(participantPath + .segment(0)); if (hasBeenBuilt(project)) { if (DEBUG) - System.out.println("Requesting another build iteration since cycle participant " + project.getName() //$NON-NLS-1$ - +" has not yet seen some structural changes"); //$NON-NLS-1$ + System.out + .println("Requesting another build iteration since cycle participant " + + project.getName() //$NON-NLS-1$ + + " has not yet seen some structural changes"); //$NON-NLS-1$ needRebuild(); return; } } } } - private void recordNewState(State state) { Object[] keyTable = binaryLocationsPerProject.keyTable; for (int i = 0, l = keyTable.length; i < l; i++) { IProject prereqProject = (IProject) keyTable[i]; if (prereqProject != null && prereqProject != currentProject) - state.recordStructuralDependency(prereqProject, getLastState(prereqProject)); + state.recordStructuralDependency(prereqProject, + getLastState(prereqProject)); } - if (DEBUG) System.out.println("Recording new state : " + state); //$NON-NLS-1$ // state.dump(); - JavaModelManager.getJavaModelManager().setLastBuiltState(currentProject, state); + JavaModelManager.getJavaModelManager().setLastBuiltState(currentProject, + state); } - /** * String representation for debugging purposes */ public String toString() { return currentProject == null ? "JavaBuilder for unknown project" //$NON-NLS-1$ - : "JavaBuilder for " + currentProject.getName(); //$NON-NLS-1$ + : "JavaBuilder for " + currentProject.getName(); //$NON-NLS-1$ } } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java index 2e76596..056edbe 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java @@ -1,5 +1,4 @@ package net.sourceforge.phpeclipse.builder; - import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.FileNotFoundException; @@ -16,52 +15,46 @@ import java.util.List; import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; - import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; import net.sourceforge.phpdt.core.compiler.InvalidInputException; import net.sourceforge.phpdt.internal.compiler.parser.Scanner; import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError; import net.sourceforge.phpdt.internal.compiler.util.Util; import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier; - import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; - /** * Manages the identifer index information for a specific project - * + * */ public class IdentifierIndexManager { - public class LineCreator implements ITerminalSymbols { - private Scanner fScanner; private int fToken; - public LineCreator() { fScanner = new Scanner(true, false); } - /** * Add the information of the current identifier to the line * - * @param typeOfIdentifier the type of the identifier ('c'lass, 'd'efine, 'f'unction, 'm'ethod, 'v'ariable) - * @param identifier current identifier - * @param line Buffer for the current index line - * @param phpdocOffset the offset of the PHPdoc comment if available - * @param phpdocLength the length of the PHPdoc comment if available + * @param typeOfIdentifier + * the type of the identifier ('c'lass, 'd'efine, 'f'unction, + * 'm'ethod, 'v'ariable) + * @param identifier + * current identifier + * @param line + * Buffer for the current index line + * @param phpdocOffset + * the offset of the PHPdoc comment if available + * @param phpdocLength + * the length of the PHPdoc comment if available */ - private void addIdentifierInformation( - char typeOfIdentifier, - char[] identifier, - StringBuffer line, - int phpdocOffset, - int phpdocLength) { - + private void addIdentifierInformation(char typeOfIdentifier, + char[] identifier, StringBuffer line, int phpdocOffset, int phpdocLength) { line.append('\t'); line.append(typeOfIdentifier); line.append(identifier); - line.append("\to"); // Offset + line.append("\to"); // Offset line.append(fScanner.getCurrentTokenStartPosition()); if (phpdocOffset >= 0) { line.append("\tp"); // phpdoc offset @@ -69,7 +62,6 @@ public class IdentifierIndexManager { line.append("\tl"); // phpdoc length line.append(phpdocLength); } - } /** * Get the next token from input @@ -80,8 +72,8 @@ public class IdentifierIndexManager { if (Scanner.DEBUG) { int currentEndPosition = fScanner.getCurrentTokenEndPosition(); int currentStartPosition = fScanner.getCurrentTokenStartPosition(); - - System.out.print(currentStartPosition + "," + currentEndPosition + ": "); + System.out.print(currentStartPosition + "," + currentEndPosition + + ": "); System.out.println(fScanner.toStringAction(fToken)); } return; @@ -90,32 +82,34 @@ public class IdentifierIndexManager { } fToken = TokenNameERROR; } - - private void parseDeclarations(char[] parent, StringBuffer buf, boolean goBack) { + private void parseDeclarations(char[] parent, StringBuffer buf, + boolean goBack) { char[] ident; char[] classVariable; int counter = 0; int phpdocOffset = -1; int phpdocLength = -1; - try { while (fToken != TokenNameEOF && fToken != TokenNameERROR) { phpdocOffset = -1; if (fToken == TokenNameCOMMENT_PHPDOC) { phpdocOffset = fScanner.getCurrentTokenStartPosition(); - phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1; + phpdocLength = fScanner.getCurrentTokenEndPosition() + - fScanner.getCurrentTokenStartPosition() + 1; getNextToken(); if (fToken == TokenNameEOF || fToken == TokenNameERROR) { break; } } - if (fToken == TokenNamevar) { + if (fToken == TokenNamevar || fToken == TokenNamepublic + || fToken == TokenNameprotected || fToken == TokenNameprivate) { getNextToken(); if (fToken == TokenNameVariable) { ident = fScanner.getCurrentIdentifierSource(); classVariable = new char[ident.length - 1]; System.arraycopy(ident, 1, classVariable, 0, ident.length - 1); - addIdentifierInformation('v', classVariable, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('v', classVariable, buf, phpdocOffset, + phpdocLength); getNextToken(); } } else if (fToken == TokenNamefunction) { @@ -127,14 +121,17 @@ public class IdentifierIndexManager { ident = fScanner.getCurrentIdentifierSource(); if (parent != null && equalCharArrays(parent, ident)) { // constructor function - addIdentifierInformation('k', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('k', ident, buf, phpdocOffset, + phpdocLength); } else { if (parent != null) { // class method function - addIdentifierInformation('m', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('m', ident, buf, phpdocOffset, + phpdocLength); } else { // nested function ?! - addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('f', ident, buf, phpdocOffset, + phpdocLength); } } getNextToken(); @@ -144,26 +141,39 @@ public class IdentifierIndexManager { getNextToken(); if (fToken == TokenNameIdentifier) { ident = fScanner.getCurrentIdentifierSource(); - addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('c', ident, buf, phpdocOffset, + phpdocLength); getNextToken(); - - //skip tokens for classname, extends and others until we have the opening '{' - while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) { + //skip tokens for classname, extends and others until we have + // the opening '{' + while (fToken != TokenNameLBRACE && fToken != TokenNameEOF + && fToken != TokenNameERROR) { getNextToken(); } parseDeclarations(ident, buf, true); } - } else if (fToken == TokenNamedefine) { + } else if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); getNextToken(); - if (fToken == TokenNameLPAREN) { - getNextToken(); - if (fToken == TokenNameStringLiteral) { - ident = fScanner.getCurrentStringLiteralSource(); - addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength); + if (ident.length==6 && + ident[0]=='d' && + ident[1]=='e' && + ident[2]=='f' && + ident[3]=='i' && + ident[4]=='n' && + ident[5]=='e') { + if (fToken == TokenNameLPAREN) { getNextToken(); + if (fToken == TokenNameStringLiteral) { + ident = fScanner.getCurrentStringLiteralSource(); + addIdentifierInformation('d', ident, buf, phpdocOffset, + phpdocLength); + getNextToken(); + } } } - } else if ((fToken == TokenNameLBRACE) || (fToken == TokenNameDOLLAR_LBRACE)) { + } else if ((fToken == TokenNameLBRACE) + || (fToken == TokenNameDOLLAR_LBRACE)) { getNextToken(); counter++; } else if (fToken == TokenNameRBRACE) { @@ -181,25 +191,23 @@ public class IdentifierIndexManager { e.printStackTrace(); } } - public void parseIdentifiers(char[] charArray, StringBuffer buf) { char[] ident; String identifier; int counter = 0; int phpdocOffset = -1; int phpdocLength = -1; - fScanner.setSource(charArray); fScanner.setPHPMode(false); fToken = TokenNameEOF; getNextToken(); - try { while (fToken != TokenNameEOF && fToken != TokenNameERROR) { phpdocOffset = -1; if (fToken == TokenNameCOMMENT_PHPDOC) { phpdocOffset = fScanner.getCurrentTokenStartPosition(); - phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1; + phpdocLength = fScanner.getCurrentTokenEndPosition() + - fScanner.getCurrentTokenStartPosition() + 1; getNextToken(); if (fToken == TokenNameEOF || fToken == TokenNameERROR) { break; @@ -212,7 +220,8 @@ public class IdentifierIndexManager { } if (fToken == TokenNameIdentifier) { ident = fScanner.getCurrentIdentifierSource(); - addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('f', ident, buf, phpdocOffset, + phpdocLength); getNextToken(); parseDeclarations(null, buf, true); } @@ -220,25 +229,35 @@ public class IdentifierIndexManager { getNextToken(); if (fToken == TokenNameIdentifier) { ident = fScanner.getCurrentIdentifierSource(); - addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength); + addIdentifierInformation('c', ident, buf, phpdocOffset, + phpdocLength); getNextToken(); - - //skip fTokens for classname, extends and others until we have the opening '{' - while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) { + //skip fTokens for classname, extends and others until we have + // the opening '{' + while (fToken != TokenNameLBRACE && fToken != TokenNameEOF + && fToken != TokenNameERROR) { getNextToken(); } - parseDeclarations(ident, buf, true); - } - } else if (fToken == TokenNamedefine) { + } else if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); getNextToken(); - if (fToken == TokenNameLPAREN) { - getNextToken(); - if (fToken == TokenNameStringLiteral) { - ident = fScanner.getCurrentStringLiteralSource(); - addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength); + if (ident.length==6 && + ident[0]=='d' && + ident[1]=='e' && + ident[2]=='f' && + ident[3]=='i' && + ident[4]=='n' && + ident[5]=='e') { + if (fToken == TokenNameLPAREN) { getNextToken(); + if (fToken == TokenNameStringLiteral) { + ident = fScanner.getCurrentStringLiteralSource(); + addIdentifierInformation('d', ident, buf, phpdocOffset, + phpdocLength); + getNextToken(); + } } } } else { @@ -251,30 +270,26 @@ public class IdentifierIndexManager { } } } - class StringComparator implements Comparator { public int compare(Object o1, Object o2) { String s1 = (String) o1; String s2 = (String) o2; return s1.compareTo(s2); - // return s1.toUpperCase().compareTo(s2.toUpperCase()); + // return s1.toUpperCase().compareTo(s2.toUpperCase()); } public boolean equals(Object o) { String s = (String) o; return compare(this, o) == 0; } } - private HashMap fFileMap; private String fFilename; private TreeMap fIndentifierMap; - public IdentifierIndexManager(String filename) { fFilename = filename; initialize(); readFile(); } - /** * Check if 2 char arrays are equal * @@ -293,10 +308,9 @@ public class IdentifierIndexManager { } return true; } - /** * Add the information for a given IFile resource - * + * */ public void addFile(IFile fileToParse) { // InputStream iStream; @@ -316,12 +330,13 @@ public class IdentifierIndexManager { InputStream stream = null; try { stream = new BufferedInputStream(fileToParse.getContents()); - StringBuffer lineBuffer = new StringBuffer(); lineBuffer.append(fileToParse.getFullPath().toString()); int lineLength = lineBuffer.length(); - // lineCreator.parseIdentifiers(buf.toString().toCharArray(), lineBuffer); - lineCreator.parseIdentifiers(Util.getInputStreamAsCharArray(stream, -1, null), lineBuffer); + // lineCreator.parseIdentifiers(buf.toString().toCharArray(), + // lineBuffer); + lineCreator.parseIdentifiers(Util.getInputStreamAsCharArray(stream, -1, + null), lineBuffer); if (lineLength != lineBuffer.length()) { addLine(lineBuffer.toString()); } @@ -340,9 +355,9 @@ public class IdentifierIndexManager { e1.printStackTrace(); } } - /** - * Adds a line of the index file for function, class, class-method and class-variable names + * Adds a line of the index file for function, class, class-method and + * class-variable names * * @param line */ @@ -355,7 +370,6 @@ public class IdentifierIndexManager { String offset = null; PHPIdentifierLocation phpIdentifier = null; boolean tokenExists = false; - tokenizer = new StringTokenizer(line, "\t"); // first token contains the filename: if (tokenizer.hasMoreTokens()) { @@ -369,46 +383,61 @@ public class IdentifierIndexManager { token = tokenizer.nextToken(); //System.out.println(token); switch (token.charAt(0)) { - case 'c' : // class name + case 'c' : + // class name identifier = token.substring(1); classname = identifier; - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CLASS, phpFileName); break; - case 'd' : // define + case 'd' : + // define identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.DEFINE, phpFileName); break; - case 'f' : // function name + case 'f' : + // function name identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.FUNCTION, phpFileName); break; - case 'k' : // constructor function name + case 'k' : + // constructor function name identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CONSTRUCTOR, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CONSTRUCTOR, phpFileName); break; - case 'm' : //method inside a class + case 'm' : + //method inside a class identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.METHOD, phpFileName, classname); break; - case 'v' : // variable inside a class + case 'v' : + // variable inside a class identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.VARIABLE, phpFileName, classname); break; - case 'o' : // offset information + case 'o' : + // offset information identifier = null; if (phpIdentifier != null) { offset = token.substring(1); phpIdentifier.setOffset(Integer.parseInt(offset)); } break; - case 'p' : // PHPdoc offset information + case 'p' : + // PHPdoc offset information identifier = null; if (phpIdentifier != null) { offset = token.substring(1); phpIdentifier.setPHPDocOffset(Integer.parseInt(offset)); } break; - case 'l' : // PHPdoc length information + case 'l' : + // PHPdoc length information identifier = null; if (phpIdentifier != null) { offset = token.substring(1); @@ -445,18 +474,17 @@ public class IdentifierIndexManager { fFileMap.put(phpFileName, line); } } - /** * Change the information for a given IFile resource - * + * */ public void changeFile(IFile fileToParse) { removeFile(fileToParse); addFile(fileToParse); } - /** - * Get a list of all PHPIdentifierLocation object's associated with an identifier + * Get a list of all PHPIdentifierLocation object's associated with an + * identifier * * @param identifier * @return @@ -464,24 +492,19 @@ public class IdentifierIndexManager { public List getLocations(String identifier) { return (List) fIndentifierMap.get(identifier); } - /** * Initialize (i.e. clear) the current index information - * + * */ public void initialize() { fIndentifierMap = new TreeMap(new StringComparator()); fFileMap = new HashMap(); } - private void readFile() { - FileReader fileReader; try { fileReader = new FileReader(fFilename); - BufferedReader bufferedReader = new BufferedReader(fileReader); - String line; while (bufferedReader.ready()) { // all entries for one file are in a line @@ -489,7 +512,6 @@ public class IdentifierIndexManager { line = bufferedReader.readLine(); addLine(line); } - fileReader.close(); } catch (FileNotFoundException e) { // ignore this @@ -498,23 +520,22 @@ public class IdentifierIndexManager { // TODO Auto-generated catch block e.printStackTrace(); } - } - /** * Remove the information for a given IFile resource - * + * */ public void removeFile(IFile fileToParse) { - // String line = (String) fFileMap.get(fileToParse.getLocation().toString()); + // String line = (String) + // fFileMap.get(fileToParse.getLocation().toString()); String line = (String) fFileMap.get(fileToParse.getFullPath().toString()); if (line != null) { removeLine(line); } } - /** - * Removes a line of the index file for function, class, class-method and class-variable names + * Removes a line of the index file for function, class, class-method and + * class-variable names * * @param line */ @@ -526,7 +547,6 @@ public class IdentifierIndexManager { String classname = null; PHPIdentifier phpIdentifier = null; boolean tokenExists = false; - tokenizer = new StringTokenizer(line, "\t"); // first token contains the filename: if (tokenizer.hasMoreTokens()) { @@ -540,30 +560,42 @@ public class IdentifierIndexManager { token = tokenizer.nextToken(); //System.out.println(token); switch (token.charAt(0)) { - case 'c' : // class name + case 'c' : + // class name identifier = token.substring(1); classname = identifier; - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CLASS, phpFileName); break; - case 'd' : // define + case 'd' : + // define identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.DEFINE, phpFileName); break; - case 'f' : // function name + case 'f' : + // function name identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.FUNCTION, phpFileName); break; - case 'k' : // constructor function name + case 'k' : + // constructor function name identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CONSTRUCTOR, phpFileName); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CONSTRUCTOR, phpFileName); break; - case 'm' : //method inside a class + case 'm' : + //method inside a class identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.METHOD, phpFileName, classname); break; - case 'v' : // variable inside a class + case 'v' : + // variable inside a class identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.VARIABLE, phpFileName, classname); break; default : identifier = null; @@ -588,10 +620,9 @@ public class IdentifierIndexManager { } fFileMap.remove(phpFileName); } - /** * Save the current index information in the projects index file - * + * */ public void writeFile() { FileWriter fileWriter; @@ -612,7 +643,6 @@ public class IdentifierIndexManager { e.printStackTrace(); } } - /** * @param fromKey * @param toKey @@ -621,5 +651,4 @@ public class IdentifierIndexManager { public SortedMap getIdentifierMap() { return fIndentifierMap; } - } \ No newline at end of file -- 1.7.1