Summary: | Listener on build process on a per file basis. | ||||||
---|---|---|---|---|---|---|---|
Product: | [Eclipse Project] JDT | Reporter: | Theodora Yeung <tyeung> | ||||
Component: | Core | Assignee: | Kent Johnson <kent_johnson> | ||||
Status: | VERIFIED FIXED | QA Contact: | |||||
Severity: | enhancement | ||||||
Priority: | P3 | CC: | philippe_mulet | ||||
Version: | 3.1 | ||||||
Target Milestone: | 3.2 M5 | ||||||
Hardware: | PC | ||||||
OS: | Windows XP | ||||||
Whiteboard: | |||||||
Attachments: |
|
Description
Theodora Yeung
2005-03-10 17:25:13 EST
So, I've managed to get some of the builder hooks we've been discussing to work on my machine. This is really just a proto-type at this point, but I think it proves that it will work. I'd like some feedback on the code. If everyone likes this, I'll clean it up with comments and submit a patch. In particular, I'd like to know if the following three things are OK: 1. the naming of the "IBuildListener" interface. It seems there is some conflict with the current idea of a BuildNotifier, and I'd like to choose as appropritae a name as possible. 2. I'd like to know if the regstration of IBuildListeners is OK. In particular, is keeping a static list of IBuildListeners on the AbstractImageBuilder OK? 3. I'd like to know if the code looks OK. Here is the basic infrastructure to do pre-build notification that I've added to the AbstractImageBuilder class: private static java.util.List _buildListeners = new java.util.ArrayList(); public static interface IBuildListener { /** * returns a Set<IFile> of new files to be added to the compilatoin */ public java.util.Set beginToCompile( ICompilationUnit[] sourceUnits, IProject p, org.eclipse.jdt.internal.core.JavaProject jp ); } public static void registerBuildListener( IBuildListener l) { _buildListeners.add( l ); } protected Set notifyBuildListeners( ICompilationUnit[] sourceUnits ) { java.util.Iterator it = _buildListeners.iterator(); Set newFiles = new HashSet(); while ( it.hasNext() ) { IBuildListener l = (IBuildListener) it.next(); Set f = l.beginToCompile( sourceUnits , javaBuilder.currentProject, javaBuilder.javaProject ); newFiles.addAll( f ); } return newFiles; } Here is where we plug into the compile method in AbstractImageBuilder to do the pre-build notificaiton. The try-block is complete. void compile(SourceFile[] units, SourceFile[] additionalUnits) { ... try { inCompiler = true; Set newFiles = notifyBuildListeners( units ); SourceFile[] newUnits = new SourceFile[ units.length + newFiles.size() ]; System.arraycopy( units, 0, newUnits, 0, units.length ); Iterator it = newFiles.iterator(); int idx = units.length; while ( it.hasNext() ) { IFile f = (IFile) it.next(); newUnits[idx++] = new SourceFile( f, getSourceLocationForFile( f ) ); } units = newUnits; compiler.compile(units); } catch (AbortCompilation ignored) { ... } And here is a utility function. The code was lifted from IncrementalImageBuilder, so when I do a patch, I'll update IncrementalImageBuilder to use this new function. protected ClasspathMultiDirectory getSourceLocationForFile( IFile file ) { ClasspathMultiDirectory md = null; if (file.exists()) { 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 && md.inclusionPatterns == null) break; if (!Util.isExcluded(file, md.inclusionPatterns, md.exclusionPatterns)) break; } } } } return md; } Created attachment 19257 [details]
zip file of the first patches for the ICompilationParticipant interfaces
I've attached a zip file which contains interfaces for the
ICompilationParticipant interfaces we discussed. These patches contain the
hookups for pre-build notification & post-reconcile notification.
The ICompilationParticipant API resolved the problem. Marking the bug as fixed. Closing bug as ICompilationParticipant API is moving into 3.2. Theodora : this bug should be assigned to someone real, and have a proper milestone when closed as fixed. Re-opening as per Philippe's request. Kent - this should be resolveable with the work you did on the CompilationParticipant API. Solved with CompilationParticipant, API follows... tests were added to ParticipantBuildTests. /** * A compilation participant is notified of events occuring during the compilation process. * The compilation process not only involves generating .class files (i.e. building), it also involve * cleaning the output directory, reconciling a working copy, etc. * So the notified events are the result of a build action, a clean action, a reconcile operation * (for a working copy), etc. * <p> * Clients wishing to participate in the compilation process must suclass this class, and implement * {@link #isActive(IJavaProject)}, {@link #aboutToBuild(IJavaProject)}, * {@link #reconcile(ReconcileContext)}, etc. * </p><p> * This class is intended to be subclassed by clients. * </p> * @since 3.2 */ public abstract class CompilationParticipant { public static int READY_FOR_BUILD = 1; public static int NEEDS_FULL_BUILD = 2; /** * Notifies this participant that a build is about to start and provides it the opportunity to * create missing source folders for generated source files. * Only sent to participants interested in the project. * <p> * Default is to return <code>READY_FOR_BUILD</code>. * </p> * @param project the project about to build * @return READY_FOR_BUILD or NEEDS_FULL_BUILD */ public int aboutToBuild(IJavaProject project) { return READY_FOR_BUILD; } /** * Notifies this participant that a compile operation is about to start and provides it the opportunity to * generate source files based on the source files about to be compiled. * When isBatchBuild is true, then files contains all source files in the project. * Only sent to participants interested in the current build project. * * @param files is an array of CompilationParticipantResult * @param isBatch identifies when the build is a batch build */ public void buildStarting(ICompilationParticipantResult[] files, boolean isBatch) { // do nothing by default } /** * Notifies this participant that a clean is about to start and provides it the opportunity to * delete generated source files. * Only sent to participants interested in the project. * @param project the project about to be cleaned */ public void cleanStarting(IJavaProject project) { // do nothing by default } /** * Returns whether this participant is active for a given project. * <p> * Default is to return <code>false</code>. * </p><p> * For efficiency, participants that are not interested in the * given project should return <code>false</code> for that project. * </p> * @param project the project to participate in * @return whether this participant is active for a given project */ public boolean isActive(IJavaProject project) { return false; } /** * Returns whether this participant is interested in only Annotations. * <p> * Default is to return <code>false</code>. * </p> * @return whether this participant is interested in only Annotations. */ public boolean isAnnotationProcessor() { return false; } /** * Notifies this participant that a compile operation has found source files using Annotations. * Only sent to participants interested in the current build project that answer true to isAnnotationProcessor(). * Each CompilationParticipantResult was informed whether its source file currently hasAnnotations(). * * @param files is an array of CompilationParticipantResult */ public void processAnnotations(ICompilationParticipantResult[] files) { // do nothing by default } } Verified for 3.2 M5 using build I20060214-0010 |