diff options
author | acolyer <acolyer> | 2006-02-10 17:53:34 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2006-02-10 17:53:34 +0000 |
commit | b03d4bb299917983d2c104e818f014e3743f4c17 (patch) | |
tree | 60f151a5106f1029273ddc7918a860f1b31ad91d /org.aspectj.ajdt.core | |
parent | 5f41f5d56a7c6a4b76660697848177aea06273a0 (diff) | |
download | aspectj-b03d4bb299917983d2c104e818f014e3743f4c17.tar.gz aspectj-b03d4bb299917983d2c104e818f014e3743f4c17.zip |
don't hold eclipse source types in ajstate
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r-- | org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java | 28 | ||||
-rw-r--r-- | org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java | 264 |
2 files changed, 225 insertions, 67 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java index caa4f2d7e..4e5230a91 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java @@ -44,6 +44,7 @@ import org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor; import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider; import org.aspectj.ajdt.internal.compiler.InterimCompilationResult; import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment; +import org.aspectj.ajdt.internal.compiler.lookup.AnonymousClassPublisher; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter; import org.aspectj.asm.AsmManager; @@ -176,6 +177,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc if (baseHandler instanceof ILifecycleAware) { ((ILifecycleAware)baseHandler).buildStarting(!batch); } + CompilationAndWeavingContext.reset(); int phase = batch ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD; ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase ,buildConfig); try { @@ -260,6 +262,11 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc CompilationAndWeavingContext.leavingPhase(ct); return false; } + + if (state.requiresFullBatchBuild()) { + return batchBuild(buildConfig, baseHandler); + } + binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(false); files = state.getFilesToCompile(false); hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty()); @@ -829,6 +836,8 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc handler.handleMessage(new Message("build cancelled:"+oce.getMessage(),IMessage.WARNING,null,null)); } // cleanup + org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(null); + AnonymousClassPublisher.aspectOf().setAnonymousClassCreationListener(null); environment.cleanup(); environment = null; } @@ -1108,6 +1117,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc */ public ICompilerAdapter getAdapter(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) { // complete compiler config and return a suitable adapter... + populateCompilerOptionsFromLintSettings(forCompiler); AjProblemReporter pr = new AjProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(), forCompiler.options, getProblemFactory()); @@ -1134,10 +1144,24 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc this, // IOutputFilenameProvider this, // IBinarySourceProvider state.getBinarySourceMap(), - state.getResultSetToUseForFullWeave(), buildConfig.isNoWeave(), buildConfig.getProceedOnError(), - buildConfig.isNoAtAspectJAnnotationProcessing()); + buildConfig.isNoAtAspectJAnnotationProcessing(), + state); + } + + /** + * Some AspectJ lint options need to be known about in the compiler. This is + * how we pass them over... + * @param forCompiler + */ + private void populateCompilerOptionsFromLintSettings(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) { + BcelWorld world = this.state.getBcelWorld(); + IMessage.Kind swallowedExceptionKind = world.getLint().swallowedExceptionInCatchBlock.getKind(); + Map optionsMap = new HashMap(); + optionsMap.put(CompilerOptions.OPTION_ReportSwallowedExceptionInCatchBlock, + swallowedExceptionKind == null ? "ignore" : swallowedExceptionKind.toString()); + forCompiler.options.set(optionsMap); } /* (non-Javadoc) 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 48f0f28ef..e47215ace 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 @@ -15,6 +15,7 @@ package org.aspectj.ajdt.internal.core.builder; import java.io.File; import java.io.FileFilter; +import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -38,6 +39,7 @@ 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.IWeaver; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.bcel.BcelWeaver; import org.aspectj.weaver.bcel.BcelWorld; @@ -64,29 +66,27 @@ public class AjState { private AjBuildConfig buildConfig; + private boolean batchBuildRequiredThisTime = false; + /** - * Holds the CompilationResult produced by JDT as a result of compiling the given - * source file. InterimCompilationResults are *very* memory intensive and we would - * like to release them as soon as possible (currently they are retained in memory - * until the next full build). - * - * Populated in noteResult which adds an InterimCompilationResult (post JDT compile, - * but pre-weave). - * - * The values() of this Map are passed to AjCompilerAdaptor as the result set to - * use if the weaver indicates that a full weave is required. + * Keeps a list of (FQN,Filename) pairs (as ClassFile objects) + * for types that resulted from the compilation of the given + * File. * - * In incremental building, used by addDependentsOf(File) to compute the compile set - * when a given file has been added or modified. + * Populated in noteResult and used in addDependentsOf(File) * - * When processing deleted files, this map is used to see if any of the compilation units - * that came from that file were aspects, and if so, to trigger a full build. + * Added by AMC during state refactoring, 1Q06. + */ + private Map/*<File, List<ClassFile>*/ fullyQualifiedTypeNamesResultingFromCompilationUnit = new HashMap(); + + /** + * Source files defining aspects * - * When deleting class files in preparation for a full build, entries are removed - * from the map. + * Populated in noteResult and used in processDeletedFiles * + * Added by AMC during state refactoring, 1Q06. */ - private Map/*<File, InterimCompilationResult*/ resultsFromFile = new HashMap(); + private Set sourceFilesDefiningAspects = new HashSet(); /** * Populated in noteResult to record the set of types that should be recompiled if @@ -163,6 +163,11 @@ public class AjState { boolean prepareForNextBuild(AjBuildConfig newBuildConfig) { currentBuildTime = System.currentTimeMillis(); + if (this.batchBuildRequiredThisTime) { + this.batchBuildRequiredThisTime = false; + return false; + } + if (lastSuccessfulBuildTime == -1 || buildConfig == null) { structuralChangesSinceLastFullBuild.clear(); return false; @@ -224,20 +229,10 @@ public class AjState { private boolean processDeletedFiles(Set deletedFiles) { for (Iterator iter = deletedFiles.iterator(); iter.hasNext();) { File aDeletedFile = (File ) iter.next(); - InterimCompilationResult cr = (InterimCompilationResult)resultsFromFile.get(aDeletedFile); - if (cr!=null) { - Map compiledTypes = cr.result().compiledTypes; - if (compiledTypes!=null) { - for (Iterator iterator = compiledTypes.keySet().iterator(); iterator.hasNext();) { - char[] className = (char[])iterator.next(); - ResolvedType rt = world.resolve(new String(className).replace('/','.')); - if (rt.isAspect()) { - removeAllResultsOfLastBuild(); - if (stateListener!=null) stateListener.detectedAspectDeleted(aDeletedFile); - return false; - } - } - } + if (this.sourceFilesDefiningAspects.contains(aDeletedFile)) { + removeAllResultsOfLastBuild(); + if (stateListener!=null) stateListener.detectedAspectDeleted(aDeletedFile); + return false; } } return true; @@ -470,15 +465,18 @@ public class AjState { private void deleteClassFiles() { for (Iterator i = deletedFiles.iterator(); i.hasNext(); ) { File deletedFile = (File)i.next(); - //System.out.println("deleting: " + deletedFile); addDependentsOf(deletedFile); - InterimCompilationResult intRes = (InterimCompilationResult) resultsFromFile.get(deletedFile); - resultsFromFile.remove(deletedFile); - //System.out.println("deleting: " + unwovenClassFiles); - if (intRes == null) continue; - for (int j=0; j<intRes.unwovenClassFiles().length; j++ ) { - deleteClassFile(intRes.unwovenClassFiles()[j]); + + List cfs = (List) this.fullyQualifiedTypeNamesResultingFromCompilationUnit.get(deletedFile); + this.fullyQualifiedTypeNamesResultingFromCompilationUnit.remove(deletedFile); + + if (cfs != null) { + for (Iterator iter = cfs.iterator(); iter.hasNext();) { + ClassFile cf = (ClassFile) iter.next(); + deleteClassFile(cf); + } } + } } @@ -488,7 +486,13 @@ public class AjState { AjBuildConfig.BinarySourceFile deletedFile = (AjBuildConfig.BinarySourceFile) iter.next(); List ucfs = (List) binarySourceFiles.get(deletedFile.binSrc.getPath()); binarySourceFiles.remove(deletedFile.binSrc.getPath()); - deleteClassFile((UnwovenClassFile)ucfs.get(0)); + + // AMC temp during refactoring + UnwovenClassFile ucf = (UnwovenClassFile) ucfs.get(0); + ClassFile cf = new ClassFile(ucf.getClassName(),new File(ucf.getFilename())); + // end temp + + deleteClassFile(cf); } } @@ -552,16 +556,10 @@ public class AjState { } } - - private void deleteClassFile(UnwovenClassFile classFile) { - classesFromName.remove(classFile.getClassName()); - - weaver.deleteClassFile(classFile.getClassName()); - try { - classFile.deleteRealFile(); - } catch (IOException e) { - //!!! might be okay to ignore - } + private void deleteClassFile(ClassFile cf) { + classesFromName.remove(cf.fullyQualifiedTypeName); + weaver.deleteClassFile(cf.fullyQualifiedTypeName); + cf.deleteFromFileSystem(); } private UnwovenClassFile createUnwovenClassFile(AjBuildConfig.BinarySourceFile bsf) { @@ -584,23 +582,122 @@ public class AjState { references.put(sourceFile, new ReferenceCollection(cr.qualifiedReferences, cr.simpleNameReferences)); } - InterimCompilationResult previous = (InterimCompilationResult) resultsFromFile.get(sourceFile); UnwovenClassFile[] unwovenClassFiles = result.unwovenClassFiles(); for (int i = 0; i < unwovenClassFiles.length; i++) { - UnwovenClassFile lastTimeRound = removeFromPreviousIfPresent(unwovenClassFiles[i],previous); + UnwovenClassFile lastTimeRound = (UnwovenClassFile) classesFromName.get(unwovenClassFiles[i].getClassName()); recordClassFile(unwovenClassFiles[i],lastTimeRound); classesFromName.put(unwovenClassFiles[i].getClassName(),unwovenClassFiles[i]); } - if (previous != null) { - for (int i = 0; i < previous.unwovenClassFiles().length; i++) { - if (previous.unwovenClassFiles()[i] != null) { - deleteClassFile(previous.unwovenClassFiles()[i]); - } + // need to do this before types are deleted from the World... + recordWhetherCompilationUnitDefinedAspect(sourceFile,cr); + deleteTypesThatWereInThisCompilationUnitLastTimeRoundButHaveBeenDeletedInThisIncrement(sourceFile, unwovenClassFiles); + + recordFQNsResultingFromCompilationUnit(sourceFile,result); + } + + /** + * Currently unused, if we ditch classesFromName, we might need this.... (in noteResult) + * @param file + * @return + */ + private UnwovenClassFile maybeGetExistingClassFileFor(UnwovenClassFile classFile) { + File existing = new File(classFile.getFilename()); + if (!existing.exists()) { + return null; + } + else { + try { + return new UnwovenClassFile(classFile.getFilename(),FileUtil.readAsByteArray(existing)); + } + catch (IOException ex) { + throw new IllegalStateException("Unable to read contents of '" + classFile.getFilename() + "' " + + "from last compile cycle"); + } + } + } + + /** + * @param sourceFile + * @param unwovenClassFiles + */ + private void deleteTypesThatWereInThisCompilationUnitLastTimeRoundButHaveBeenDeletedInThisIncrement(File sourceFile, UnwovenClassFile[] unwovenClassFiles) { + List classFiles = (List) this.fullyQualifiedTypeNamesResultingFromCompilationUnit.get(sourceFile); + if (classFiles != null) { + for (int i = 0; i < unwovenClassFiles.length; i++) { + // deleting also deletes types from the weaver... don't do this if they are + // still present this time around... + removeFromClassFilesIfPresent(unwovenClassFiles[i].getClassName(),classFiles); + } + for (Iterator iter = classFiles.iterator(); iter.hasNext();) { + ClassFile cf = (ClassFile) iter.next(); + deleteClassFile(cf); + } + } + } + + + private void removeFromClassFilesIfPresent(String className, List classFiles) { + ClassFile victim = null; + for (Iterator iter = classFiles.iterator(); iter.hasNext();) { + ClassFile cf = (ClassFile) iter.next(); + if (cf.fullyQualifiedTypeName.equals(className)) { + victim = cf; + break; } } - resultsFromFile.put(sourceFile, result); + if (victim != null) { + classFiles.remove(victim); + } + } + + /** + * Record the fully-qualified names of the types that were declared in the given + * source file. + * + * @param sourceFile, the compilation unit + * @param icr, the CompilationResult from compiling it + */ + private void recordFQNsResultingFromCompilationUnit(File sourceFile, InterimCompilationResult icr) { + List classFiles = new ArrayList(); + UnwovenClassFile[] types = icr.unwovenClassFiles(); + for (int i = 0; i < types.length; i++) { + classFiles.add(new ClassFile(types[i].getClassName(),new File(types[i].getFilename()))); + } + this.fullyQualifiedTypeNamesResultingFromCompilationUnit.put(sourceFile,classFiles); + } + + /** + * If this compilation unit defined an aspect, we need to know in case it is + * modified in a future increment. + * + * @param sourceFile + * @param cr + */ + private void recordWhetherCompilationUnitDefinedAspect(File sourceFile, CompilationResult cr) { + this.sourceFilesDefiningAspects.remove(sourceFile); + + if (cr!=null) { + Map compiledTypes = cr.compiledTypes; + if (compiledTypes!=null) { + for (Iterator iterator = compiledTypes.keySet().iterator(); iterator.hasNext();) { + char[] className = (char[])iterator.next(); + String typeName = new String(className).replace('/','.'); + if (typeName.indexOf(IWeaver.SYNTHETIC_CLASS_POSTFIX) == -1) { + ResolvedType rt = world.resolve(typeName); + if (rt.isMissing()) { + throw new IllegalStateException("Type '" + rt.getSignature() + "' not found in world!"); + } + if (rt.isAspect()) { + this.sourceFilesDefiningAspects.add(sourceFile); + break; + } + } + } + } + } + } private UnwovenClassFile removeFromPreviousIfPresent(UnwovenClassFile cf, InterimCompilationResult previous) { @@ -791,12 +888,15 @@ public class AjState { } protected void addDependentsOf(File sourceFile) { - InterimCompilationResult intRes = (InterimCompilationResult)resultsFromFile.get(sourceFile); - if (intRes == null) return; + List cfs = (List) this.fullyQualifiedTypeNamesResultingFromCompilationUnit.get(sourceFile); - for (int i = 0; i < intRes.unwovenClassFiles().length; i++) { - addDependentsOf(intRes.unwovenClassFiles()[i].getClassName()); + if (cfs != null) { + for (Iterator iter = cfs.iterator(); iter.hasNext();) { + ClassFile cf = (ClassFile) iter.next(); + addDependentsOf(cf.fullyQualifiedTypeName); + } } + } public void setStructureModel(IHierarchy model) { @@ -837,10 +937,6 @@ public class AjState { return this.buildConfig; } - public Collection getResultSetToUseForFullWeave() { - return this.resultsFromFile.values(); - } - public void clearBinarySourceFiles() { this.binarySourceFiles = new HashMap(); } @@ -878,4 +974,42 @@ public class AjState { public Set getDeletedFiles() { return this.deletedFiles; } + + public void forceBatchBuildNextTimeAround() { + this.batchBuildRequiredThisTime = true; + } + + public boolean requiresFullBatchBuild() { + return this.batchBuildRequiredThisTime; + } + + private static class ClassFile { + public String fullyQualifiedTypeName; + public File locationOnDisk; + + public ClassFile(String fqn, File location) { + this.fullyQualifiedTypeName = fqn; + this.locationOnDisk = location; + } + + public void deleteFromFileSystem() { + String namePrefix = locationOnDisk.getName(); + namePrefix = namePrefix.substring(0,namePrefix.lastIndexOf('.')); + final String targetPrefix = namePrefix + IWeaver.CLOSURE_CLASS_PREFIX; + File dir = locationOnDisk.getParentFile(); + if (dir != null) { + File[] weaverGenerated = dir.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.startsWith(targetPrefix); + }}); + if (weaverGenerated!=null) { + for (int i = 0; i < weaverGenerated.length; i++) { + weaverGenerated[i].delete(); + } + } + } + locationOnDisk.delete(); + } + } + } |