Community
Participate
Working Groups
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(); } }
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--; } }
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.
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()
Verified.