/** * Adds all API super types of the given type to the given list in top down order. * * @param superTypes list to add to * @param type type being processed */ private void gatherAPISuperTypes(List<IApiType> superTypes, IApiType type) throws CoreException { if (type != null) { if (isAPIType(type)) { superTypes.add(0, type); } gatherAPISuperTypes(superTypes, type.getSuperclass()); IApiType[] interfaces = type.getSuperInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (isAPIType(interfaces[i])) { superTypes.add(interfaces[i]); gatherAPISuperTypes(superTypes, interfaces[i]); } } } } }
/* * (non-Javadoc) * @see * org.eclipse.pde.api.tools.internal.search.AbstractTypeLeakDetector#isProblem * (org.eclipse.pde.api.tools.internal.provisional.model.IReference) */ @Override public boolean isProblem(IReference reference) { if (super.isProblem(reference)) { // check the use restrictions on the API type (can be extended or // not) IApiType type = (IApiType) reference.getMember(); IApiComponent component = type.getApiComponent(); try { if (type.isClass()) { int modifiers = 0; IApiAnnotations annotations = component.getApiDescription().resolveAnnotations(type.getHandle()); if (annotations != null) { // if annotations are null, the reference should not // have been retained // as it indicates a reference from a top level non // public type if (RestrictionModifiers.isExtendRestriction(annotations.getRestrictions())) { // The no extend restriction means only public // members can be seen modifiers = Flags.AccPublic; } else { if (Flags.isFinal(type.getModifiers())) { // if final then only public members can be seen modifiers = Flags.AccPublic; } else { // public and protected members can be seen modifiers = Flags.AccPublic | Flags.AccProtected; } } IApiType nonApiSuper = type.getSuperclass(); // collect all visible methods in non-API types Set<MethodKey> methods = new HashSet<MethodKey>(); while (!isAPIType(nonApiSuper)) { if (hasVisibleField(nonApiSuper, modifiers)) { // a visible field in a non-API type is a // definite leak return true; } gatherVisibleMethods(nonApiSuper, methods, modifiers); nonApiSuper = nonApiSuper.getSuperclass(); } if (methods.size() > 0) { // check if the visible members are part of an API // interface/class List<IApiType> apiTypes = new LinkedList<IApiType>(); apiTypes.add(type); gatherAPISuperTypes(apiTypes, type); for (IApiType t2 : apiTypes) { Set<MethodKey> apiMembers = new HashSet<MethodKey>(); gatherVisibleMethods(t2, apiMembers, modifiers); methods.removeAll(apiMembers); if (methods.size() == 0) { // there are no visible methods left that // are not part of an API type/interface return false; } } if (methods.size() > 0) { // there are visible members that are not part // of an API type/interface return true; } } } } else { // don't process interfaces, enums, annotations return true; } } catch (CoreException ce) { if (ApiPlugin.DEBUG_PROBLEM_DETECTOR) { ApiPlugin.log(ce); } return true; } } return false; }