/** * Returns whether the given type has API visibility. * * @param type type * @return whether the given type has API visibility */ private boolean isAPIType(IApiType type) throws CoreException { IApiDescription description = type.getApiComponent().getApiDescription(); IApiAnnotations annotations = description.resolveAnnotations(type.getHandle()); if (annotations == null) { // top level non-public top can have no annotations - they are not // API return false; } return VisibilityModifiers.isAPI(annotations.getVisibility()); }
/* * (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; }