View | Details | Raw Unified | Return to bug 233643 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/pde/api/tools/builder/tests/usage/UnusedApiProblemFilterTests.java (-14 / +17 lines)
Lines 161-171 Link Here
161
	}
161
	}
162
	
162
	
163
	public void testUnusedFilter2F() {
163
	public void testUnusedFilter2F() {
164
//		x2(false);
164
		x2(false);
165
	}
165
	}
166
	
166
	
167
	public void testUnusedFilter2I() {
167
	public void testUnusedFilter2I() {
168
//		x2(true);
168
		x2(true);
169
	}
169
	}
170
	
170
	
171
	/**
171
	/**
Lines 173-191 Link Here
173
	 * problem filter
173
	 * problem filter
174
	 * @param inc
174
	 * @param inc
175
	 */
175
	 */
176
//	private void x2(boolean inc) {
176
	private void x2(boolean inc) {
177
//		String testname = "test2";
177
		String testname = "test2";
178
//		String sourcename = "testUF2";
178
		String sourcename = "testUF2";
179
//		setExpectedProblemIds(getDefaultProblemIdSet(1));
179
		setExpectedProblemIds(getDefaultProblemIdSet(1));
180
//		setExpectedMessageArgs(new String[][] {{"testUF2.m1() has non-API return type internal"}});
180
		setExpectedMessageArgs(new String[][] {{"testUF2.m1() has non-API return type internal"}});
181
//		deployReplacementTest(
181
		deployReplacementTest(
182
//				getBeforePath(testname),
182
				getBeforePath(testname),
183
//				null,
183
				null,
184
//				getFilterFilePath(testname),
184
				getFilterFilePath(testname),
185
//				sourcename,
185
				sourcename,
186
//				inc);
186
				inc);
187
//	}
187
	}
188
188
189
	/**
190
	 * 
191
	 */
189
	public void testUnusedFilter3F() {
192
	public void testUnusedFilter3F() {
190
		x3(false);
193
		x3(false);
191
	}
194
	}
(-)src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java (-142 / +148 lines)
Lines 19-29 Link Here
19
import java.io.FileOutputStream;
19
import java.io.FileOutputStream;
20
import java.io.IOException;
20
import java.io.IOException;
21
import java.util.ArrayList;
21
import java.util.ArrayList;
22
import java.util.Collection;
22
import java.util.Date;
23
import java.util.Date;
23
import java.util.HashMap;
24
import java.util.HashMap;
24
import java.util.HashSet;
25
import java.util.HashSet;
25
import java.util.Iterator;
26
import java.util.Iterator;
26
import java.util.List;
27
import java.util.Map;
27
import java.util.Map;
28
import java.util.Set;
28
import java.util.Set;
29
import java.util.jar.JarFile;
29
import java.util.jar.JarFile;
Lines 87-98 Link Here
87
	 * - removal of the .api_filter file
87
	 * - removal of the .api_filter file
88
	 */
88
	 */
89
	class ResourceDeltaVisitor implements IResourceDeltaVisitor {
89
	class ResourceDeltaVisitor implements IResourceDeltaVisitor {
90
		IProject[] projects;
90
		
91
		public ResourceDeltaVisitor(IProject[] projects) {
91
		private boolean fRequireFullBuild = false;
92
		private Set projects;
93
		
94
		/**
95
		 * Constructor
96
		 * @param projects
97
		 */
98
		public ResourceDeltaVisitor(Set/*<IProject>*/ projects) {
92
			this.projects = projects;
99
			this.projects = projects;
93
		}
100
		}
94
		private boolean fRequireFullBuild = false;
101
		
95
96
		/**
102
		/**
97
		 * Returns whether a full build should be run.
103
		 * Returns whether a full build should be run.
98
		 * 
104
		 * 
Lines 125-140 Link Here
125
						IProject project = resource.getProject();
131
						IProject project = resource.getProject();
126
						if (fCurrentProject.equals(project)) {
132
						if (fCurrentProject.equals(project)) {
127
							if (delta.getKind() == IResourceDelta.ADDED) {
133
							if (delta.getKind() == IResourceDelta.ADDED) {
128
								fAddedRemovedDeltas.add(delta);
134
								fAddedDeltas.add(delta);
129
							}
130
							fTypesToCheck.add(resource);
131
						} else if (this.projects != null) {
132
							loop: for (int i = 0, max = this.projects.length; i < max; i++) {
133
								if (this.projects[i].equals(project)) {
134
									fTypesToCheck.add(resource);
135
									break loop;
136
								}
137
							}
135
							}
136
							fChangedTypesToCheck.add(resource);
137
						} else if (this.projects.contains(project)) {
138
							fChangedTypesToCheck.add(resource);
138
						}
139
						}
139
					} else if (!fRequireFullBuild && IApiCoreConstants.API_FILTERS_XML_NAME.equals(fileName)) {
140
					} else if (!fRequireFullBuild && IApiCoreConstants.API_FILTERS_XML_NAME.equals(fileName)) {
140
						switch(delta.getKind()) {
141
						switch(delta.getKind()) {
Lines 202-214 Link Here
202
	private StringSet fPackages = new StringSet(3);
203
	private StringSet fPackages = new StringSet(3);
203
	
204
	
204
	/**
205
	/**
205
	 * The type that we want to check for API problems
206
	 * The changed types that we want to check for API problems
207
	 */
208
	private HashSet fChangedTypesToCheck = new HashSet();
209
	/**
210
	 * The computed dependent types we also want to check for API problems 
211
	 */
212
	private HashSet fDependentTypesToCheck = new HashSet();
213
	/**
214
	 * The set of added deltas that come directly from the builder resource delta 
206
	 */
215
	 */
207
	private HashSet fTypesToCheck = new HashSet();
216
	private HashSet fAddedDeltas = new HashSet(4);
217
	
208
	/**
218
	/**
209
	 * The set of added/removed deltas that come directly from the builder resource delta 
219
	 * The set of removed deltas that come directly from the builder {@link IResourceDelta}
210
	 */
220
	 */
211
	private HashSet fAddedRemovedDeltas = new HashSet(5);
221
	private HashSet fRemovedDeltas = new HashSet(4);
212
	
222
	
213
	/**
223
	/**
214
	 * Current build state
224
	 * Current build state
Lines 331-341 Link Here
331
					if (fBuildState == null) {
341
					if (fBuildState == null) {
332
						buildAll(baseline, localMonitor.newChild(1));
342
						buildAll(baseline, localMonitor.newChild(1));
333
					} else {
343
					} else {
334
						IProject[] reexportedProjects = null;
344
						HashSet reexportedProjects = new HashSet();
335
						String[] projectNames = this.fBuildState.getReexportedComponents();
345
						String[] projectNames = this.fBuildState.getReexportedComponents();
336
						int length = projectNames.length;
346
						int length = projectNames.length;
337
						if (length != 0) {
347
						if (length != 0) {
338
							List allProjects = new ArrayList();
339
							IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
348
							IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
340
							for (int i = 0, max = projectNames.length; i < max; i++) {
349
							for (int i = 0, max = projectNames.length; i < max; i++) {
341
								String projectName = projectNames[i];
350
								String projectName = projectNames[i];
Lines 343-356 Link Here
343
								if (project.isAccessible()) {
352
								if (project.isAccessible()) {
344
									// select only projects that don't exist in the reference baseline
353
									// select only projects that don't exist in the reference baseline
345
									if (baseline != null && baseline.getApiComponent(projectName) == null) {
354
									if (baseline != null && baseline.getApiComponent(projectName) == null) {
346
										allProjects.add(project);
355
										reexportedProjects.add(project);
347
									}
356
									}
348
								}
357
								}
349
							}
358
							}
350
							if (allProjects.size() != 0) {
351
								reexportedProjects = new IProject[allProjects.size()];
352
								allProjects.toArray(reexportedProjects);
353
							}
354
						}
359
						}
355
						ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(reexportedProjects);
360
						ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(reexportedProjects);
356
						for (int i = 0; i < deltas.length; i++) {
361
						for (int i = 0; i < deltas.length; i++) {
Lines 392-399 Link Here
392
		} finally {
397
		} finally {
393
			fTypes.clear();
398
			fTypes.clear();
394
			fPackages.clear();
399
			fPackages.clear();
395
			fTypesToCheck.clear();
400
			fChangedTypesToCheck.clear();
396
			fAddedRemovedDeltas.clear();
401
			fDependentTypesToCheck.clear();
402
			fAddedDeltas.clear();
397
			fProjectToOutputLocations.clear();
403
			fProjectToOutputLocations.clear();
398
			updateMonitor(monitor, 0);
404
			updateMonitor(monitor, 0);
399
			fAnalyzer.dispose();
405
			fAnalyzer.dispose();
Lines 647-657 Link Here
647
		IApiBaseline wsprofile = null;
653
		IApiBaseline wsprofile = null;
648
		try {
654
		try {
649
			clearLastState(); // so if the build fails, a full build will be triggered
655
			clearLastState(); // so if the build fails, a full build will be triggered
650
			int typesToCheckSize = fTypesToCheck.size();
656
			int typesToCheckSize = fChangedTypesToCheck.size();
651
			SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 2 + (typesToCheckSize != 0 ? 3 : 0));
657
			SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 3 + (typesToCheckSize != 0 ? 3 : 0));
652
			localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_finding_affected_source_files, fCurrentProject.getName()));
658
			localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_finding_affected_source_files, fCurrentProject.getName()));
653
			updateMonitor(localMonitor, 0);
659
			updateMonitor(localMonitor, 0);
654
			collectAffectedSourceFiles(state, fTypesToCheck);
660
			collectAffectedSourceFiles(state, fDependentTypesToCheck);
655
			updateMonitor(localMonitor, 1);
661
			updateMonitor(localMonitor, 1);
656
			if (typesToCheckSize != 0) {
662
			if (typesToCheckSize != 0) {
657
				IPluginModelBase currentModel = getCurrentModel();
663
				IPluginModelBase currentModel = getCurrentModel();
Lines 668-677 Link Here
668
					if(apiComponent == null) {
674
					if(apiComponent == null) {
669
						return;
675
						return;
670
					}
676
					}
671
					List tnames = new ArrayList(typesToCheckSize),
677
					HashSet tnames = new HashSet(typesToCheckSize),
672
						 cnames = new ArrayList(typesToCheckSize);
678
						 	cnames = new HashSet(typesToCheckSize);
673
					collectAllQualifiedNames(fTypesToCheck, tnames, cnames, localMonitor.newChild(1));
679
					//collect changed type qualified names
680
					collectAllQualifiedNames(fChangedTypesToCheck, tnames, cnames, false, localMonitor.newChild(1));
681
					//collect dependent type qualified names
682
					collectAllQualifiedNames(fDependentTypesToCheck, tnames, cnames, true, localMonitor.newChild(1));
683
					//make sure a type only appears in one place
684
					fDependentTypesToCheck.removeAll(fChangedTypesToCheck);
685
					IPath path = null;
686
					for(Iterator iter = fRemovedDeltas.iterator(); iter.hasNext();) {
687
						path = resolveJavaPathFromResource(((IResourceDelta) iter.next()).getResource());
688
						if(path != null) {
689
							cnames.add(path.toString().replace('/', '.'));
690
						}
691
					}
674
					updateMonitor(localMonitor, 1);
692
					updateMonitor(localMonitor, 1);
693
					//clean up markers on the manifest
694
					IResource manifestFile = Util.getManifestFile(this.fCurrentProject);
695
					if (manifestFile != null) {
696
						try {
697
							IMarker[] markers = manifestFile.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
698
							cleanMarkersWithTypeNames(markers, tnames);
699
							cleanMarkersWithTypeNames(markers, getTypeNamesFromDeltas(this.fAddedDeltas, IResourceDelta.ADDED, true));
700
							cleanMarkersWithTypeNames(manifestFile.findMarkers(IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER, false, IResource.DEPTH_ZERO), tnames);
701
						} catch (CoreException e) {
702
							ApiPlugin.log(e.getStatus());
703
						}
704
					}
675
					fAnalyzer.analyzeComponent(fBuildState, 
705
					fAnalyzer.analyzeComponent(fBuildState, 
676
							null, 
706
							null, 
677
							null, 
707
							null, 
Lines 704-849 Link Here
704
	 * @param cnames the list to collect the changed type names into
734
	 * @param cnames the list to collect the changed type names into
705
	 * @param monitor
735
	 * @param monitor
706
	 */
736
	 */
707
	private void collectAllQualifiedNames(final HashSet alltypes, List tnames, List cnames, final IProgressMonitor monitor) {
737
	private void collectAllQualifiedNames(final HashSet alltypes, Set tnames, Set cnames, boolean dependenttypes, final IProgressMonitor monitor) {
708
		IType[] types = null;
738
		IType[] types = null;
709
		IFile file = null;
739
		IFile file = null;
710
		for (Iterator iterator = alltypes.iterator(); iterator.hasNext(); ) {
740
		for (Iterator iterator = alltypes.iterator(); iterator.hasNext(); ) {
711
			file = (IFile) iterator.next();
741
			file = (IFile) iterator.next();
712
			ICompilationUnit unit = (ICompilationUnit) JavaCore.create(file);
742
			IType type = getTypeFromResource(file);
713
			if(!unit.exists()) {
714
				continue;
715
			}
716
			IType type = unit.findPrimaryType();
717
			if(type == null) {
743
			if(type == null) {
718
				continue;
744
				continue;
719
			}
745
			}
746
			if(dependenttypes) {
747
				tnames.add(type.getFullyQualifiedName());
748
			}
749
			else {
750
				cnames.add(type.getFullyQualifiedName());
751
			}
720
			updateMonitor(monitor, 0);
752
			updateMonitor(monitor, 0);
753
			
721
			cleanupUnsupportedTagMarkers(file);
754
			cleanupUnsupportedTagMarkers(file);
722
			updateMonitor(monitor, 0);
755
			updateMonitor(monitor, 0);
723
			cleanupCompatibilityMarkers(file);
756
			cleanupCompatibilityMarkers(file);
724
			updateMonitor(monitor, 0);
757
			updateMonitor(monitor, 0);
725
			cnames.add(type.getFullyQualifiedName());
758
			cleanupUsageMarkers(file);
759
			updateMonitor(monitor, 0);
760
			
726
			try {
761
			try {
727
				cleanupUsageMarkers(file);
762
				types = type.getCompilationUnit().getAllTypes();
728
				updateMonitor(monitor, 0);
729
				types = unit.getAllTypes();
730
				String tname = null;
731
				for (int i = 0; i < types.length; i++) {
763
				for (int i = 0; i < types.length; i++) {
732
					IType type2 = types[i];
764
					IType type2 = types[i];
733
					if (type2.isMember()) {
765
					if (type2.isMember()) {
734
						tname = type2.getFullyQualifiedName('$');
766
						tnames.add(type2.getFullyQualifiedName('$'));
735
					} else {
767
					} else {
736
						tname = type2.getFullyQualifiedName();
768
						tnames.add(type2.getFullyQualifiedName());
737
					}
769
					}
738
					tnames.add(tname);
739
				}
770
				}
740
			} catch (JavaModelException e) {
771
			} catch (JavaModelException e) {
741
				ApiPlugin.log(e.getStatus());
772
				ApiPlugin.log(e.getStatus());
742
			}
773
			}
743
			updateMonitor(monitor, 0);
774
			updateMonitor(monitor, 0);
744
		}
775
		}
745
		// inject removed types inside changed type names so that we can properly detect type removal
776
	}
746
		for (Iterator iterator = this.fAddedRemovedDeltas.iterator(); iterator.hasNext(); ) {
777
	
747
			IResourceDelta delta = (IResourceDelta) iterator.next();
778
	/**
748
			if (delta.getKind() != IResourceDelta.REMOVED) continue;
779
	 * Returns the primary {@link IType} for the {@link IJavaElement} represented by the 
749
			IResource resource = delta.getResource();
780
	 * given {@link IResource}, or <code>null</code> if the element does not exist
750
			IPath typePath = resolveJavaPathFromResource(resource);
781
	 * 
751
			if(typePath == null) {
782
	 * @param resource
783
	 * @return
784
	 */
785
	private IType getTypeFromResource(IResource resource) {
786
		ICompilationUnit unit = (ICompilationUnit) JavaCore.create(resource);
787
		if(unit.exists()) {
788
			return unit.findPrimaryType();
789
		}
790
		return null;
791
	}
792
	
793
	/**
794
	 * Collects the fully qualified type names from the elements in the collection 
795
	 * of {@link IResourceDelta}s.
796
	 * 
797
	 * @param deltas the collection of deltas
798
	 * @param deltakind the kind of delta we should care about
799
	 * @param includesubstypes if we should include sub-types for a root type from the delta
800
	 * @return a list of fully qualified type names
801
	 * @throws CoreException
802
	 */
803
	private Set/*<String>*/ getTypeNamesFromDeltas(Collection/*<IResourceDelta>*/ deltas, int deltakind, boolean includesubstypes) throws CoreException {
804
		HashSet names = new HashSet(deltas.size());
805
		IResourceDelta delta = null;
806
		IType type = null;
807
		IType[] types = null;
808
		for (Iterator iterator = deltas.iterator(); iterator.hasNext();) {
809
			delta = (IResourceDelta) iterator.next();
810
			if(delta.getKind() != deltakind) {
752
				continue;
811
				continue;
753
			}
812
			}
754
			// record removed type names (package + type)
813
			type = getTypeFromResource(delta.getResource());
755
			StringBuffer buffer = new StringBuffer();
814
			if(type == null) {
756
			String[] segments = typePath.segments();
815
				continue;
757
			for (int i = 0, max = segments.length; i < max; i++) {
758
				if (i > 0) {
759
					buffer.append('.');
760
				}
761
				buffer.append(segments[i]);
762
			}
816
			}
763
			cnames.add(String.valueOf(buffer));
817
			names.add(type.getFullyQualifiedName());
764
		}
818
			if(includesubstypes) {
765
		// clean up markers on added deltas
819
				types = type.getCompilationUnit().getAllTypes();
766
		if (!this.fAddedRemovedDeltas.isEmpty()) {
820
				for (int j = 0; j < types.length; j++) {
767
			IResource manifestFile = Util.getManifestFile(this.fCurrentProject);
821
					IType type2 = types[j];
768
			if (manifestFile != null) {
822
					if (type2.isMember()) {
769
				try {
823
						names.add(type2.getFullyQualifiedName('$'));
770
					IMarker[] markers = manifestFile.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
824
					} else {
771
					for (int i = 0, max = markers.length; i < max; i++) {
825
						names.add(type2.getFullyQualifiedName());
772
						IMarker marker = markers[i];
773
						String typeName = marker.getAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_TYPE_NAME, null);
774
						if (typeName != null) {
775
							for (Iterator iterator = this.fAddedRemovedDeltas.iterator(); iterator.hasNext(); ) {
776
								IResourceDelta delta = (IResourceDelta) iterator.next();
777
								if (delta.getKind() != IResourceDelta.ADDED) continue;
778
								ICompilationUnit unit = (ICompilationUnit) JavaCore.create(delta.getResource());
779
								if(!unit.exists()) {
780
									continue;
781
								}
782
								IType type = unit.findPrimaryType();
783
								if(type == null) {
784
									continue;
785
								}
786
								if (typeName.equals(type.getFullyQualifiedName())) {
787
									marker.delete();
788
									return;
789
								} else {
790
									// check secondary types
791
									try {
792
										types = unit.getAllTypes();
793
										for (int j = 0; j < types.length; j++) {
794
											IType type2 = types[i];
795
											String fullyQualifiedName = null;
796
											if (type2.isMember()) {
797
												fullyQualifiedName = type2.getFullyQualifiedName('$');
798
											} else {
799
												fullyQualifiedName = type2.getFullyQualifiedName();
800
											}
801
											if (typeName.equals(fullyQualifiedName)) {
802
												marker.delete();
803
												return;
804
											}
805
										}
806
									} catch (JavaModelException e) {
807
										ApiPlugin.log(e.getStatus());
808
									}
809
								}
810
							}
811
						}
812
					}
826
					}
813
				} catch (CoreException e) {
814
					ApiPlugin.log(e.getStatus());
815
				}
827
				}
816
			}
828
			}
817
		}
829
		}
818
		IResource resource = fCurrentProject.findMember(MANIFEST_PATH);
830
		return names;
819
		if (resource != null) {
831
	}
820
			try {
832
	
821
				IMarker[] markers = resource.findMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
833
	/**
822
				loop: for (int i = 0, max = markers.length; i < max; i++) {
834
	 * Deletes markers from the workspace that have a type name that is in the given listing
823
					IMarker marker = markers[i];
835
	 * of type names.
824
					String typeNameFromMarker = Util.getTypeNameFromMarker(marker);
836
	 * 
825
					for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) {
837
	 * @param markers the list of markers to examine
826
						String typeName = (String) iterator.next();
838
	 * @param typenames the list of type names to check for in the listing of markers
827
						if (typeName.equals(typeNameFromMarker)) {
839
	 * @throws CoreException
828
							marker.delete();
840
	 */
829
							continue loop;
841
	private void cleanMarkersWithTypeNames(IMarker[] markers, final Set/*<String>*/ typenames) throws CoreException {
830
						}
842
		if((markers != null && markers.length > 0) && (typenames != null && typenames.size() > 0)) {
831
					}
843
			loop: for (int i = 0, max = markers.length; i < max; i++) {
832
				}
844
				IMarker marker = markers[i];
833
				markers = resource.findMarkers(IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
845
				String typeNameFromMarker = Util.getTypeNameFromMarker(marker);
834
				loop: for (int i = 0, max = markers.length; i < max; i++) {
846
				for (Iterator iterator = typenames.iterator(); iterator.hasNext(); ) {
835
					IMarker marker = markers[i];
847
					String typeName = (String) iterator.next();
836
					String typeNameFromMarker = Util.getTypeNameFromMarker(marker);
848
					if (typeName.equals(typeNameFromMarker)) {
837
					for (Iterator iterator = tnames.iterator(); iterator.hasNext(); ) {
849
						marker.delete();
838
						String typeName = (String) iterator.next();
850
						continue loop;
839
						if (typeName.equals(typeNameFromMarker)) {
840
							marker.delete();
841
							continue loop;
842
						}
843
					}
851
					}
844
				}
852
				}
845
			} catch (CoreException e) {
846
				ApiPlugin.log(e);
847
			}
853
			}
848
		}
854
		}
849
	}
855
	}
Lines 928-936 Link Here
928
			if (Util.isClassFile(resource.getName())) {
934
			if (Util.isClassFile(resource.getName())) {
929
				switch (binaryDelta.getKind()) {
935
				switch (binaryDelta.getKind()) {
930
					case IResourceDelta.REMOVED :
936
					case IResourceDelta.REMOVED :
931
						fAddedRemovedDeltas.add(binaryDelta);
937
						fRemovedDeltas.add(binaryDelta);
932
						//$FALL-THROUGH$
938
						//$FALL-THROUGH$
933
					case IResourceDelta.ADDED : {
939
				case IResourceDelta.ADDED : {
934
						IPath typePath = resolveJavaPathFromResource(resource);
940
						IPath typePath = resolveJavaPathFromResource(resource);
935
						if(typePath == null) {
941
						if(typePath == null) {
936
							return;
942
							return;

Return to bug 233643