/**
  * 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;
 }