Bug 37438

Summary: searchenging NPE in searchDeclarationsOfReferencedTypes
Product: [Eclipse Project] JDT Reporter: Frank Sauer <frank.sauer>
Component: CoreAssignee: Jerome Lanneluc <jerome_lanneluc>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: 2.1   
Target Milestone: 3.0 M1   
Hardware: PC   
OS: Windows 2000   
Whiteboard:

Description Frank Sauer CLA 2003-05-09 12:05:42 EDT
This code snippet (note that source.getJavaElement() yields an IPackageFragment 
in this case):

	private Metric calculateEfferentCoupling(PackageFragmentMetrics source) 
{
		SearchEngine searchEngine = new SearchEngine();
		EfferentCollector c = new EfferentCollector(source);
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		try {
			searchEngine.searchDeclarationsOfReferencedTypes
(workspace, source.getJavaElement(), c);
			return c.getResult();
		} catch (JavaModelException e) {
			MetricsPlugin.logError("Error searching for efferent 
couplings", e);
			return null;
		}
	}


java.lang.NullPointerException
	at 
org.eclipse.jdt.internal.core.search.matching.DeclarationOfReferencedTypesPatter
n.reportDeclaration(DeclarationOfReferencedTypesPattern.java:137)
	at 
org.eclipse.jdt.internal.core.search.matching.DeclarationOfReferencedTypesPatter
n.matchReportReference(DeclarationOfReferencedTypesPattern.java:118)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchLocator2.reportSuperTypeRefer
ence(MatchLocator2.java:1365)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchingNodeSet.reportMatching
(MatchingNodeSet.java:476)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchingNodeSet$LocalDeclarationVi
sitor.visit(MatchingNodeSet.java:72)
	at 
org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration.traverse
(AnonymousLocalTypeDeclaration.java:138)
	at 
org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression.traverse
(QualifiedAllocationExpression.java:342)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.traverse
(MessageSend.java:290)
	at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.traverse
(MethodDeclaration.java:157)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchingNodeSet.reportMatching
(MatchingNodeSet.java:227)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchingNodeSet.reportMatching
(MatchingNodeSet.java:448)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchingNodeSet.reportMatching
(MatchingNodeSet.java:346)
	at org.eclipse.jdt.internal.core.search.matching.MatchLocator2.process
(MatchLocator2.java:978)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchLocator2.locateMatches
(MatchLocator2.java:677)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchLocator2.locateMatches
(MatchLocator2.java:635)
	at 
org.eclipse.jdt.internal.core.search.matching.MatchLocator2.locateMatches
(MatchLocator2.java:851)
	at org.eclipse.jdt.core.search.SearchEngine.search
(SearchEngine.java:471)
	at 
org.eclipse.jdt.core.search.SearchEngine.searchDeclarationsOfReferencedTypes
(SearchEngine.java:707)
	at 
net.sourceforge.metrics.calculators.RMartinCouplings.calculateEfferentCoupling
(RMartinCouplings.java:160)


To ensure this is not caused by my collector, I catch all exceptions in the
accept method, just to find out:

		public void accept(IResource resource, int start, int end, 
IJavaElement enclosingElement, int accuracy) throws CoreException {
			try {
				if (enclosingElement != null) {
					// don't count references to standard 
java(x) API and internal (same package)
					String type = 
enclosingElement.getHandleIdentifier();
					IJavaElement pack = 
enclosingElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
					if ((!source.getJavaElement().equals
(pack))&&(!pack.getElementName().startsWith("java"))) {
						results.add(type);
						packages.add
(pack.getHandleIdentifier());
					}
				}			
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
Comment 1 Frank Sauer CLA 2003-05-09 13:27:22 EDT
here's the offending code:
line marked with >>>
TypeDeclaration typeDecl = ((SourceTypeBinding)
typeBinding).scope.referenceContext;

I guess either typeBinding or its scope must be null for some reason...
Note that for some packages it works, others cause this problem.

private void reportDeclaration(TypeBinding typeBinding, int maxType, 
MatchLocator locator) throws CoreException {
	IType type = locator.lookupType(typeBinding);
	if (type == null) return; // case of a secondary type
	IResource resource = type.getResource();
	boolean isBinary = type.isBinary();
	IBinaryType info = null;
	if (isBinary) {
		if (resource == null) {
			resource = type.getJavaProject().getProject();
		}
		info = locator.getBinaryInfo
((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
	}
	while (maxType >= 0 && type != null) {
		if (!this.knownTypes.contains(type)) {
			if (isBinary) {
				locator.reportBinaryMatch(resource, type, info, 
IJavaSearchResultCollector.EXACT_MATCH);
			} else {
>>>				TypeDeclaration typeDecl = ((SourceTypeBinding)
typeBinding).scope.referenceContext;
				locator.report(resource, typeDecl.sourceStart, 
typeDecl.sourceEnd, type, IJavaSearchResultCollector.EXACT_MATCH);
			}
			this.knownTypes.add(type);
		}
		if (typeBinding instanceof BinaryTypeBinding) {
			typeBinding = ((BinaryTypeBinding)
typeBinding).enclosingType();
		} else {
			typeBinding = ((SourceTypeBinding)
typeBinding).enclosingType();
		}
		IJavaElement parent = type.getParent();
		if (parent instanceof IType) {
			type = (IType)parent;
		} else {
			type = null;
		}
		maxType--;
	}
}
Comment 2 Frank Sauer CLA 2003-05-12 08:36:01 EDT
never mind, case of RTFM. Doesn't work with packages..... Sorry
Perhaps a feature request? Search for all declarations of referenced
types in a package? Now I have to do multiple searches to get the same
effect.
Comment 3 Jerome Lanneluc CLA 2003-05-22 05:21:31 EDT
As Frank noticed this is not supported, but we should not get a NPE. Added 
protection against this case. We now return no result.

Added regression test JavaSearchTests.testDeclarationOfReferencedTypes7()
Comment 4 David Audel CLA 2003-06-06 07:07:54 EDT
Verified.