import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.SourceLocation;
-import org.aspectj.util.FileUtil;
-import org.aspectj.weaver.bcel.UnwovenClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
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.UnwovenClassFile;
/**
public class AjState {
AjBuildManager buildManager;
+ // static so beware of multi-threading bugs...
+ public static IStateListener stateListener = null;
+
long lastSuccessfulBuildTime = -1;
long currentBuildTime = -1;
AjBuildConfig buildConfig;
// coming - otherwise a file that has been deleted from an inpath jar
// since the last build will not be deleted from the output directory.
removeAllResultsOfLastBuild();
+ if (stateListener!=null) stateListener.pathChangeDetected();
return false;
}
});
for (int i = 0; i < classFiles.length; i++) {
long modTime = classFiles[i].lastModified();
- if (modTime + 1000 >= lastSuccessfulBuildTime) return true;
+ if (modTime + 1000 >= lastSuccessfulBuildTime) {
+ return true;
+ }
}
return false;
}
boolean changed = false;
List oldClasspath = oldConfig.getClasspath();
List newClasspath = newConfig.getClasspath();
- if (changed(oldClasspath,newClasspath,true)) return true;
+ if (stateListener!=null) stateListener.aboutToCompareClasspaths(oldClasspath,newClasspath);
+ if (changed(oldClasspath,newClasspath,true,oldConfig.getOutputDir())) return true;
List oldAspectpath = oldConfig.getAspectpath();
List newAspectpath = newConfig.getAspectpath();
- if (changed(oldAspectpath,newAspectpath,true)) return true;
+ if (changed(oldAspectpath,newAspectpath,true,oldConfig.getOutputDir())) return true;
List oldInJars = oldConfig.getInJars();
List newInJars = newConfig.getInJars();
- if (changed(oldInJars,newInJars,false)) return true;
+ if (changed(oldInJars,newInJars,false,oldConfig.getOutputDir())) return true;
List oldInPath = oldConfig.getInpath();
List newInPath = newConfig.getInpath();
- if (changed(oldInPath, newInPath,false)) return true;
+ if (changed(oldInPath, newInPath,false,oldConfig.getOutputDir())) return true;
return changed;
}
- private boolean changed(List oldPath, List newPath, boolean checkClassFiles) {
+ private boolean changed(List oldPath, List newPath, boolean checkClassFiles, File oldOutputLocation) {
if (oldPath == null) oldPath = new ArrayList();
if (newPath == null) newPath = new ArrayList();
if (oldPath.size() != newPath.size()) {
if (f.exists() && !f.isDirectory() && (f.lastModified() >= lastSuccessfulBuildTime)) {
return true;
}
- if (f.exists() && f.isDirectory() && checkClassFiles) {
- return classFileChangedInDirSinceLastBuild(f);
+ if (f.exists() && f.isDirectory() && checkClassFiles && !(f.equals(oldOutputLocation))) {
+ boolean b= classFileChangedInDirSinceLastBuild(f);
+ if (b && stateListener!=null) stateListener.detectedClassChangeInThisDir(f);
+ if (b) return true;
}
}
return false;
addDependentsOf(intRes.unwovenClassFiles()[i].getClassName());
}
}
+
}
--- /dev/null
+/**
+ * Copyright (c) 2005 IBM and other contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+
+package org.aspectj.ajdt.internal.core.builder;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Implementations of this interface get told interesting information about
+ * decisions made in AjState objects. Should help us improve incremental
+ * compilation, and ease the testing of incremental compilation!
+ *
+ * Not yet complete, will expand as we determine what extra useful information
+ * should be recorded.
+ *
+ * @author AndyClement
+ */
+public interface IStateListener {
+
+ public void detectedClassChangeInThisDir(File f);
+
+ public void aboutToCompareClasspaths(List oldClasspath, List newClasspath);
+
+ public void pathChangeDetected();
+
+}
package org.aspectj.systemtest.incremental;
import java.io.File;
+import java.util.List;
import junit.framework.Test;
+import org.aspectj.ajdt.internal.core.builder.AjState;
+import org.aspectj.ajdt.internal.core.builder.IStateListener;
import org.aspectj.testing.XMLBasedAjcTestCase;
public class IncrementalTests extends org.aspectj.testing.XMLBasedAjcTestCase {
copyFileAndDoIncrementalBuild("changes/Main.20.java","src/app/Main.java");
run("app.Main");
}
+
+ /**
+ * See bug report 85297. We plugged a hole so that we check whether the contents of
+ * directories on the classpath have changed when deciding whether we can do an
+ * incremental build or not - the implementation didn't allow for the output location
+ * being on the classpath. This test verifies the fix is OK
+ */
+ public void testIncrementalOKWithOutputPathOnClasspath() throws Exception {
+ class MyStateListener implements IStateListener {
+ public boolean pathChange = false;
+ public void pathChangeDetected() {pathChange = true;}
+ public void aboutToCompareClasspaths(List oldClasspath, List newClasspath) {}
+ public void detectedClassChangeInThisDir(File f) {}
+ };
+ MyStateListener sl = new MyStateListener();
+ AjState.stateListener = sl;
+ runTest("change source");
+ nextIncrement(false);
+ copyFileAndDoIncrementalBuild("changes/Main.20.java","src/app/Main.java");
+ assertTrue("Did not expect a path change to be detected ",!sl.pathChange);
+ run("app.Main");
+ }
public void test009() throws Exception {
runTest("incrementally change only string literal, still expect advice");