Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 127856 Details for
Bug 233643
API builder performance bad for incremental build
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
work in progress
builder_perfB.patch (text/plain), 63.33 KB, created by
Michael Rennie
on 2009-03-06 14:56:58 EST
(
hide
)
Description:
work in progress
Filename:
MIME Type:
Creator:
Michael Rennie
Created:
2009-03-06 14:56:58 EST
Size:
63.33 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.pde.api.tools >Index: src/org/eclipse/pde/api/tools/internal/builder/BaseApiAnalyzer.java >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/BaseApiAnalyzer.java,v >retrieving revision 1.87 >diff -u -r1.87 BaseApiAnalyzer.java >--- src/org/eclipse/pde/api/tools/internal/builder/BaseApiAnalyzer.java 4 Mar 2009 01:44:08 -0000 1.87 >+++ src/org/eclipse/pde/api/tools/internal/builder/BaseApiAnalyzer.java 6 Mar 2009 19:52:48 -0000 >@@ -301,7 +301,7 @@ > } > } > if (changedTypes != null) { >- // check the ones not already checked as part of typenames check >+ // check the ones not already checked as part of type names check > for (int i = 0; i < changedTypes.length; i++) { > String typeName = changedTypes[i]; > if (typeNamesSet == null || !typeNamesSet.remove(typeName)) { >@@ -1550,7 +1550,7 @@ > Util.EMPTY_STRING); > } > } >- // analyse version of required components >+ // analyze version of required components > ReexportedBundleVersionInfo info = null; > if (problem != null) { > switch (problem.getKind()) { >@@ -1580,7 +1580,7 @@ > } > break; > case IApiProblem.MINOR_VERSION_CHANGE : >- // check if there is a version change required due to reexported bundles >+ // check if there is a version change required due to re-exported bundles > info = checkBundleVersionsOfReexportedBundles(reference, component); > if (info != null) { > switch(info.kind) { >@@ -1602,7 +1602,7 @@ > } > break; > case IApiProblem.MINOR_VERSION_CHANGE_NO_NEW_API : >- // check if there is a version change required due to reexported bundles >+ // check if there is a version change required due to re-exported bundles > info = checkBundleVersionsOfReexportedBundles(reference, component); > if (info != null) { > switch(info.kind) { >Index: src/org/eclipse/pde/api/tools/internal/builder/BuilderMessages.java >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/BuilderMessages.java,v >retrieving revision 1.32 >diff -u -r1.32 BuilderMessages.java >--- src/org/eclipse/pde/api/tools/internal/builder/BuilderMessages.java 7 Jan 2009 19:29:01 -0000 1.32 >+++ src/org/eclipse/pde/api/tools/internal/builder/BuilderMessages.java 6 Mar 2009 19:52:48 -0000 >@@ -20,6 +20,7 @@ > public static String checking_api_usage; > > public static String AbstractTypeLeakDetector_vis_type_has_no_api_description; >+ public static String ApiAnalysisBuilder_builder_for_project; > public static String ApiAnalysisBuilder_finding_affected_source_files; > public static String ApiAnalysisBuilder_initializing_analyzer; > public static String ApiProblemFactory_problem_message_not_found; >Index: src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java,v >retrieving revision 1.93 >diff -u -r1.93 ApiAnalysisBuilder.java >--- src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java 5 Mar 2009 20:57:12 -0000 1.93 >+++ src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java 6 Mar 2009 19:52:47 -0000 >@@ -22,18 +22,14 @@ > import java.util.Date; > import java.util.HashMap; > import java.util.HashSet; >-import java.util.Iterator; > import java.util.List; > import java.util.Map; >-import java.util.Set; > import java.util.jar.JarFile; > >-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.IResourceDelta; >-import org.eclipse.core.resources.IResourceDeltaVisitor; > import org.eclipse.core.resources.IWorkspaceRoot; > import org.eclipse.core.resources.IncrementalProjectBuilder; > import org.eclipse.core.resources.ResourcesPlugin; >@@ -41,7 +37,6 @@ > import org.eclipse.core.runtime.IPath; > import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.core.runtime.IStatus; >-import org.eclipse.core.runtime.NullProgressMonitor; > import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.core.runtime.Path; > import org.eclipse.core.runtime.Platform; >@@ -49,16 +44,9 @@ > import org.eclipse.core.runtime.SubMonitor; > import org.eclipse.jdt.core.IClasspathAttribute; > import org.eclipse.jdt.core.IClasspathEntry; >-import org.eclipse.jdt.core.ICompilationUnit; >-import org.eclipse.jdt.core.IJavaElement; > import org.eclipse.jdt.core.IJavaProject; >-import org.eclipse.jdt.core.IType; > import org.eclipse.jdt.core.JavaCore; > import org.eclipse.jdt.core.JavaModelException; >-import org.eclipse.jdt.internal.core.JavaModelManager; >-import org.eclipse.jdt.internal.core.builder.ReferenceCollection; >-import org.eclipse.jdt.internal.core.builder.State; >-import org.eclipse.jdt.internal.core.builder.StringSet; > import org.eclipse.osgi.service.resolver.BundleDescription; > import org.eclipse.osgi.util.NLS; > import org.eclipse.pde.api.tools.internal.ApiDescriptionManager; >@@ -82,93 +70,30 @@ > */ > public class ApiAnalysisBuilder extends IncrementalProjectBuilder { > /** >- * Visits a resource delta to determine if the changes have been made that might required a rebuild: >- * - modification to the manifest file >- * - removal of the .api_filter file >- */ >- class ResourceDeltaVisitor implements IResourceDeltaVisitor { >- IProject[] projects; >- public ResourceDeltaVisitor(IProject[] projects) { >- this.projects = projects; >- } >- private boolean fRequireFullBuild = false; >- >- /** >- * Returns whether a full build should be run. >- * >- * @return whether a full build should be run >- */ >- boolean shouldRunFullBuild() { >- return fRequireFullBuild; >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) >- */ >- public boolean visit(IResourceDelta delta) throws CoreException { >- switch (delta.getResource().getType()) { >- case IResource.ROOT: >- case IResource.PROJECT: >- return !fRequireFullBuild; >- case IResource.FOLDER: >- return !fRequireFullBuild; >- case IResource.FILE: >- if (delta.getResource().getProjectRelativePath().equals(MANIFEST_PATH)) { >- fRequireFullBuild = true; >- break; >- } >- IResource resource = delta.getResource(); >- String fileName = resource.getName(); >- if (Util.isClassFile(fileName)) { >- findAffectedSourceFiles(delta); >- } else if (Util.isJavaFileName(fileName)) { >- IProject project = resource.getProject(); >- if (fCurrentProject.equals(project)) { >- if (delta.getKind() == IResourceDelta.ADDED) { >- fAddedRemovedDeltas.add(delta); >- } >- fTypesToCheck.add(resource); >- } else if (this.projects != null) { >- loop: for (int i = 0, max = this.projects.length; i < max; i++) { >- if (this.projects[i].equals(project)) { >- fTypesToCheck.add(resource); >- break loop; >- } >- } >- } >- } else if (!fRequireFullBuild && IApiCoreConstants.API_FILTERS_XML_NAME.equals(fileName)) { >- switch(delta.getKind()) { >- case IResourceDelta.REMOVED : >- case IResourceDelta.REPLACED : >- case IResourceDelta.CHANGED : >- case IResourceDelta.ADDED : >- fRequireFullBuild = true; >- } >- } >- } >- return false; >- } >- } >- /** > * Constant used for controlling tracing in the API tool builder > */ >- private static boolean DEBUG = Util.DEBUG; >+ static boolean DEBUG = Util.DEBUG; > > /** > * Project relative path to the manifest file. > */ >- private static final IPath MANIFEST_PATH = new Path(JarFile.MANIFEST_NAME); >+ static final IPath MANIFEST_PATH = new Path(JarFile.MANIFEST_NAME); > > /** >- * Internal flag used to determine what created the marker, as there is overlap for reference kinds and deltas >+ * Project relative path to the .api_filters file > */ >- public static final int REF_TYPE_FLAG = 0; >+ static final IPath FILTER_PATH = new Path(".settings").append(IApiCoreConstants.API_FILTERS_XML_NAME); //$NON-NLS-1$ >+ >+ /** >+ * Empty listing of projects to be returned by the builder if there is nothing to do >+ */ >+ static final IProject[] NO_PROJECTS = new IProject[0]; > > /** > * Constant representing the name of the 'source' attribute on API tooling markers. > * Value is <code>Api Tooling</code> > */ >- public static final String SOURCE = "Api Tooling"; //$NON-NLS-1$ >+ static final String SOURCE = "Api Tooling"; //$NON-NLS-1$ > > /** > * Method used for initializing tracing in the API tool builder >@@ -176,51 +101,33 @@ > public static void setDebug(boolean debugValue) { > DEBUG = debugValue || Util.DEBUG; > } >+ > /** > * The current project for which this builder was defined > */ >- private IProject fCurrentProject = null; >+ private IProject currentproject = null; > > /** > * The API analyzer for this builder > */ >- private IApiAnalyzer fAnalyzer = null; >+ private IApiAnalyzer analyzer = null; > > /** > * Maps prerequisite projects to their output location(s) > */ >- private HashMap fProjectToOutputLocations = new HashMap(); >- >- /** >- * List of type names to lookup for each project context to find dependents of >- */ >- private StringSet fTypes = new StringSet(3); >- >- /** >- * List of package names to qualify type names >- */ >- private StringSet fPackages = new StringSet(3); >- >- /** >- * The type that we want to check for API problems >- */ >- private HashSet fTypesToCheck = new HashSet(); >- /** >- * The set of added/removed deltas that come directly from the builder resource delta >- */ >- private HashSet fAddedRemovedDeltas = new HashSet(5); >+ private HashMap projecttooutputlocations = new HashMap(); > > /** > * Current build state > */ >- private BuildState fBuildState; >+ private BuildState buildstate = null; > > /** > * Cleans up markers associated with API tooling on the given resource. > * > * @param resource > */ >- public static void cleanupMarkers(IResource resource) { >+ void cleanupMarkers(IResource resource) { > cleanupUsageMarkers(resource); > cleanupCompatibilityMarkers(resource); > cleanupUnsupportedTagMarkers(resource); >@@ -230,7 +137,7 @@ > * Cleans up unsupported Javadoc tag markers on the specified resource > * @param resource > */ >- private static void cleanupUnsupportedTagMarkers(IResource resource) { >+ void cleanupUnsupportedTagMarkers(IResource resource) { > try { > if(DEBUG) { > System.out.println("cleaning unsupported tag problems"); //$NON-NLS-1$ >@@ -245,7 +152,7 @@ > * Cleans up only API compatibility markers on the given {@link IResource} > * @param resource the given resource > */ >- private static void cleanupCompatibilityMarkers(IResource resource) { >+ void cleanupCompatibilityMarkers(IResource resource) { > try { > if (resource != null && resource.isAccessible()) { > resource.deleteMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); >@@ -266,7 +173,7 @@ > * cleans up only API usage markers from the given {@link IResource} > * @param resource > */ >- private static void cleanupUsageMarkers(IResource resource) { >+ void cleanupUsageMarkers(IResource resource) { > try { > if (resource != null && resource.isAccessible()) { > resource.deleteMarkers(IApiMarkerConstants.API_USAGE_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); >@@ -276,39 +183,17 @@ > } > } > >- /** >- * Adds a type to search for dependents of in considered projects for an incremental build >- * >- * @param path >- */ >- private void addDependentsOf(IPath path) { >- // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' >- path = path.setDevice(null); >- String packageName = path.removeLastSegments(1).toString(); >- String typeName = path.lastSegment(); >- int memberIndex = typeName.indexOf('$'); >- if (memberIndex > 0) { >- typeName = typeName.substring(0, memberIndex); >- } >- if (fTypes.add(typeName) && fPackages.add(packageName) && DEBUG) { >- System.out.println(" will look for dependents of " + typeName + " in " + packageName); //$NON-NLS-1$ //$NON-NLS-2$ >- } >- } >- > /* (non-Javadoc) > * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) > */ > protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { >- fCurrentProject = getProject(); >- fAnalyzer = getAnalyzer(); >- if (fCurrentProject == null || >- !fCurrentProject.isAccessible() || >- !fCurrentProject.hasNature(ApiPlugin.NATURE_ID) || >- hasBeenBuilt(fCurrentProject)) { >- return new IProject[0]; >+ this.currentproject = getProject(); >+ this.analyzer = getAnalyzer(); >+ if (!this.currentproject.isAccessible() || !this.currentproject.hasNature(ApiPlugin.NATURE_ID) || hasBeenBuilt(this.currentproject)) { >+ return NO_PROJECTS; > } > if (DEBUG) { >- System.out.println("\nStarting build of " + fCurrentProject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$ >+ System.out.println("\nStarting build of " + this.currentproject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$ > } > updateMonitor(monitor, 0); > SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_builder, 2); >@@ -326,63 +211,60 @@ > case AUTO_BUILD : > case INCREMENTAL_BUILD : { > IResourceDelta[] deltas = getDeltas(projects); >- boolean shouldRunFullBuild = false; >- fBuildState = getLastBuiltState(fCurrentProject); >- if (fBuildState == null) { >+ if(deltas.length == 0) { > buildAll(baseline, localMonitor.newChild(1)); >- } else { >- IProject[] reexportedProjects = null; >- String[] projectNames = this.fBuildState.getReexportedComponents(); >- int length = projectNames.length; >- if (length != 0) { >- List allProjects = new ArrayList(); >- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); >- for (int i = 0, max = projectNames.length; i < max; i++) { >- String projectName = projectNames[i]; >- IProject project = root.getProject(projectName); >- if (project.isAccessible()) { >- // select only projects that don't exist in the reference baseline >- if (baseline != null && baseline.getApiComponent(projectName) == null) { >- allProjects.add(project); >- } >- } >- } >- if (allProjects.size() != 0) { >- reexportedProjects = new IProject[allProjects.size()]; >- allProjects.toArray(reexportedProjects); >- } >+ break; >+ } >+ this.buildstate = getLastBuiltState(currentproject); >+ if (this.buildstate == null) { >+ buildAll(baseline, localMonitor.newChild(1)); >+ break; >+ } >+ IResourceDelta manifest = null; >+ IResourceDelta filters = null; >+ for (int i = 0; i < deltas.length; i++) { >+ manifest = deltas[i].findMember(MANIFEST_PATH); >+ if(manifest != null) { >+ break; >+ } >+ filters = deltas[i].findMember(FILTER_PATH); >+ if(filters != null){ >+ break; > } >- ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(reexportedProjects); >- for (int i = 0; i < deltas.length; i++) { >- deltas[i].accept(visitor); >- if (visitor.shouldRunFullBuild()) { >- shouldRunFullBuild = true; >- break; >- } >+ } >+ if (manifest != null || filters != null) { >+ if (DEBUG) { >+ System.out.println("Performing full build since MANIFEST.MF or .api_filters was modified"); //$NON-NLS-1$ > } >- if (shouldRunFullBuild) { >- if (DEBUG) { >- System.out.println("Performing full build since MANIFEST.MF was modified"); //$NON-NLS-1$ >- } >- buildAll(baseline, localMonitor.newChild(1)); >- } else if (deltas.length == 0) { >- if (DEBUG) { >- System.out.println("Performing full build since deltas are missing after incremental request"); //$NON-NLS-1$ >- } >- buildAll(baseline, localMonitor.newChild(1)); >- } else { >- State state = (State)JavaModelManager.getJavaModelManager().getLastBuiltState(fCurrentProject, new NullProgressMonitor()); >- if (state == null) { >- buildAll(baseline, localMonitor.newChild(1)); >- } else { >- build(state, baseline, localMonitor.newChild(1)); >+ buildAll(baseline, localMonitor.newChild(1)); >+ } >+ IProject[] reexportedProjects = null; >+ String[] projectNames = this.buildstate.getReexportedComponents(); >+ int length = projectNames.length; >+ if (length != 0) { >+ List allProjects = new ArrayList(); >+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); >+ for (int i = 0, max = projectNames.length; i < max; i++) { >+ String projectName = projectNames[i]; >+ IProject project = root.getProject(projectName); >+ if (project.isAccessible()) { >+ // select only projects that don't exist in the reference baseline >+ if (baseline != null && baseline.getApiComponent(projectName) == null) { >+ allProjects.add(project); >+ } > } > } >+ if (allProjects.size() != 0) { >+ reexportedProjects = new IProject[allProjects.size()]; >+ allProjects.toArray(reexportedProjects); >+ } >+ } >+ IncrementalApiBuilder incbuilder = new IncrementalApiBuilder(this); >+ incbuilder.build(baseline, deltas, localMonitor.newChild(1)); > } > break; > } >- } >- updateMonitor(monitor, 0); >+ updateMonitor(monitor, 0); > } catch(CoreException e) { > IStatus status = e.getStatus(); > if (status == null || status.getCode() != ApiPlugin.REPORT_BASELINE_IS_DISPOSED) { >@@ -390,26 +272,22 @@ > } > ApiPlugin.log(e); > } finally { >- fTypes.clear(); >- fPackages.clear(); >- fTypesToCheck.clear(); >- fAddedRemovedDeltas.clear(); >- fProjectToOutputLocations.clear(); >+ this.projecttooutputlocations.clear(); > updateMonitor(monitor, 0); >- fAnalyzer.dispose(); >+ this.analyzer.dispose(); > if(baseline != null) { > baseline.close(); > } > if(monitor != null) { > monitor.done(); > } >- if (fBuildState != null) { >- saveBuiltState(fCurrentProject, fBuildState); >- fBuildState = null; >+ if (this.buildstate != null) { >+ saveBuiltState(this.currentproject, this.buildstate); >+ this.buildstate = null; > } > } > if (DEBUG) { >- System.out.println("Finished build of " + fCurrentProject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$ >+ System.out.println("Finished build of " + currentproject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$ > } > return projects; > } >@@ -418,14 +296,14 @@ > * Performs a full build for the project > * @param monitor > */ >- private void buildAll(IApiBaseline baseline, IProgressMonitor monitor) throws CoreException { >+ void buildAll(IApiBaseline baseline, IProgressMonitor monitor) throws CoreException { > IApiBaseline wsprofile = null; > try { > clearLastState(); >- fBuildState = new BuildState(); >+ this.buildstate = new BuildState(); > SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 4); >- localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_initializing_analyzer, fCurrentProject.getName())); >- cleanupMarkers(fCurrentProject); >+ localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_initializing_analyzer, currentproject.getName())); >+ cleanupMarkers(this.currentproject); > IPluginModelBase currentModel = getCurrentModel(); > if (currentModel != null) { > localMonitor.subTask(BuilderMessages.building_workspace_profile); >@@ -441,7 +319,7 @@ > // Compatibility checks > IApiComponent apiComponent = wsprofile.getApiComponent(id); > if(apiComponent != null) { >- fAnalyzer.analyzeComponent(fBuildState, null, null, baseline, apiComponent, null, null, localMonitor.newChild(1)); >+ this.analyzer.analyzeComponent(this.buildstate, null, null, baseline, apiComponent, null, null, localMonitor.newChild(1)); > updateMonitor(localMonitor, 1); > createMarkers(); > updateMonitor(localMonitor, 1); >@@ -465,13 +343,13 @@ > */ > protected void createMarkers() { > try { >- fCurrentProject.deleteMarkers(IApiMarkerConstants.VERSION_NUMBERING_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); >- fCurrentProject.deleteMarkers(IApiMarkerConstants.DEFAULT_API_BASELINE_PROBLEM_MARKER, true, IResource.DEPTH_ZERO); >- fCurrentProject.deleteMarkers(IApiMarkerConstants.API_COMPONENT_RESOLUTION_PROBLEM_MARKER, true, IResource.DEPTH_ZERO); >+ this.currentproject.deleteMarkers(IApiMarkerConstants.VERSION_NUMBERING_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); >+ this.currentproject.deleteMarkers(IApiMarkerConstants.DEFAULT_API_BASELINE_PROBLEM_MARKER, true, IResource.DEPTH_ZERO); >+ this.currentproject.deleteMarkers(IApiMarkerConstants.API_COMPONENT_RESOLUTION_PROBLEM_MARKER, true, IResource.DEPTH_ZERO); > } catch (CoreException e) { > ApiPlugin.log(e); > } >- IApiProblem[] problems = fAnalyzer.getProblems(); >+ IApiProblem[] problems = this.analyzer.getProblems(); > String type = null; > for(int i = 0; i < problems.length; i++) { > int category = problems[i].getCategory(); >@@ -555,7 +433,7 @@ > IApiMarkerConstants.MARKER_ATTR_PROBLEM_ID}, > new Object[] { > problem.getMessage(), >- new Integer(ApiPlugin.getDefault().getSeverityLevel(ApiProblemFactory.getProblemSeverityId(problem), this.fCurrentProject)), >+ new Integer(ApiPlugin.getDefault().getSeverityLevel(ApiProblemFactory.getProblemSeverityId(problem), this.currentproject)), > new Integer(line), > new Integer(problem.getCharStart()), > new Integer(problem.getCharEnd()), >@@ -597,7 +475,7 @@ > if (resourcePath == null) { > return null; > } >- IResource resource = fCurrentProject.findMember(new Path(resourcePath)); >+ IResource resource = currentproject.findMember(new Path(resourcePath)); > if(resource == null) { > return null; > } >@@ -631,7 +509,7 @@ > * @param ticks > * @throws OperationCanceledException > */ >- private void updateMonitor(IProgressMonitor monitor, int ticks) throws OperationCanceledException { >+ void updateMonitor(IProgressMonitor monitor, int ticks) throws OperationCanceledException { > if(monitor != null) { > monitor.worked(ticks); > if (monitor.isCanceled()) { >@@ -640,232 +518,21 @@ > } > } > >- /** >- * Builds an API delta using the default profile (from the workspace settings and the current >- * workspace profile >- * @param state >- * @param monitor >- */ >- private void build(final State state, IApiBaseline baseline, IProgressMonitor monitor) throws CoreException { >- IApiBaseline wsprofile = null; >- try { >- clearLastState(); // so if the build fails, a full build will be triggered >- int typesToCheckSize = fTypesToCheck.size(); >- SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 2 + (typesToCheckSize != 0 ? 3 : 0)); >- localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_finding_affected_source_files, fCurrentProject.getName())); >- updateMonitor(localMonitor, 0); >- collectAffectedSourceFiles(state, fTypesToCheck); >- updateMonitor(localMonitor, 1); >- if (typesToCheckSize != 0) { >- IPluginModelBase currentModel = getCurrentModel(); >- if (currentModel != null) { >- wsprofile = getWorkspaceProfile(); >- if (wsprofile == null) { >- if (DEBUG) { >- System.err.println("Could not retrieve a workspace profile"); //$NON-NLS-1$ >- } >- return; >- } >- String id = currentModel.getBundleDescription().getSymbolicName(); >- IApiComponent apiComponent = wsprofile.getApiComponent(id); >- if(apiComponent == null) { >- return; >- } >- List tnames = new ArrayList(typesToCheckSize), >- cnames = new ArrayList(typesToCheckSize); >- collectAllQualifiedNames(fTypesToCheck, tnames, cnames, localMonitor.newChild(1)); >- updateMonitor(localMonitor, 1); >- fAnalyzer.analyzeComponent(fBuildState, >- null, >- null, >- baseline, >- apiComponent, >- (String[])tnames.toArray(new String[tnames.size()]), >- (String[])cnames.toArray(new String[cnames.size()]), >- localMonitor.newChild(1)); >- updateMonitor(localMonitor, 1); >- createMarkers(); >- updateMonitor(localMonitor, 1); >- } >- } >- } >- finally { >- if(wsprofile != null) { >- wsprofile.close(); >- } >- if(monitor != null) { >- monitor.done(); >- } >- } >- } >- >- /** >- * Returns an array of type names, and cleans up markers for the specified resource >- * @param alltypes the listing of {@link IFile}s to get qualified names from >- * @param changedtypes the listing of {@link IFile}s that have actually changed (from the {@link IResourceDelta} >- * @param tnames the list to collect all type names into (including inner member names) >- * @param cnames the list to collect the changed type names into >- * @param monitor >- */ >- private void collectAllQualifiedNames(final HashSet alltypes, List tnames, List cnames, final IProgressMonitor monitor) { >- IType[] types = null; >- IFile file = null; >- for (Iterator iterator = alltypes.iterator(); iterator.hasNext(); ) { >- file = (IFile) iterator.next(); >- ICompilationUnit unit = (ICompilationUnit) JavaCore.create(file); >- if(!unit.exists()) { >- continue; >- } >- IType type = unit.findPrimaryType(); >- if(type == null) { >- continue; >- } >- updateMonitor(monitor, 0); >- cleanupUnsupportedTagMarkers(file); >- updateMonitor(monitor, 0); >- cleanupCompatibilityMarkers(file); >- updateMonitor(monitor, 0); >- cnames.add(type.getFullyQualifiedName()); >- try { >- cleanupUsageMarkers(file); >- updateMonitor(monitor, 0); >- types = unit.getAllTypes(); >- String tname = null; >- for (int i = 0; i < types.length; i++) { >- IType type2 = types[i]; >- if (type2.isMember()) { >- tname = type2.getFullyQualifiedName('$'); >- } else { >- tname = type2.getFullyQualifiedName(); >- } >- tnames.add(tname); >- } >- } catch (JavaModelException e) { >- ApiPlugin.log(e.getStatus()); >- } >- updateMonitor(monitor, 0); >- } >- // inject removed types inside changed type names so that we can properly detect type removal >- for (Iterator iterator = this.fAddedRemovedDeltas.iterator(); iterator.hasNext(); ) { >- IResourceDelta delta = (IResourceDelta) iterator.next(); >- if (delta.getKind() != IResourceDelta.REMOVED) continue; >- IResource resource = delta.getResource(); >- IPath typePath = resolveJavaPathFromResource(resource); >- if(typePath == null) { >- continue; >- } >- // record removed type names (package + type) >- StringBuffer buffer = new StringBuffer(); >- String[] segments = typePath.segments(); >- for (int i = 0, max = segments.length; i < max; i++) { >- if (i > 0) { >- buffer.append('.'); >- } >- buffer.append(segments[i]); >- } >- cnames.add(String.valueOf(buffer)); >- } >- // clean up markers on added deltas >- if (!this.fAddedRemovedDeltas.isEmpty()) { >- IResource manifestFile = Util.getManifestFile(this.fCurrentProject); >- if (manifestFile != null) { >- try { >- IMarker[] markers = manifestFile.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); >- for (int i = 0, max = markers.length; i < max; i++) { >- IMarker marker = markers[i]; >- String typeName = marker.getAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_TYPE_NAME, null); >- if (typeName != null) { >- for (Iterator iterator = this.fAddedRemovedDeltas.iterator(); iterator.hasNext(); ) { >- IResourceDelta delta = (IResourceDelta) iterator.next(); >- if (delta.getKind() != IResourceDelta.ADDED) continue; >- ICompilationUnit unit = (ICompilationUnit) JavaCore.create(delta.getResource()); >- if(!unit.exists()) { >- continue; >- } >- IType type = unit.findPrimaryType(); >- if(type == null) { >- continue; >- } >- if (typeName.equals(type.getFullyQualifiedName())) { >- marker.delete(); >- return; >- } else { >- // check secondary types >- try { >- types = unit.getAllTypes(); >- for (int j = 0; j < types.length; j++) { >- IType type2 = types[i]; >- String fullyQualifiedName = null; >- if (type2.isMember()) { >- fullyQualifiedName = type2.getFullyQualifiedName('$'); >- } else { >- fullyQualifiedName = type2.getFullyQualifiedName(); >- } >- if (typeName.equals(fullyQualifiedName)) { >- marker.delete(); >- return; >- } >- } >- } catch (JavaModelException e) { >- ApiPlugin.log(e.getStatus()); >- } >- } >- } >- } >- } >- } catch (CoreException e) { >- ApiPlugin.log(e.getStatus()); >- } >- } >- } >- IResource resource = fCurrentProject.findMember(MANIFEST_PATH); >- if (resource != null) { >- try { >- IMarker[] markers = resource.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); >- loop: for (int i = 0, max = markers.length; i < max; i++) { >- IMarker marker = markers[i]; >- String typeNameFromMarker = Util.getTypeNameFromMarker(marker); >- for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) { >- String typeName = (String) iterator.next(); >- if (typeName.equals(typeNameFromMarker)) { >- marker.delete(); >- continue loop; >- } >- } >- } >- markers = resource.findMarkers(IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); >- loop: for (int i = 0, max = markers.length; i < max; i++) { >- IMarker marker = markers[i]; >- String typeNameFromMarker = Util.getTypeNameFromMarker(marker); >- for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) { >- String typeName = (String) iterator.next(); >- if (typeName.equals(typeNameFromMarker)) { >- marker.delete(); >- continue loop; >- } >- } >- } >- } catch (CoreException e) { >- ApiPlugin.log(e); >- } >- } >- } >- > /* (non-Javadoc) > * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor) > */ > protected void clean(IProgressMonitor monitor) throws CoreException { >- fCurrentProject = getProject(); >- SubMonitor localmonitor = SubMonitor.convert(monitor, MessageFormat.format(BuilderMessages.CleaningAPIDescription, new String[] {fCurrentProject.getName()}), 2); >+ this.currentproject = getProject(); >+ SubMonitor localmonitor = SubMonitor.convert(monitor, MessageFormat.format(BuilderMessages.CleaningAPIDescription, new String[] {currentproject.getName()}), 2); > try { > // clean up all existing markers >- cleanupUsageMarkers(fCurrentProject); >- cleanupCompatibilityMarkers(fCurrentProject); >- cleanupUnsupportedTagMarkers(fCurrentProject); >- fCurrentProject.deleteMarkers(IApiMarkerConstants.UNUSED_FILTER_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); >+ cleanupUsageMarkers(this.currentproject); >+ cleanupCompatibilityMarkers(this.currentproject); >+ cleanupUnsupportedTagMarkers(this.currentproject); >+ this.currentproject.deleteMarkers(IApiMarkerConstants.UNUSED_FILTER_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); > updateMonitor(localmonitor, 1); > //clean up the .api_settings >- cleanupApiDescription(fCurrentProject); >+ cleanupApiDescription(this.currentproject); > updateMonitor(localmonitor, 1); > } > finally { >@@ -882,93 +549,13 @@ > ApiDescriptionManager.getDefault().clean(JavaCore.create(project), true, false); > } > } >- /** >- * Collects the complete set of affected source files from the current project context based on the current JDT build state. >- * >- * @param state >- */ >- private void collectAffectedSourceFiles(State state, Set typesToCheck) { >- // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' >- char[][][] internedQualifiedNames = ReferenceCollection.internQualifiedNames(fPackages); >- // if a well known qualified name was found then we can skip over these >- if (internedQualifiedNames.length < fPackages.elementSize) { >- internedQualifiedNames = null; >- } >- char[][] internedSimpleNames = ReferenceCollection.internSimpleNames(fTypes, true); >- // if a well known name was found then we can skip over these >- if (internedSimpleNames.length < fTypes.elementSize) { >- internedSimpleNames = null; >- } >- Object[] keyTable = state.getReferences().keyTable; >- Object[] valueTable = state.getReferences().valueTable; >- next : for (int i = 0, l = valueTable.length; i < l; i++) { >- String typeLocator = (String) keyTable[i]; >- if (typeLocator != null) { >- ReferenceCollection refs = (ReferenceCollection) valueTable[i]; >- if (refs.includes(internedQualifiedNames, internedSimpleNames, null)) { >- IFile file = fCurrentProject.getFile(typeLocator); >- if (file == null) { >- continue next; >- } >- if (DEBUG) { >- System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$ >- } >- typesToCheck.add(file); >- } >- } >- } >- } >- > >- >- /** >- * Finds affected source files for a resource that has changed that either contains class files or is itself a class file >- * @param binaryDelta >- */ >- private void findAffectedSourceFiles(IResourceDelta binaryDelta) { >- IResource resource = binaryDelta.getResource(); >- if(resource.getType() == IResource.FILE) { >- if (Util.isClassFile(resource.getName())) { >- switch (binaryDelta.getKind()) { >- case IResourceDelta.REMOVED : >- fAddedRemovedDeltas.add(binaryDelta); >- //$FALL-THROUGH$ >- case IResourceDelta.ADDED : { >- IPath typePath = resolveJavaPathFromResource(resource); >- if(typePath == null) { >- return; >- } >- if (DEBUG) { >- System.out.println("Found added/removed class file " + typePath); //$NON-NLS-1$ >- } >- addDependentsOf(typePath); >- return; >- } >- case IResourceDelta.CHANGED : { >- if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0) { >- return; // skip it since it really isn't changed >- } >- IPath typePath = resolveJavaPathFromResource(resource); >- if(typePath == null) { >- return; >- } >- if (DEBUG) { >- System.out.println("Found changed class file " + typePath); //$NON-NLS-1$ >- } >- addDependentsOf(typePath); >- } >- } >- return; >- } >- } >- } >- > /** > * @return the current {@link IPluginModelBase} based on the current project for this builder > */ >- private IPluginModelBase getCurrentModel() { >+ IPluginModelBase getCurrentModel() { > IPluginModelBase[] workspaceModels = PluginRegistry.getWorkspaceModels(); >- IPath location = fCurrentProject.getLocation(); >+ IPath location = this.currentproject.getLocation(); > IPluginModelBase currentModel = null; > BundleDescription desc = null; > loop: for (int i = 0, max = workspaceModels.length; i < max; i++) { >@@ -994,10 +581,10 @@ > */ > private IResourceDelta[] getDeltas(IProject[] projects) { > if(DEBUG) { >- System.out.println("Searching for deltas for build of project: "+fCurrentProject.getName()); //$NON-NLS-1$ >+ System.out.println("Searching for deltas for build of project: "+this.currentproject.getName()); //$NON-NLS-1$ > } > ArrayList deltas = new ArrayList(); >- IResourceDelta delta = getDelta(fCurrentProject); >+ IResourceDelta delta = getDelta(this.currentproject); > if(delta != null) { > if (DEBUG) { > System.out.println("Found a delta: " + delta); //$NON-NLS-1$ >@@ -1032,15 +619,15 @@ > */ > private IProject[] getRequiredProjects(boolean includebinaries) throws CoreException { > IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); >- if (fCurrentProject == null || workspaceRoot == null) { >+ if (this.currentproject == null || workspaceRoot == null) { > return new IProject[0]; > } > ArrayList projects = new ArrayList(); > try { >- IJavaProject javaProject = JavaCore.create(fCurrentProject); >+ IJavaProject javaProject = JavaCore.create(this.currentproject); > HashSet blocations = new HashSet(); > blocations.add(javaProject.getOutputLocation()); >- fProjectToOutputLocations.put(fCurrentProject, blocations); >+ projecttooutputlocations.put(this.currentproject, blocations); > IClasspathEntry[] entries = javaProject.getResolvedClasspath(true); > for (int i = 0, l = entries.length; i < l; i++) { > IClasspathEntry entry = entries[i]; >@@ -1088,7 +675,7 @@ > } > } > } >- fProjectToOutputLocations.put(p, bins); >+ this.projecttooutputlocations.put(p, bins); > } > } > } >@@ -1104,9 +691,19 @@ > /** > * @return the workspace {@link IApiProfile} > */ >- private IApiBaseline getWorkspaceProfile() throws CoreException { >+ IApiBaseline getWorkspaceProfile() throws CoreException { > return ApiPlugin.getDefault().getApiBaselineManager().getWorkspaceBaseline(); > } >+ >+ /** >+ * Returns the output paths of the given project or <code>null</code> if none have been computed >+ * @param project >+ * @return the output paths for the given project or <code>null</code> >+ */ >+ HashSet getProjectOutputPaths(IProject project) { >+ return (HashSet) this.projecttooutputlocations.get(project); >+ } >+ > /** > * Returns is the given classpath entry is optional or not > * @param entry >@@ -1121,39 +718,12 @@ > } > return false; > } >- >- /** >- * Resolves the java path from the given resource >- * @param resource >- * @return the resolved path or <code>null</code> if the resource is not part of the java model >- */ >- private IPath resolveJavaPathFromResource(IResource resource) { >- IJavaElement element = JavaCore.create(resource); >- if(element != null) { >- switch(element.getElementType()) { >- case IJavaElement.CLASS_FILE: { >- org.eclipse.jdt.core.IClassFile classfile = (org.eclipse.jdt.core.IClassFile) element; >- IType type = classfile.getType(); >- HashSet paths = (HashSet) fProjectToOutputLocations.get(resource.getProject()); >- IPath prefix = null; >- for(Iterator iter = paths.iterator(); iter.hasNext();) { >- prefix = (IPath) iter.next(); >- if(prefix.isPrefixOf(type.getPath())) { >- return type.getPath().removeFirstSegments(prefix.segmentCount()).removeFileExtension(); >- } >- } >- break; >- } >- } >- } >- return null; >- } > > /* (non-Javadoc) > * @see java.lang.Object#toString() > */ > public String toString() { >- return "Builder for project: ["+fCurrentProject.getName()+"]"; //$NON-NLS-1$ //$NON-NLS-2$ >+ return NLS.bind(BuilderMessages.ApiAnalysisBuilder_builder_for_project, this.currentproject.getName()); > } > > /** >@@ -1170,7 +740,7 @@ > /** > * Reads the build state for the relevant project. > */ >- protected static BuildState readState(IProject project) throws CoreException { >+ static BuildState readState(IProject project) throws CoreException { > File file = getSerializationFile(project); > if (file != null && file.exists()) { > try { >@@ -1221,7 +791,7 @@ > /** > * Returns the File to use for saving and restoring the last built state for the given project. > */ >- private static File getSerializationFile(IProject project) { >+ static File getSerializationFile(IProject project) { > if (!project.exists()) { > return null; > } >@@ -1235,7 +805,7 @@ > * @param state > * @throws CoreException > */ >- private static void saveBuiltState(IProject project, BuildState state) throws CoreException { >+ static void saveBuiltState(IProject project, BuildState state) throws CoreException { > if (DEBUG) { > System.out.println("Saving build state for project: "+project.getName()); //$NON-NLS-1$ > } >@@ -1281,7 +851,7 @@ > * Clears the last build state by setting it to <code>null</code> > * @throws CoreException > */ >- private void clearLastState() throws CoreException { >- setLastBuiltState(fCurrentProject, null); >+ void clearLastState() throws CoreException { >+ setLastBuiltState(this.currentproject, null); > } > } >Index: src/org/eclipse/pde/api/tools/internal/builder/buildermessages.properties >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/buildermessages.properties,v >retrieving revision 1.44 >diff -u -r1.44 buildermessages.properties >--- src/org/eclipse/pde/api/tools/internal/builder/buildermessages.properties 7 Jan 2009 19:29:01 -0000 1.44 >+++ src/org/eclipse/pde/api/tools/internal/builder/buildermessages.properties 6 Mar 2009 19:52:48 -0000 >@@ -13,6 +13,7 @@ > building_workspace_profile=Building workspace API profile > checking_api_usage=Checking API use of ''{0}'' > AbstractTypeLeakDetector_vis_type_has_no_api_description=Visible type {0} has no API description >+ApiAnalysisBuilder_builder_for_project=Builder for project: [{0}] > ApiAnalysisBuilder_finding_affected_source_files=Finding affected source in ''{0}'' > ApiAnalysisBuilder_initializing_analyzer=Initializing analyzer for ''{0}'' > ApiProblemFactory_problem_message_not_found=Message not found for id: {0} >Index: src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java,v >retrieving revision 1.6 >diff -u -r1.6 ApiBaselineManager.java >--- src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java 26 Feb 2009 16:23:30 -0000 1.6 >+++ src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java 6 Mar 2009 19:52:46 -0000 >@@ -56,7 +56,6 @@ > import org.eclipse.jdt.core.IPackageFragment; > import org.eclipse.jdt.core.IPackageFragmentRoot; > import org.eclipse.jdt.core.JavaCore; >-import org.eclipse.pde.api.tools.internal.builder.ApiAnalysisBuilder; > import org.eclipse.pde.api.tools.internal.model.ApiBaseline; > import org.eclipse.pde.api.tools.internal.model.ApiModelFactory; > import org.eclipse.pde.api.tools.internal.model.StubApiComponent; >@@ -880,7 +879,6 @@ > IJavaProject jp = JavaCore.create(project); > if (jp.exists()) { > ApiDescriptionManager.getDefault().clean(jp, true, true); >- ApiAnalysisBuilder.cleanupMarkers(resource); > } > } > } catch (CoreException e) { >Index: src/org/eclipse/pde/api/tools/internal/ApiDescriptionManager.java >=================================================================== >RCS file: /cvsroot/eclipse/pde/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiDescriptionManager.java,v >retrieving revision 1.19 >diff -u -r1.19 ApiDescriptionManager.java >--- src/org/eclipse/pde/api/tools/internal/ApiDescriptionManager.java 4 Mar 2009 00:24:40 -0000 1.19 >+++ src/org/eclipse/pde/api/tools/internal/ApiDescriptionManager.java 6 Mar 2009 19:52:46 -0000 >@@ -139,8 +139,8 @@ > * Cleans the API description for the given project. > * > * @param project >- * @param whether to delete the file on disk >- * @param whether to remove the cached API description >+ * @param delete whether to delete the file on disk >+ * @param remove whether to remove the cached API description > */ > public synchronized void clean(IJavaProject project, boolean delete, boolean remove) { > ProjectApiDescription desc = null; >Index: src/org/eclipse/pde/api/tools/internal/builder/IncrementalApiBuilder.java >=================================================================== >RCS file: src/org/eclipse/pde/api/tools/internal/builder/IncrementalApiBuilder.java >diff -N src/org/eclipse/pde/api/tools/internal/builder/IncrementalApiBuilder.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/pde/api/tools/internal/builder/IncrementalApiBuilder.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,507 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.pde.api.tools.internal.builder; >+ >+import java.util.ArrayList; >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.List; >+import java.util.Set; >+ >+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.IResourceDelta; >+import org.eclipse.core.resources.IResourceDeltaVisitor; >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IPath; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.SubMonitor; >+import org.eclipse.jdt.core.ICompilationUnit; >+import org.eclipse.jdt.core.IJavaElement; >+import org.eclipse.jdt.core.IType; >+import org.eclipse.jdt.core.JavaCore; >+import org.eclipse.jdt.core.JavaModelException; >+import org.eclipse.jdt.internal.core.JavaModelManager; >+import org.eclipse.jdt.internal.core.builder.ReferenceCollection; >+import org.eclipse.jdt.internal.core.builder.State; >+import org.eclipse.jdt.internal.core.builder.StringSet; >+import org.eclipse.osgi.util.NLS; >+import org.eclipse.pde.api.tools.internal.IApiCoreConstants; >+import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; >+import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants; >+import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline; >+import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; >+import org.eclipse.pde.api.tools.internal.util.Util; >+import org.eclipse.pde.core.plugin.IPluginModelBase; >+ >+/** >+ * Used to incrementally build changed Java types >+ * >+ * @since 3.5 >+ */ >+public class IncrementalApiBuilder { >+ >+ /** >+ * Visits a resource delta to determine if the changes have been made that might required a rebuild: >+ * - modification to the manifest file >+ * - removal of the .api_filter file >+ */ >+ class ResourceDeltaVisitor implements IResourceDeltaVisitor { >+ IProject[] projects; >+ public ResourceDeltaVisitor(IProject[] projects) { >+ this.projects = projects; >+ } >+ private boolean fRequireFullBuild = false; >+ >+ /** >+ * Returns whether a full build should be run. >+ * >+ * @return whether a full build should be run >+ */ >+ boolean shouldRunFullBuild() { >+ return fRequireFullBuild; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) >+ */ >+ public boolean visit(IResourceDelta delta) throws CoreException { >+ switch (delta.getResource().getType()) { >+ case IResource.ROOT: >+ case IResource.PROJECT: >+ return !fRequireFullBuild; >+ case IResource.FOLDER: >+ return !fRequireFullBuild; >+ case IResource.FILE: >+ IResource resource = delta.getResource(); >+ String fileName = resource.getName(); >+ if (Util.isClassFile(fileName)) { >+ findAffectedSourceFiles(delta); >+ } else if (Util.isJavaFileName(fileName)) { >+ IProject project = resource.getProject(); >+ if (IncrementalApiBuilder.this.project.equals(project)) { >+ if (delta.getKind() == IResourceDelta.ADDED) { >+ IncrementalApiBuilder.this.addremovedeltas.add(delta); >+ } >+ IncrementalApiBuilder.this.changedtypes.add(resource); >+ } else if (this.projects != null) { >+ loop: for (int i = 0, max = this.projects.length; i < max; i++) { >+ if (this.projects[i].equals(project)) { >+ IncrementalApiBuilder.this.changedtypes.add(resource); >+ break loop; >+ } >+ } >+ } >+ } else if (!fRequireFullBuild && IApiCoreConstants.API_FILTERS_XML_NAME.equals(fileName)) { >+ switch(delta.getKind()) { >+ case IResourceDelta.REMOVED : >+ case IResourceDelta.REPLACED : >+ case IResourceDelta.CHANGED : >+ case IResourceDelta.ADDED : >+ fRequireFullBuild = true; >+ } >+ } >+ } >+ return false; >+ } >+ } >+ >+ State state = null; >+ ApiAnalysisBuilder builder = null; >+ IProject project = null; >+ HashSet changedtypes = new HashSet(16); >+ HashSet addremovedeltas = new HashSet(8); >+ StringSet typenames = new StringSet(16); >+ StringSet packages = new StringSet(16); >+ >+ >+ /** >+ * Constructor >+ * @param project the current project context being built >+ * @param delta the {@link IResourceDelta} from the build framework >+ * @param buildstate the current build state from the {@link org.eclipse.jdt.internal.core.builder.JavaBuilder} >+ */ >+ public IncrementalApiBuilder(ApiAnalysisBuilder builder) { >+ this.builder = builder; >+ this.state = null; >+ } >+ >+ /** >+ * Incrementally builds using the {@link org.eclipse.pde.api.tools.internal.provisional.builder.IApiAnalyzer} >+ * from the given {@link ApiAnalysisBuilder} >+ * >+ * @param baseline >+ * @param deltas >+ * @param monitor >+ * @throws CoreException >+ */ >+ public void build(IApiBaseline baseline, IResourceDelta[] deltas, IProgressMonitor monitor) throws CoreException { >+ this.project = this.builder.getProject(); >+ SubMonitor localmonitor = SubMonitor.convert(monitor, NLS.bind("API analysis: Incrementally building... {0}", this.project), 10); >+ try { >+ this.state = (State)JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, localmonitor.newChild(1)); >+ if(this.state == null) { >+ this.builder.buildAll(baseline, localmonitor); >+ } >+ this.builder.clearLastState(); >+ //start incremental preparing >+ build(this.state, baseline, localmonitor.newChild(1)); >+ } >+ finally { >+ if(!localmonitor.isCanceled()) { >+ localmonitor.done(); >+ } >+ this.changedtypes.clear(); >+ } >+ } >+ >+ /** >+ * Collects the complete set of affected source files from the current project context based on the current JDT build state. >+ * >+ * @param state >+ */ >+ private void collectAffectedSourceFiles(State state, Set typesToCheck) { >+ // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' >+ char[][][] internedQualifiedNames = ReferenceCollection.internQualifiedNames(this.packages); >+ // if a well known qualified name was found then we can skip over these >+ if (internedQualifiedNames.length < this.packages.elementSize) { >+ internedQualifiedNames = null; >+ } >+ char[][] internedSimpleNames = ReferenceCollection.internSimpleNames(this.typenames, true); >+ // if a well known name was found then we can skip over these >+ if (internedSimpleNames.length < this.typenames.elementSize) { >+ internedSimpleNames = null; >+ } >+ Object[] keyTable = state.getReferences().keyTable; >+ Object[] valueTable = state.getReferences().valueTable; >+ next : for (int i = 0, l = valueTable.length; i < l; i++) { >+ String typeLocator = (String) keyTable[i]; >+ if (typeLocator != null) { >+ ReferenceCollection refs = (ReferenceCollection) valueTable[i]; >+ if (refs.includes(internedQualifiedNames, internedSimpleNames, null)) { >+ IFile file = this.project.getFile(typeLocator); >+ if (file == null) { >+ continue next; >+ } >+ if (ApiAnalysisBuilder.DEBUG) { >+ System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$ >+ } >+ typesToCheck.add(file); >+ } >+ } >+ } >+ } >+ >+ /** >+ * Finds affected source files for a resource that has changed that either contains class files or is itself a class file >+ * @param binaryDelta >+ */ >+ private void findAffectedSourceFiles(IResourceDelta binaryDelta) { >+ IResource resource = binaryDelta.getResource(); >+ if(resource.getType() == IResource.FILE) { >+ if (Util.isClassFile(resource.getName())) { >+ switch (binaryDelta.getKind()) { >+ case IResourceDelta.REMOVED : >+ //fAddedRemovedDeltas.add(binaryDelta); >+ //$FALL-THROUGH$ >+ case IResourceDelta.ADDED : { >+ IPath typePath = resolveJavaPathFromResource(resource); >+ if(typePath == null) { >+ return; >+ } >+ if (ApiAnalysisBuilder.DEBUG) { >+ System.out.println("Found added/removed class file " + typePath); //$NON-NLS-1$ >+ } >+ addDependentsOf(typePath); >+ return; >+ } >+ case IResourceDelta.CHANGED : { >+ if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0) { >+ return; // skip it since it really isn't changed >+ } >+ IPath typePath = resolveJavaPathFromResource(resource); >+ if(typePath == null) { >+ return; >+ } >+ if (ApiAnalysisBuilder.DEBUG) { >+ System.out.println("Found changed class file " + typePath); //$NON-NLS-1$ >+ } >+ addDependentsOf(typePath); >+ } >+ } >+ return; >+ } >+ } >+ } >+ >+ /** >+ * Adds a type to search for dependents of in considered projects for an incremental build >+ * >+ * @param path >+ */ >+ void addDependentsOf(IPath path) { >+ // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X' >+ path = path.setDevice(null); >+ String packageName = path.removeLastSegments(1).toString(); >+ String typeName = path.lastSegment(); >+ int memberIndex = typeName.indexOf('$'); >+ if (memberIndex > 0) { >+ typeName = typeName.substring(0, memberIndex); >+ } >+ if (this.typenames.add(typeName) && this.packages.add(packageName) && ApiAnalysisBuilder.DEBUG) { >+ System.out.println(" will look for dependents of " + typeName + " in " + packageName); //$NON-NLS-1$ //$NON-NLS-2$ >+ } >+ } >+ >+ /** >+ * Builds an API delta using the default profile (from the workspace settings and the current >+ * workspace profile >+ * @param state >+ * @param monitor >+ */ >+ private void build(final State state, IApiBaseline baseline, IProgressMonitor monitor) throws CoreException { >+ IApiBaseline wsprofile = null; >+ try { >+ int typesToCheckSize = this.changedtypes.size(); >+ SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 2 + (typesToCheckSize != 0 ? 3 : 0)); >+ localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_finding_affected_source_files, this.project.getName())); >+ this.builder.updateMonitor(localMonitor, 0); >+ collectAffectedSourceFiles(state, this.changedtypes); >+ this.builder.updateMonitor(localMonitor, 1); >+ if (typesToCheckSize != 0) { >+ IPluginModelBase currentModel = this.builder.getCurrentModel(); >+ if (currentModel != null) { >+ wsprofile = this.builder.getWorkspaceProfile(); >+ if (wsprofile == null) { >+ if (ApiAnalysisBuilder.DEBUG) { >+ System.err.println("Could not retrieve a workspace profile"); //$NON-NLS-1$ >+ } >+ return; >+ } >+ String id = currentModel.getBundleDescription().getSymbolicName(); >+ IApiComponent apiComponent = wsprofile.getApiComponent(id); >+ if(apiComponent == null) { >+ return; >+ } >+ List tnames = new ArrayList(typesToCheckSize), >+ cnames = new ArrayList(typesToCheckSize); >+ collectAllQualifiedNames(this.changedtypes, tnames, cnames, localMonitor.newChild(1)); >+ this.builder.updateMonitor(localMonitor, 1); >+ this.builder.getAnalyzer().analyzeComponent(null, >+ null, >+ null, >+ baseline, >+ apiComponent, >+ (String[])tnames.toArray(new String[tnames.size()]), >+ (String[])cnames.toArray(new String[cnames.size()]), >+ localMonitor.newChild(1)); >+ this.builder.updateMonitor(localMonitor, 1); >+ this.builder.createMarkers(); >+ this.builder.updateMonitor(localMonitor, 1); >+ } >+ } >+ } >+ finally { >+ if(wsprofile != null) { >+ wsprofile.close(); >+ } >+ if(monitor != null) { >+ monitor.done(); >+ } >+ } >+ } >+ >+ /** >+ * Returns an array of type names, and cleans up markers for the specified resource >+ * @param alltypes the listing of {@link IFile}s to get qualified names from >+ * @param changedtypes the listing of {@link IFile}s that have actually changed (from the {@link IResourceDelta} >+ * @param tnames the list to collect all type names into (including inner member names) >+ * @param cnames the list to collect the changed type names into >+ * @param monitor >+ */ >+ private void collectAllQualifiedNames(final HashSet alltypes, List tnames, List cnames, final IProgressMonitor monitor) { >+ IType[] types = null; >+ IFile file = null; >+ for (Iterator iterator = alltypes.iterator(); iterator.hasNext(); ) { >+ file = (IFile) iterator.next(); >+ ICompilationUnit unit = (ICompilationUnit) JavaCore.create(file); >+ if(!unit.exists()) { >+ continue; >+ } >+ IType type = unit.findPrimaryType(); >+ if(type == null) { >+ continue; >+ } >+ this.builder.updateMonitor(monitor, 0); >+ this.builder.cleanupUnsupportedTagMarkers(file); >+ this.builder.updateMonitor(monitor, 0); >+ this.builder.cleanupCompatibilityMarkers(file); >+ this.builder.updateMonitor(monitor, 0); >+ cnames.add(type.getFullyQualifiedName()); >+ try { >+ this.builder.cleanupUsageMarkers(file); >+ this.builder.updateMonitor(monitor, 0); >+ types = unit.getAllTypes(); >+ String tname = null; >+ for (int i = 0; i < types.length; i++) { >+ IType type2 = types[i]; >+ if (type2.isMember()) { >+ tname = type2.getFullyQualifiedName('$'); >+ } else { >+ tname = type2.getFullyQualifiedName(); >+ } >+ tnames.add(tname); >+ } >+ } catch (JavaModelException e) { >+ ApiPlugin.log(e.getStatus()); >+ } >+ this.builder.updateMonitor(monitor, 0); >+ } >+ // inject removed types inside changed type names so that we can properly detect type removal >+ for (Iterator iterator = this.addremovedeltas.iterator(); iterator.hasNext(); ) { >+ IResourceDelta delta = (IResourceDelta) iterator.next(); >+ if (delta.getKind() != IResourceDelta.REMOVED) continue; >+ IResource resource = delta.getResource(); >+ IPath typePath = resolveJavaPathFromResource(resource); >+ if(typePath == null) { >+ continue; >+ } >+ // record removed type names (package + type) >+ StringBuffer buffer = new StringBuffer(); >+ String[] segments = typePath.segments(); >+ for (int i = 0, max = segments.length; i < max; i++) { >+ if (i > 0) { >+ buffer.append('.'); >+ } >+ buffer.append(segments[i]); >+ } >+ cnames.add(String.valueOf(buffer)); >+ } >+ // clean up markers on added deltas >+ if (!this.addremovedeltas.isEmpty()) { >+ IResource manifestFile = Util.getManifestFile(this.project); >+ if (manifestFile != null) { >+ try { >+ IMarker[] markers = manifestFile.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); >+ for (int i = 0, max = markers.length; i < max; i++) { >+ IMarker marker = markers[i]; >+ String typeName = marker.getAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_TYPE_NAME, null); >+ if (typeName != null) { >+ for (Iterator iterator = this.addremovedeltas.iterator(); iterator.hasNext(); ) { >+ IResourceDelta delta = (IResourceDelta) iterator.next(); >+ if (delta.getKind() != IResourceDelta.ADDED) { >+ continue; >+ } >+ ICompilationUnit unit = (ICompilationUnit) JavaCore.create(delta.getResource()); >+ if(!unit.exists()) { >+ continue; >+ } >+ IType type = unit.findPrimaryType(); >+ if(type == null) { >+ continue; >+ } >+ if (typeName.equals(type.getFullyQualifiedName())) { >+ marker.delete(); >+ return; >+ } else { >+ // check secondary types >+ try { >+ types = unit.getAllTypes(); >+ for (int j = 0; j < types.length; j++) { >+ IType type2 = types[i]; >+ String fullyQualifiedName = null; >+ if (type2.isMember()) { >+ fullyQualifiedName = type2.getFullyQualifiedName('$'); >+ } else { >+ fullyQualifiedName = type2.getFullyQualifiedName(); >+ } >+ if (typeName.equals(fullyQualifiedName)) { >+ marker.delete(); >+ return; >+ } >+ } >+ } catch (JavaModelException e) { >+ ApiPlugin.log(e.getStatus()); >+ } >+ } >+ } >+ } >+ } >+ } catch (CoreException e) { >+ ApiPlugin.log(e.getStatus()); >+ } >+ } >+ } >+ IResource resource = this.project.findMember(ApiAnalysisBuilder.MANIFEST_PATH); >+ if (resource != null) { >+ try { >+ IMarker[] markers = resource.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); >+ loop: for (int i = 0, max = markers.length; i < max; i++) { >+ IMarker marker = markers[i]; >+ String typeNameFromMarker = Util.getTypeNameFromMarker(marker); >+ for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) { >+ String typeName = (String) iterator.next(); >+ if (typeName.equals(typeNameFromMarker)) { >+ marker.delete(); >+ continue loop; >+ } >+ } >+ } >+ markers = resource.findMarkers(IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); >+ loop: for (int i = 0, max = markers.length; i < max; i++) { >+ IMarker marker = markers[i]; >+ String typeNameFromMarker = Util.getTypeNameFromMarker(marker); >+ for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) { >+ String typeName = (String) iterator.next(); >+ if (typeName.equals(typeNameFromMarker)) { >+ marker.delete(); >+ continue loop; >+ } >+ } >+ } >+ } catch (CoreException e) { >+ ApiPlugin.log(e); >+ } >+ } >+ } >+ >+ /** >+ * Resolves the java path from the given resource >+ * @param resource >+ * @return the resolved path or <code>null</code> if the resource is not part of the java model >+ */ >+ IPath resolveJavaPathFromResource(IResource resource) { >+ IJavaElement element = JavaCore.create(resource); >+ if(element != null) { >+ switch(element.getElementType()) { >+ case IJavaElement.CLASS_FILE: { >+ org.eclipse.jdt.core.IClassFile classfile = (org.eclipse.jdt.core.IClassFile) element; >+ IType type = classfile.getType(); >+ HashSet paths = this.builder.getProjectOutputPaths(resource.getProject()); >+ if(paths == null) { >+ return null; >+ } >+ IPath prefix = null; >+ for(Iterator iter = paths.iterator(); iter.hasNext();) { >+ prefix = (IPath) iter.next(); >+ if(prefix.isPrefixOf(type.getPath())) { >+ return type.getPath().removeFirstSegments(prefix.segmentCount()).removeFileExtension(); >+ } >+ } >+ break; >+ } >+ } >+ } >+ return null; >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 233643
:
101805
|
126467
|
126895
|
127856
|
130342
|
130743
|
130860
|
131061
|
153351
|
155857