From: aclement Date: Tue, 26 Apr 2005 18:08:28 +0000 (+0000) Subject: MultiIncrementalSupport: state that was scattered across the hierarchy has been pulle... X-Git-Tag: PRE_ANDY~420 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e7f4844541b00ce04f5c710e9022db9b47e5027c;p=aspectj.git MultiIncrementalSupport: state that was scattered across the hierarchy has been pulled into AjState - it now captures everything unique about a particular build of a project. --- diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java index a747db5cd..97d85e4a0 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java @@ -20,12 +20,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.aspectj.ajdt.internal.compiler.InterimCompilationResult; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IRelationshipMap; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.Message; import org.aspectj.bridge.SourceLocation; @@ -35,6 +38,8 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatExcepti import org.aspectj.org.eclipse.jdt.internal.core.builder.ReferenceCollection; import org.aspectj.org.eclipse.jdt.internal.core.builder.StringSet; import org.aspectj.util.FileUtil; +import org.aspectj.weaver.bcel.BcelWeaver; +import org.aspectj.weaver.bcel.BcelWorld; import org.aspectj.weaver.bcel.UnwovenClassFile; @@ -44,11 +49,18 @@ import org.aspectj.weaver.bcel.UnwovenClassFile; public class AjState { AjBuildManager buildManager; - // static so beware of multi-threading bugs... + // SECRETAPI static so beware of multi-threading bugs... public static IStateListener stateListener = null; + + private IHierarchy structureModel; + private IRelationshipMap relmap; + + private long lastSuccessfulFullBuildTime = -1; + private Hashtable /* File, long */ structuralChangesSinceLastFullBuild = new Hashtable(); + + private long lastSuccessfulBuildTime = -1; + private long currentBuildTime = -1; - long lastSuccessfulBuildTime = -1; - long currentBuildTime = -1; AjBuildConfig buildConfig; AjBuildConfig newBuildConfig; @@ -68,15 +80,20 @@ public class AjState { Set /*BinarySourceFile*/addedBinaryFiles; Set /*BinarySourceFile*/deletedBinaryFiles; + private BcelWeaver weaver; + private BcelWorld world; + List addedClassFiles; public AjState(AjBuildManager buildManager) { this.buildManager = buildManager; } - void successfulCompile(AjBuildConfig config) { + void successfulCompile(AjBuildConfig config,boolean wasFullBuild) { buildConfig = config; lastSuccessfulBuildTime = currentBuildTime; + if (stateListener!=null) stateListener.buildSuccessful(wasFullBuild); + if (wasFullBuild) lastSuccessfulFullBuildTime = currentBuildTime; } /** @@ -88,11 +105,15 @@ public class AjState { addedClassFiles = new ArrayList(); if (lastSuccessfulBuildTime == -1 || buildConfig == null) { + structuralChangesSinceLastFullBuild.clear(); return false; } // we don't support incremental with an outjar yet - if (newBuildConfig.getOutputJar() != null) return false; + if (newBuildConfig.getOutputJar() != null) { + structuralChangesSinceLastFullBuild.clear(); + return false; + } // we can't do an incremental build if one of our paths // has changed, or a jar on a path has been modified @@ -104,6 +125,7 @@ public class AjState { // since the last build will not be deleted from the output directory. removeAllResultsOfLastBuild(); if (stateListener!=null) stateListener.pathChangeDetected(); + structuralChangesSinceLastFullBuild.clear(); return false; } @@ -175,22 +197,53 @@ public class AjState { } private boolean classFileChangedInDirSinceLastBuild(File dir) { - File[] classFiles = FileUtil.listFiles(dir, new FileFilter(){ - + // Is another process building into that directory? + AjState state = IncrementalStateManager.findStateManagingOutputLocation(dir); + + File[] classFiles = FileUtil.listFiles(dir, new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".class"); } - }); + for (int i = 0; i < classFiles.length; i++) { long modTime = classFiles[i].lastModified(); - if (modTime + 1000 >= lastSuccessfulBuildTime) { - return true; + if ((modTime+1000)>=lastSuccessfulBuildTime) { + // so the class on disk has changed since our last successful build + + // To work out if it is a real change we should ask any state + // object managing this output location whether the file has + // structurally changed or not + if (state!=null) { + boolean realChange = state.hasStructuralChangedSince(classFiles[i],lastSuccessfulBuildTime); + if (realChange) return true; + } else { + // FIXME asc you should ask Eclipse project state here... + return true; // no state object to ask so it must have changed + } } } return false; } + /** + * Determine if a file has changed since a given time, using the local information + * recorded in the structural changes data structure. + * + * file is the file we are wondering about + * lastSBT is the last build time for the state asking the question + */ + private boolean hasStructuralChangedSince(File file,long lastSuccessfulBuildTime) { + long lastModTime = file.lastModified(); + Long l = (Long)structuralChangesSinceLastFullBuild.get(file.getAbsolutePath()); + long strucModTime = -1; + if (l!=null) strucModTime = l.longValue(); + else strucModTime = this.lastSuccessfulFullBuildTime; + // we now have: + // 'strucModTime'-> the last time the class was structurally changed + return (strucModTime>lastSuccessfulBuildTime); + } + private boolean pathChange(AjBuildConfig oldConfig, AjBuildConfig newConfig) { boolean changed = false; List oldClasspath = oldConfig.getClasspath(); @@ -408,7 +461,7 @@ public class AjState { private void deleteClassFile(UnwovenClassFile classFile) { classesFromName.remove(classFile.getClassName()); - buildManager.bcelWeaver.deleteClassFile(classFile.getClassName()); + weaver.deleteClassFile(classFile.getClassName()); try { classFile.deleteRealFile(); } catch (IOException e) { @@ -419,7 +472,7 @@ public class AjState { private UnwovenClassFile createUnwovenClassFile(AjBuildConfig.BinarySourceFile bsf) { UnwovenClassFile ucf = null; try { - ucf = buildManager.bcelWeaver.addClassFile(bsf.binSrc, bsf.fromInPathDirectory, buildConfig.getOutputDir()); + ucf = weaver.addClassFile(bsf.binSrc, bsf.fromInPathDirectory, buildConfig.getOutputDir()); } catch(IOException ex) { IMessage msg = new Message("can't read class file " + bsf.binSrc.getPath(), new SourceLocation(bsf.binSrc,0),false); @@ -486,7 +539,9 @@ public class AjState { try { ClassFileReader reader = new ClassFileReader(oldBytes, lastTime.getFilename().toCharArray()); // ignore local types since they're only visible inside a single method - if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) { + if (!(reader.isLocal() || reader.isAnonymous()) && + reader.hasStructuralChanges(newBytes)) { + structuralChangesSinceLastFullBuild.put(thisTime.getFilename(),new Long(currentBuildTime)); addDependentsOf(lastTime.getClassName()); } } catch (ClassFormatException e) { @@ -649,4 +704,35 @@ public class AjState { } } + public void setStructureModel(IHierarchy model) { + structureModel = model; + } + + public IHierarchy getStructureModel() { + return structureModel; + } + + public void setWeaver(BcelWeaver bw) { weaver=bw;} + public BcelWeaver getWeaver() {return weaver;} + + public void setWorld(BcelWorld bw) {world=bw;} + public BcelWorld getBcelWorld() {return world; } + + public void setRelationshipMap(IRelationshipMap irm) { relmap = irm;} + public IRelationshipMap getRelationshipMap() { return relmap;} + + public int getNumberOfStructuralChangesSinceLastFullBuild() { + return structuralChangesSinceLastFullBuild.size(); + } + + /** Returns last time we did a full or incremental build. */ + public long getLastBuildTime() { + return lastSuccessfulBuildTime; + } + + /** Returns last time we did a full build */ + public long getLastFullBuildTime() { + return lastSuccessfulFullBuildTime; + } + }