예제 #1
0
 @Override
 public int getSeverity() {
   if (ApiPlugin.isRunningInFramework()) {
     return ApiPlugin.getDefault()
         .getSeverityLevel(ApiProblemFactory.getProblemSeverityId(this), null);
   }
   return ApiPlugin.SEVERITY_WARNING;
 }
예제 #2
0
 /* (non-Javadoc)
  * @see org.eclipse.pde.api.tools.internal.provisional.search.IApiProblemDetector#createProblems()
  */
 public List createProblems() {
   List references = getRetainedReferences();
   List problems = new LinkedList();
   Iterator iterator = references.iterator();
   while (iterator.hasNext()) {
     IReference reference = (IReference) iterator.next();
     if (reference.getResolvedReference() == null) {
       // TODO: unresolved reference
     } else {
       if (isProblem(reference)) {
         try {
           IApiProblem problem = null;
           IApiComponent component = reference.getMember().getApiComponent();
           if (component instanceof ProjectComponent) {
             ProjectComponent ppac = (ProjectComponent) component;
             IJavaProject project = ppac.getJavaProject();
             problem = createProblem(reference, project);
           } else {
             problem = createProblem(reference);
           }
           if (problem != null) {
             problems.add(problem);
           }
         } catch (CoreException e) {
           ApiPlugin.log(e.getStatus());
         }
       }
     }
   }
   return problems;
 }
 /*
  * (non-Javadoc)
  * @see
  * org.eclipse.pde.api.tools.internal.provisional.search.IApiProblemDetector
  * #createProblems()
  */
 @Override
 public List<IApiProblem> createProblems() {
   List<IReference> references = getRetainedReferences();
   List<IApiProblem> problems = new LinkedList<IApiProblem>();
   for (IReference reference : references) {
     if (isProblem(reference)) {
       try {
         IApiProblem problem = null;
         IApiComponent component = reference.getMember().getApiComponent();
         if (component instanceof ProjectComponent) {
           ProjectComponent ppac = (ProjectComponent) component;
           IJavaProject project = ppac.getJavaProject();
           problem = createProblem(reference, project);
         } else {
           problem = createProblem(reference);
         }
         if (problem != null) {
           problems.add(problem);
         }
       } catch (CoreException e) {
         ApiPlugin.log(e.getStatus());
       }
     }
   }
   return problems;
 }
예제 #4
0
 /**
  * Scans the specified source {@linkplain CompilationUnit} for contributed API javadoc tags. Tags
  * on methods will have unresolved signatures.
  *
  * @param source the source file to scan for tags
  * @param description the API description to annotate with any new tag rules found
  * @param container optional class file container containing the class file for the given source
  *     that can be used to resolve method signatures if required (for tags on methods). If not
  *     provided (<code>null</code>), method signatures will be unresolved.
  * @param options a map of Java compiler options to use when creating the AST to scan or <code>
  *     null</code> if default options should be used
  * @param monitor
  * @throws CoreException
  */
 public void scan(
     CompilationUnit source,
     IApiDescription description,
     IApiTypeContainer container,
     Map options,
     IProgressMonitor monitor)
     throws CoreException {
   SubMonitor localmonitor = SubMonitor.convert(monitor, 2);
   ASTParser parser = ASTParser.newParser(AST.JLS3);
   InputStream inputStream = null;
   try {
     inputStream = source.getInputStream();
     parser.setSource(
         Util.getInputStreamAsCharArray(
             inputStream, -1, System.getProperty("file.encoding"))); // $NON-NLS-1$
   } catch (FileNotFoundException e) {
     throw new CoreException(
         new Status(
             IStatus.ERROR,
             ApiPlugin.PLUGIN_ID,
             MessageFormat.format(
                 "Compilation unit source not found: {0}", new String[] {source.getName()}),
             e)); //$NON-NLS-1$
   } catch (IOException e) {
     if (DEBUG) {
       System.err.println(source.getName());
     }
     throw new CoreException(
         new Status(
             IStatus.ERROR,
             ApiPlugin.PLUGIN_ID,
             MessageFormat.format(
                 "Error reading compilation unit: {0}", new String[] {source.getName()}),
             e)); //$NON-NLS-1$
   } finally {
     if (inputStream != null) {
       try {
         inputStream.close();
       } catch (IOException e) {
         ApiPlugin.log(e);
       }
     }
   }
   Util.updateMonitor(localmonitor);
   Map loptions = options;
   if (loptions == null) {
     loptions = JavaCore.getOptions();
   }
   loptions.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
   parser.setCompilerOptions(loptions);
   org.eclipse.jdt.core.dom.CompilationUnit cunit =
       (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(localmonitor.newChild(1));
   Visitor visitor = new Visitor(description, container);
   cunit.accept(visitor);
   if (visitor.getException() != null) {
     throw visitor.getException();
   }
 }
 /*
  * (non-Javadoc)
  * @see
  * org.eclipse.pde.api.tools.internal.search.AbstractProblemDetector#isProblem
  * (org.eclipse.pde.api.tools.internal.provisional.model.IReference)
  */
 @Override
 protected boolean isProblem(IReference reference) {
   // the reference must be in the system library
   try {
     IApiMember member = reference.getMember();
     IApiComponent apiComponent = member.getApiComponent();
     String[] lowestEEs = apiComponent.getLowestEEs();
     if (lowestEEs == null) {
       // this should not be true for Eclipse bundle as they should
       // always have a EE set
       return false;
     }
     loop:
     for (int i = 0, max = lowestEEs.length; i < max; i++) {
       String lowestEE = lowestEEs[i];
       int eeValue = ProfileModifiers.getValue(lowestEE);
       if (eeValue == ProfileModifiers.NO_PROFILE_VALUE) {
         return false;
       }
       if (!((Reference) reference).resolve(eeValue)) {
         /*
          * Make sure that the resolved reference doesn't below to
          * one of the imported package of the current component
          */
         if (apiComponent instanceof BundleComponent) {
           BundleDescription bundle = ((BundleComponent) apiComponent).getBundleDescription();
           ImportPackageSpecification[] importPackages = bundle.getImportPackages();
           String referencedTypeName = reference.getReferencedTypeName();
           int index = referencedTypeName.lastIndexOf('.');
           String packageName = referencedTypeName.substring(0, index);
           for (int j = 0, max2 = importPackages.length; j < max2; j++) {
             ImportPackageSpecification importPackageSpecification = importPackages[j];
             // get the IPackageDescriptor for the element
             // descriptor
             String importPackageName = importPackageSpecification.getName();
             if (importPackageName.equals(packageName)) {
               continue loop;
             }
           }
         }
         if (this.referenceEEs == null) {
           this.referenceEEs = new HashMap<IReference, Integer>(3);
         }
         this.referenceEEs.put(reference, new Integer(eeValue));
         return true;
       }
     }
   } catch (CoreException e) {
     ApiPlugin.log(e);
   }
   return false;
 }
예제 #6
0
 protected boolean isReferenceFromComponent(IReference reference, Object componentId) {
   if (componentId != null) {
     final IApiComponent apiComponent = reference.getResolvedReference().getApiComponent();
     // API component is either component id itself or one of its fragment
     if (apiComponent.getSymbolicName().equals(componentId)) {
       return true;
     }
     try {
       final IApiComponent host = apiComponent.getHost();
       return host != null && host.getSymbolicName().equals(componentId);
     } catch (CoreException e) {
       ApiPlugin.log(e);
     }
   }
   return false;
 }
예제 #7
0
 /**
  * Returns whether the resolved reference is a real problem.
  *
  * @param reference
  * @return whether a problem
  */
 protected boolean isProblem(IReference reference) {
   // by default fragment -> host references are not problems
   // https://bugs.eclipse.org/bugs/show_bug.cgi?id=255659
   IApiMember member = reference.getResolvedReference();
   if (member != null) {
     IApiMember local = reference.getMember();
     try {
       IApiComponent lcomp = local.getApiComponent();
       if (lcomp != null && lcomp.isFragment()) {
         return !lcomp.getHost().equals(member.getApiComponent());
       }
     } catch (CoreException ce) {
       ApiPlugin.log(ce);
     }
   }
   return true;
 }
 /*
  * (non-Javadoc)
  * @see
  * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom
  * .Javadoc)
  */
 @Override
 public boolean visit(Javadoc node) {
   Set<String> tagnames = ApiPlugin.getJavadocTagManager().getAllTagNames();
   List<TagElement> tags = node.tags();
   if (fExistingTags == null) {
     fExistingTags = new HashMap<String, Boolean>(tags.size());
   }
   String name = null;
   for (TagElement tag : tags) {
     name = tag.getTagName();
     if (name == null) {
       continue;
     }
     if (tagnames.contains(name)) {
       // only add existing API tools tags
       fExistingTags.put(name, Boolean.valueOf(tag.fragments().isEmpty()));
     }
   }
   return false;
 }
 /*
  * (non-Javadoc)
  * @see
  * org.eclipse.pde.api.tools.internal.provisional.builder.IApiProblemDetector
  * #
  * considerReference(org.eclipse.pde.api.tools.internal.provisional.builder.
  * IReference)
  */
 @Override
 public boolean considerReference(IReference reference) {
   try {
     IApiComponent apiComponent = reference.getMember().getApiComponent();
     IApiBaseline baseline = apiComponent.getBaseline();
     if (baseline == null) {
       return false;
     }
     String referencedTypeName = reference.getReferencedTypeName();
     // extract the package name
     int index = referencedTypeName.lastIndexOf('.');
     if (index == -1) {
       return false;
     }
     String substring = referencedTypeName.substring(0, index);
     IApiComponent[] resolvePackages = baseline.resolvePackage(apiComponent, substring);
     switch (resolvePackages.length) {
       case 1:
         {
           if (resolvePackages[0].isSystemComponent()) {
             switch (reference.getReferenceKind()) {
               case IReference.REF_OVERRIDE:
               case IReference.REF_CONSTANTPOOL:
                 return false;
               default:
                 break;
             }
             ((Reference) reference).setResolveStatus(false);
             retainReference(reference);
             return true;
           }
           break;
         }
       default:
         break;
     }
   } catch (CoreException e) {
     ApiPlugin.log(e);
   }
   return false;
 }
예제 #10
0
 /**
  * Processes the tags for the given {@link IElementDescriptor}
  *
  * @param descriptor the descriptor
  * @param tags the listing of tags from the AST
  * @param type one of <code>CLASS</code> or <code>INTERFACE</code>
  * @param member one of <code>METHOD</code> or <code>FIELD</code> or <code>NONE</code>
  */
 protected void processTags(IElementDescriptor descriptor, List tags, int type, int member) {
   JavadocTagManager jtm = ApiPlugin.getJavadocTagManager();
   TagElement tag = null;
   String tagname = null;
   int restrictions = RestrictionModifiers.NO_RESTRICTIONS;
   for (Iterator iter = tags.iterator(); iter.hasNext(); ) {
     tag = (TagElement) iter.next();
     tagname = tag.getTagName();
     restrictions |= jtm.getRestrictionsForTag(tagname, type, member);
   }
   if (restrictions != RestrictionModifiers.NO_RESTRICTIONS) {
     IElementDescriptor ldesc = descriptor;
     if (ldesc.getElementType() == IElementDescriptor.METHOD) {
       try {
         ldesc = resolveMethod((IMethodDescriptor) ldesc);
       } catch (CoreException e) {
         fException = e;
       }
     }
     fDescription.setRestrictions(ldesc, restrictions);
   }
 }
 /**
  * Computes all of the Javadoc completion proposals
  *
  * @param jcontext
  * @param corecontext
  * @return the complete list of Javadoc completion proposals or an empty list, never <code>null
  *     </code>
  * @since 1.0.500
  */
 List<ICompletionProposal> computeJavadocProposals(
     JavaContentAssistInvocationContext jcontext, CompletionContext corecontext) {
   ICompilationUnit cunit = jcontext.getCompilationUnit();
   if (cunit != null) {
     try {
       int offset = jcontext.getInvocationOffset();
       IJavaElement element = cunit.getElementAt(offset);
       if (!isVisible(element)) {
         return Collections.EMPTY_LIST;
       }
       ImageDescriptor imagedesc =
           jcontext
               .getLabelProvider()
               .createImageDescriptor(
                   org.eclipse.jdt.core.CompletionProposal.create(
                       org.eclipse.jdt.core.CompletionProposal.JAVADOC_BLOCK_TAG, offset));
       fImageHandle = (imagedesc == null ? null : imagedesc.createImage());
       int type = getType(element);
       int member = IApiJavadocTag.MEMBER_NONE;
       switch (element.getElementType()) {
         case IJavaElement.METHOD:
           {
             IMethod method = (IMethod) element;
             member = IApiJavadocTag.MEMBER_METHOD;
             if (method.isConstructor()) {
               member = IApiJavadocTag.MEMBER_CONSTRUCTOR;
             }
             break;
           }
         case IJavaElement.FIELD:
           {
             member = IApiJavadocTag.MEMBER_FIELD;
             break;
           }
         default:
           break;
       }
       IApiJavadocTag[] tags = ApiPlugin.getJavadocTagManager().getTagsForType(type, member);
       int tagcount = tags.length;
       if (tagcount > 0) {
         ArrayList<ICompletionProposal> list = null;
         collectExistingTags(element, jcontext);
         String completiontext = null;
         int tokenstart = corecontext.getTokenStart();
         int length = offset - tokenstart;
         for (int i = 0; i < tagcount; i++) {
           if (!acceptTag(tags[i], element)) {
             continue;
           }
           completiontext = tags[i].getCompleteTag(type, member);
           if (appliesToContext(
               jcontext.getDocument(), completiontext, tokenstart, (length > 0 ? length : 1))) {
             if (list == null) {
               list = new ArrayList<ICompletionProposal>(tagcount - i);
             }
             list.add(
                 new APIToolsJavadocCompletionProposal(
                     corecontext, completiontext, tags[i].getTagName(), fImageHandle));
           }
         }
         if (list != null) {
           return list;
         }
       }
     } catch (JavaModelException e) {
       fErrorMessage = e.getMessage();
     }
   }
   return Collections.EMPTY_LIST;
 }
 /*
  * (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;
 }
/** Tests the {@link ApiBaselineManager} without the framework running */
@SuppressWarnings("unchecked")
public class ApiBaselineManagerTests extends AbstractApiTest {

  static final String THREE = "three";
  static final String TESTDEFAULT = "testdefault";
  static final String ADDTEST = "addtest";

  class SourceChangeVisitor extends ASTVisitor {
    String name = null;
    String signature = null;
    String tagname = null;
    ASTRewrite rewrite = null;
    boolean remove = false;

    public SourceChangeVisitor(
        String name, String signature, String tagname, boolean remove, ASTRewrite rewrite) {
      this.name = name;
      this.signature = signature;
      this.tagname = tagname;
      this.rewrite = rewrite;
      this.remove = remove;
    }
    /* (non-Javadoc)
     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
     */
    public boolean visit(FieldDeclaration node) {
      if (signature != null) {
        return false;
      }
      List<VariableDeclarationFragment> fields = node.fragments();
      VariableDeclarationFragment fragment = null;
      for (Iterator<VariableDeclarationFragment> iter = fields.iterator(); iter.hasNext(); ) {
        fragment = iter.next();
        if (fragment.getName().getFullyQualifiedName().equals(name)) {
          break;
        }
      }
      if (fragment != null) {
        updateTag(node);
      }
      return false;
    }
    /* (non-Javadoc)
     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
     */
    public boolean visit(MethodDeclaration node) {
      if (name.equals(node.getName().getFullyQualifiedName())) {
        if (signature.equals(Signatures.getMethodSignatureFromNode(node))) {
          updateTag(node);
        }
      }
      return false;
    }
    /* (non-Javadoc)
     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclaration)
     */
    public boolean visit(TypeDeclaration node) {
      if (name.equals(node.getName().getFullyQualifiedName())) {
        updateTag(node);
        return false;
      }
      return true;
    }
    /**
     * Updates a javadoc tag, by either adding a new one or removing an existing one
     *
     * @param body
     */
    private void updateTag(BodyDeclaration body) {
      Javadoc docnode = body.getJavadoc();
      AST ast = body.getAST();
      if (docnode == null) {
        docnode = ast.newJavadoc();
        rewrite.set(body, body.getJavadocProperty(), docnode, null);
      }
      ListRewrite lrewrite = rewrite.getListRewrite(docnode, Javadoc.TAGS_PROPERTY);
      if (remove) {
        List<TagElement> tags =
            (List<TagElement>) docnode.getStructuralProperty(Javadoc.TAGS_PROPERTY);
        if (tags != null) {
          TagElement tag = null;
          for (int i = 0; i < tags.size(); i++) {
            tag = tags.get(i);
            if (tagname.equals(tag.getTagName())) {
              lrewrite.remove(tag, null);
            }
          }
        }
      } else {
        TagElement newtag = ast.newTagElement();
        newtag.setTagName(tagname);
        lrewrite.insertLast(newtag, null);
      }
    }
  }

  private IPath SRC_LOC =
      TestSuiteHelper.getPluginDirectoryPath()
          .append("test-source")
          .append("a")
          .append("b")
          .append("c");
  private IPath PLUGIN_LOC = TestSuiteHelper.getPluginDirectoryPath().append("test-plugins");
  private IApiBaselineManager fPMmanager = ApiPlugin.getDefault().getApiBaselineManager();
  private final String TESTING_PACKAGE = "a.b.c";

  /** @return the {@link IApiDescription} for the testing project */
  private IApiDescription getTestProjectApiDescription() throws CoreException {
    IApiBaseline baseline = getWorkspaceBaseline();
    assertNotNull("the workspace baseline must exist", baseline);
    IApiComponent component = baseline.getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
    if (component != null) {
      return component.getApiDescription();
    }
    return null;
  }

  /**
   * Creates and returns a test baseline with the given id. Also adds it to the baseline manager
   *
   * @param id
   * @return
   */
  protected IApiBaseline getTestBaseline(String id) {
    IApiBaseline baseline = ApiModelFactory.newApiBaseline(id);
    fPMmanager.addApiBaseline(baseline);
    return baseline;
  }

  /** Tests trying to get the workspace baseline without the framework running */
  public void testGetWorkspaceComponent() {
    IApiBaseline baseline = getWorkspaceBaseline();
    assertTrue("the workspace baseline must not be null", baseline != null);
  }

  /** Tests that an API baseline can be added and retrieved successfully */
  public void testAddBaseline() {
    IApiBaseline baseline = getTestBaseline(ADDTEST);
    assertTrue("the test baseline must have been created", baseline != null);
    assertTrue(
        "the testadd baseline must be in the manager", fPMmanager.removeApiBaseline(ADDTEST));
  }

  /** Tests that an API baseline can be added/removed successfully */
  public void testRemoveBaseline() {
    IApiBaseline baseline = getTestBaseline("removetest");
    assertTrue("the testremove baseline must exist", baseline != null);
    baseline = fPMmanager.getApiBaseline("removetest");
    assertTrue("the testremove baseline must be in the manager", baseline != null);
    assertTrue(
        "the testremove baseline should have been removed",
        fPMmanager.removeApiBaseline("removetest"));
  }

  /** Tests that the default baseline can be set/retrieved */
  public void testSetDefaultBaseline() {
    try {
      IApiBaseline baseline = getTestBaseline(TESTDEFAULT);
      assertTrue("the testdefault baseline must exist", baseline != null);
      fPMmanager.setDefaultApiBaseline(TESTDEFAULT);
      baseline = fPMmanager.getDefaultApiBaseline();
      assertTrue("the default baseline must be the testdefault baseline", baseline != null);
    } finally {
      fPMmanager.removeApiBaseline(TESTDEFAULT);
    }
  }

  /** Tests that all baselines added to the manager can be retrieved */
  public void testGetAllBaselines() {
    try {
      fPMmanager.addApiBaseline(getTestBaseline(ADDTEST));
      fPMmanager.addApiBaseline(getTestBaseline(TESTDEFAULT));
      fPMmanager.addApiBaseline(getTestBaseline(THREE));
      IApiBaseline[] baselines = fPMmanager.getApiBaselines();
      assertTrue("there should be three baselines", baselines.length == 3);
    } finally {
      fPMmanager.removeApiBaseline(ADDTEST);
      fPMmanager.removeApiBaseline(TESTDEFAULT);
      fPMmanager.removeApiBaseline(THREE);
    }
  }

  /** Tests that all of the baselines have been removed */
  public void testCleanUpMmanager() {
    try {
      fPMmanager.addApiBaseline(getTestBaseline(ADDTEST));
      fPMmanager.addApiBaseline(getTestBaseline(TESTDEFAULT));
      fPMmanager.addApiBaseline(getTestBaseline(THREE));
      IApiBaseline[] baselines = fPMmanager.getApiBaselines();
      assertTrue("there should be three baselines", baselines.length == 3);
      assertTrue(
          "the testadd baseline should have been removed", fPMmanager.removeApiBaseline(ADDTEST));
      assertTrue(
          "the testdefault baseline should have been removed",
          fPMmanager.removeApiBaseline(TESTDEFAULT));
      assertTrue(
          "the three baseline should have been removed", fPMmanager.removeApiBaseline(THREE));
      assertTrue("There sould be no more baselines", fPMmanager.getApiBaselines().length == 0);
    } finally {
      fPMmanager.removeApiBaseline(ADDTEST);
      fPMmanager.removeApiBaseline(TESTDEFAULT);
      fPMmanager.removeApiBaseline(THREE);
    }
  }

  /**
   * Adds the given source to the given package in the given fragment root
   *
   * @param root the root to add the source to
   * @param packagename the name of the package e.g. a.b.c
   * @param sourcename the name of the source file without an extension e.g. TestClass1
   */
  public void assertTestSource(IPackageFragmentRoot root, String packagename, String sourcename)
      throws CoreException, InvocationTargetException, IOException {
    IPackageFragment fragment = root.getPackageFragment(packagename);
    FileUtils.importFileFromDirectory(
        SRC_LOC.append(sourcename + ".java").toFile(),
        fragment.getPath(),
        new NullProgressMonitor());
  }

  /**
   * Adds the package with the given name to the given package fragment root
   *
   * @param the project to add the package to
   * @param srcroot the absolute path to the package fragment root to add the new package to
   * @param packagename the name of the new package
   * @return the new {@link IPackageFragment} or <code>null</code>
   */
  public IPackageFragment assertTestPackage(IJavaProject project, IPath srcroot, String packagename)
      throws JavaModelException {
    IPackageFragment fragment = null;
    IPackageFragmentRoot root = project.findPackageFragmentRoot(srcroot);
    assertNotNull("the 'src' package fragment root must exist", root);
    fragment = root.createPackageFragment(packagename, true, new NullProgressMonitor());
    assertNotNull("the new package '" + packagename + "' should have been created", fragment);
    return fragment;
  }

  /**
   * Adds a test library with the given name to the test projects' class path. The library is
   * imported from the {@link #PLUGIN_LOC} location.
   *
   * @param project the project to add the library classpath entry to
   * @param folderpath the path in the project where the library should be imported to
   * @param libname the name of the library
   */
  public IFolder assertTestLibrary(IJavaProject project, IPath folderpath, String libname)
      throws CoreException, InvocationTargetException, IOException {
    IFolder folder = null;
    // import library
    folder = project.getProject().getFolder(folderpath);
    if (!folder.exists()) {
      folder.create(false, true, null);
    }
    FileUtils.importFileFromDirectory(
        PLUGIN_LOC.append(libname).toFile(), folder.getFullPath(), null);
    IPath libPath = folder.getFullPath().append(libname);

    // add to manifest bundle classpath
    ProjectUtils.addBundleClasspathEntry(
        project.getProject(),
        ProjectUtils.getBundleProjectService()
            .newBundleClasspathEntry(null, null, libPath.removeFirstSegments(1)));
    waitForAutoBuild();
    return folder;
  }

  /**
   * Asserts if the given restriction is on the specified source
   *
   * @param packagename
   * @param sourcename
   */
  public void assertSourceResctriction(String packagename, String sourcename, int restriction)
      throws CoreException {
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.typeDescriptor(packagename + "." + sourcename));
    assertNotNull(
        "the annotations for " + packagename + "." + sourcename + " cannot be null", annot);
    assertTrue(
        "there must be a noinstantiate setting for TestClass1",
        annot.getRestrictions() == restriction);
  }

  /** Tests that closing an API aware project causes the workspace description to be updated */
  public void testWPUpdateProjectClosed() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    assertNotNull("the workspace baseline must not be null", getWorkspaceBaseline());
    IApiComponent component = getWorkspaceBaseline().getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
    assertNotNull(
        "the change project api component must exist in the workspace baseline", component);
    project.getProject().close(new NullProgressMonitor());
    component = getWorkspaceBaseline().getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
    assertNull(
        "the test project api component should no longer exist in the workspace baseline",
        component);
  }

  /** Tests that opening an API aware project causes the workspace description to be updated */
  public void testWPUpdateProjectOpen() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    if (project.getProject().isAccessible()) {
      project.getProject().close(new NullProgressMonitor());
    }
    project.getProject().open(new NullProgressMonitor());
    IApiBaseline baseline = getWorkspaceBaseline();
    assertNotNull("the workspace baseline must not be null", baseline);
    IApiComponent component = baseline.getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
    assertNotNull("the test project api component must exist in the workspace baseline", component);
  }

  /**
   * Tests that adding a source file to an API aware project causes the workspace description to be
   * updated This test adds <code>a.b.c.TestClass1</code> to the plug-in project
   */
  public void testWPUpdateSourceAdded() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName())
                .append(ProjectUtils.SRC_FOLDER)
                .makeAbsolute()
                .makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass1");
    assertSourceResctriction(TESTING_PACKAGE, "TestClass1", RestrictionModifiers.NO_INSTANTIATE);
  }

  /**
   * Tests that removing a source file from an API aware project causes the workspace description to
   * be updated
   */
  public void testWPUpdateSourceRemoved() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass1");
    IJavaElement element = project.findElement(new Path("a/b/c/TestClass1.java"));
    assertNotNull("the class a.b.c.TestClass1 must exist in the project", element);
    element.getResource().delete(true, new NullProgressMonitor());
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass1"));
    assertNull("the annotations for a.b.c.TestClass1 should no longer be present", annot);
  }

  /**
   * Adds the specified tag to the source member defined by the member name and signature
   *
   * @param unit
   * @param membername
   * @param signature
   * @param tagname
   * @param remove
   * @throws CoreException
   * @throws MalformedTreeException
   * @throws BadLocationException
   */
  private void updateTagInSource(
      ICompilationUnit unit, String membername, String signature, String tagname, boolean remove)
      throws CoreException, MalformedTreeException, BadLocationException {
    ASTParser parser = ASTParser.newParser(AST.JLS4);
    parser.setSource(unit);
    CompilationUnit cunit = (CompilationUnit) parser.createAST(new NullProgressMonitor());
    assertNotNull("the ast compilation unit cannot be null", cunit);
    cunit.recordModifications();
    ASTRewrite rewrite = ASTRewrite.create(cunit.getAST());
    cunit.accept(new SourceChangeVisitor(membername, signature, tagname, remove, rewrite));
    ITextFileBufferManager bm = FileBuffers.getTextFileBufferManager();
    IPath path = cunit.getJavaElement().getPath();
    try {
      bm.connect(path, LocationKind.IFILE, null);
      ITextFileBuffer tfb = bm.getTextFileBuffer(path, LocationKind.IFILE);
      IDocument document = tfb.getDocument();
      TextEdit edits = rewrite.rewriteAST(document, null);
      edits.apply(document);
      tfb.commit(new NullProgressMonitor(), true);
    } finally {
      bm.disconnect(path, LocationKind.IFILE, null);
    }
  }

  /**
   * Tests that making Javadoc changes to the source file TestClass2 cause the workspace baseline to
   * be updated.
   *
   * <p>This test adds a @noinstantiate tag to the source file TestClass2
   */
  public void testWPUpdateSourceTypeChanged() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    NullProgressMonitor monitor = new NullProgressMonitor();
    IPackageFragment fragment = root.getPackageFragment("a.b.c");
    FileUtils.importFileFromDirectory(
        SRC_LOC.append("TestClass2.java").toFile(), fragment.getPath(), monitor);
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass2.java"));
    assertNotNull("TestClass2 must exist in the test project", element);
    updateTagInSource(element, "TestClass2", null, "@noinstantiate", false);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass2"));
    assertNotNull("the annotations for a.b.c.TestClass2 cannot be null", annot);
    assertTrue(
        "there must be a noinstantiate setting for TestClass2",
        (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) != 0);
    assertTrue(
        "there must be a noextend setting for TestClass2",
        (annot.getRestrictions() & RestrictionModifiers.NO_EXTEND) != 0);
  }

  /**
   * Tests that tags updated on an inner type are updated in the workspace description.
   *
   * <p>This test adds a @noinstantiate tag to an inner class in TestClass3
   */
  public void testWPUpdateSourceInnerTypeChanged() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass3");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass3.java"));
    assertNotNull("TestClass3 must exist in the test project", element);
    updateTagInSource(element, "InnerTestClass3", null, "@noinstantiate", false);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass3$InnerTestClass3"));
    assertNotNull("the annotations for a.b.c.TestClass3$InnerTestClass3 cannot be null", annot);
    assertTrue(
        "there must be a noinstantiate setting for TestClass3$InnerTestClass3",
        (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) != 0);
    assertTrue(
        "there must be a noextend setting for TestClass3$InnerTestClass3",
        (annot.getRestrictions() & RestrictionModifiers.NO_EXTEND) != 0);
  }

  /**
   * Tests that changing the javadoc for a method updates the workspace baseline
   *
   * <p>This test adds a @noextend tag to the method foo() in TestClass1
   */
  public void testWPUpdateSourceMethodChanged() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass1");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass1.java"));
    assertNotNull("TestClass1 must exist in the test project", element);
    updateTagInSource(element, "foo", "()V", "@nooverride", false);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.methodDescriptor("a.b.c.TestClass1", "foo", "()V"));
    assertNotNull("the annotations for foo() cannot be null", annot);
    assertTrue(
        "there must be a nooverride setting for foo()",
        (annot.getRestrictions() & RestrictionModifiers.NO_OVERRIDE) != 0);
  }

  /**
   * Tests that changing the javadoc for a field updates the workspace baseline
   *
   * <p>This test adds a @noextend tag to the field 'field' in TestField9
   */
  public void testWPUpdateSourceFieldChanged() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestField9");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestField9.java"));
    assertNotNull("TestField9 must exist in the test project", element);
    updateTagInSource(element, "field", null, "@noreference", false);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.fieldDescriptor("a.b.c.TestField9", "field"));
    assertNotNull("the annotations for 'field' cannot be null", annot);
    assertTrue(
        "there must be a noreference setting for 'field'",
        (annot.getRestrictions() & RestrictionModifiers.NO_REFERENCE) != 0);
  }

  /**
   * Tests that removing a tag from a method updates the workspace baseline
   *
   * <p>This test removes a @noextend tag to the method foo() in TestClass1
   */
  public void testWPUpdateSourceMethodRemoveTag() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass1");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass1.java"));
    assertNotNull("TestClass1 must exist in the test project", element);
    updateTagInSource(element, "foo", "()V", "@nooverride", true);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.methodDescriptor("a.b.c.TestClass1", "foo", "()V"));
    assertNotNull("the annotations for foo() cannot be null", annot);
    assertTrue("there must be no restrictions for foo()", annot.getRestrictions() == 0);
  }

  /**
   * Tests that removing a tag from a type updates the workspace baseline
   *
   * <p>This test removes a @noinstantiate tag to an inner class in TestClass3
   */
  public void testWPUpdateSourceTypeRemoveTag() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestClass3");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass3.java"));
    assertNotNull("TestClass3 must exist in the test project", element);
    updateTagInSource(element, "InnerTestClass3", null, "@noextend", true);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass3$InnerTestClass3"));
    assertNotNull("the annotations for 'InnerTestClass3' cannot be null", annot);
    assertTrue(
        "there must be a no restrictions for 'InnerTestClass3'",
        (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) == 0);
  }

  /**
   * Tests that removing a tag from a field updates the workspace baseline
   *
   * <p>This test adds a @noextend tag to the field 'field' in TestField9
   */
  public void testWPUpdateSourceFieldRemoveTag() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IPackageFragmentRoot root =
        project.findPackageFragmentRoot(
            new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
    assertNotNull("the 'src' package fragment root must exist", root);
    assertTestSource(root, TESTING_PACKAGE, "TestField9");
    ICompilationUnit element =
        (ICompilationUnit) project.findElement(new Path("a/b/c/TestField9.java"));
    assertNotNull("TestField9 must exist in the test project", element);
    updateTagInSource(element, "field1", null, "@noreference", true);
    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot =
        desc.resolveAnnotations(Factory.fieldDescriptor("a.b.c.TestField9", "field"));
    assertNotNull("the annotations for 'field' cannot be null", annot);
    assertTrue("there must be a no restrictions for 'field'", annot.getRestrictions() == 0);
  }

  /**
   * Tests that a library added to the build and bundle class path of a project causes the class
   * file containers for the project to need to be recomputed
   *
   * @throws IOException
   * @throws InvocationTargetException
   * @throws CoreException
   */
  public void testWPUpdateLibraryAddedToClasspath() throws Exception {
    IFolder folder = null;
    try {
      IJavaProject project = getTestingProject();
      assertNotNull("The testing project must exist", project);
      IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
      assertNotNull("the workspace component must exist", component);
      int before = component.getApiTypeContainers().length;

      // add to classpath
      folder = assertTestLibrary(project, new Path("libx"), "component.a_1.0.0.jar");
      assertNotNull("The new library path should not be null", folder);

      // re-retrieve updated component
      component = getWorkspaceBaseline().getApiComponent(project.getElementName());
      assertTrue(
          "there must be more containers after the addition",
          before < component.getApiTypeContainers().length);
    } finally {
      if (folder != null) {
        FileUtils.delete(folder);
      }
    }
  }

  /** Tests removing a library from the classpath of a project */
  public void testWPUpdateLibraryRemovedFromClasspath() throws Exception {
    IPath libPath = null;
    try {
      IJavaProject project = getTestingProject();
      assertNotNull("The testing project must exist", project);

      // add to classpath
      IFolder folder = assertTestLibrary(project, new Path("libx"), "component.a_1.0.0.jar");
      IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
      assertNotNull("the workspace component must exist", component);
      int before = component.getApiTypeContainers().length;
      libPath = folder.getFullPath().append("component.a_1.0.0.jar");

      // remove classpath entry
      ProjectUtils.removeFromClasspath(project, JavaCore.newLibraryEntry(libPath, null, null));
      waitForAutoBuild();

      // remove from bundle class path
      IBundleProjectService service = ProjectUtils.getBundleProjectService();
      IBundleProjectDescription description = service.getDescription(project.getProject());
      description.setBundleClasspath(
          new IBundleClasspathEntry[] {
            service.newBundleClasspathEntry(new Path(ProjectUtils.SRC_FOLDER), null, null)
          });
      description.apply(null);
      waitForAutoBuild();

      // retrieve updated component
      component = getWorkspaceBaseline().getApiComponent(project.getElementName());
      assertTrue(
          "there must be less containers after the removal",
          before > component.getApiTypeContainers().length);
    } finally {
      if (libPath != null) {
        FileUtils.delete(libPath.toOSString());
      }
    }
  }

  /**
   * Tests that changing the output folder settings for a project cause the class file containers to
   * be updated
   */
  public void testWPUpdateDefaultOutputFolderChanged() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);
    IContainer container = ProjectUtils.addFolderToProject(project.getProject(), "bin2");
    assertNotNull("the new output folder cannot be null", container);
    IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
    assertNotNull("the workspace component must exist", component);
    int before = component.getApiTypeContainers().length;
    project.setOutputLocation(container.getFullPath(), new NullProgressMonitor());
    waitForAutoBuild();
    assertTrue(
        "there must be the same number of containers after the change",
        before == component.getApiTypeContainers().length);
    assertTrue(
        "the new output location should be 'bin2'",
        "bin2".equalsIgnoreCase(project.getOutputLocation().toFile().getName()));
  }

  /**
   * Tests that the output folder settings for a source folder cause the class file containers to be
   * updated
   */
  public void testWPUpdateOutputFolderSrcFolderChanged() throws Exception {
    IJavaProject project = getTestingProject();
    IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
    assertNotNull("the workspace component must exist", component);
    int before = component.getApiTypeContainers().length;

    ProjectUtils.addFolderToProject(project.getProject(), "bin3");
    IContainer container = ProjectUtils.addFolderToProject(project.getProject(), "src2");
    // add to bundle class path
    IBundleProjectService service = ProjectUtils.getBundleProjectService();
    IBundleClasspathEntry next =
        service.newBundleClasspathEntry(new Path("src2"), new Path("bin3"), new Path("next.jar"));
    ProjectUtils.addBundleClasspathEntry(project.getProject(), next);
    waitForAutoBuild();

    // retrieve updated component
    component = getWorkspaceBaseline().getApiComponent(project.getElementName());
    assertTrue(
        "there must be one more container after the change",
        before < component.getApiTypeContainers().length);
    IPackageFragmentRoot root = project.getPackageFragmentRoot(container);
    assertTrue(
        "the class file container for src2 must be 'bin3'",
        "bin3".equals(root.getRawClasspathEntry().getOutputLocation().toFile().getName()));
  }

  /** Tests that adding a package does not update the workspace baseline */
  public void testWPUpdatePackageAdded() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);

    // add the package
    assertTestPackage(
        project,
        new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(),
        "a.test1.c.d");

    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot = desc.resolveAnnotations(Factory.packageDescriptor("a.test1.c.d"));
    assertNotNull("the annotations for package " + TESTING_PACKAGE + " should exist", annot);
  }

  /**
   * Tests that removing a package updates the workspace baseline This test removes the a.b.c
   * package being used in all tests thus far, and should be run last
   */
  public void testWPUpdatePackageRemoved() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);

    // add the package
    IPath srcroot =
        new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute();
    IPackageFragment fragment = assertTestPackage(project, srcroot, "a.test2");
    assertNotNull("the package " + TESTING_PACKAGE + " must exist", fragment);

    // remove the package
    fragment.delete(true, new NullProgressMonitor());

    IApiDescription desc = getTestProjectApiDescription();
    assertNotNull("the testing project api description must exist", desc);
    IApiAnnotations annot = desc.resolveAnnotations(Factory.packageDescriptor("a.test2"));
    assertNull("the annotations for package " + TESTING_PACKAGE + " should not exist", annot);
  }

  /**
   * Tests that an exported package addition in the PDE model is reflected in the workspace api
   * baseline
   */
  public void testWPUpdateExportPackageAdded() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);

    // add package
    assertTestPackage(
        project,
        new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(),
        "export1");

    // update
    setPackageToApi(project, "export1");
    IApiAnnotations annot =
        getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1"));
    assertNotNull("there must be an annotation for the new exported package", annot);
    assertTrue(
        "the newly exported package must be API visibility",
        annot.getVisibility() == VisibilityModifiers.API);
  }

  /**
   * Tests that changing a directive to x-internal on an exported package causes the workspace api
   * baseline to be updated
   */
  public void testWPUPdateExportPackageDirectiveChangedToInternal() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);

    // add package
    assertTestPackage(
        project,
        new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(),
        "export1");

    // export the package
    ProjectUtils.addExportedPackage(project.getProject(), "export1", true, null);

    // check the description
    IApiAnnotations annot =
        getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1"));
    assertNotNull("there must be an annotation for the new exported package", annot);
    assertTrue(
        "the changed exported package must be PRIVATE visibility",
        annot.getVisibility() == VisibilityModifiers.PRIVATE);
  }

  /**
   * Tests that an exported package removal in the PDE model is reflected in the workspace api
   * baseline
   */
  public void testWPUpdateExportPackageRemoved() throws Exception {
    IJavaProject project = getTestingProject();
    assertNotNull("The testing project must exist", project);

    // add package
    assertTestPackage(
        project,
        new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(),
        "export1");

    setPackageToApi(project, "export1");
    IApiAnnotations annot =
        getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1"));
    assertNotNull("there must be an annotation for the new exported package", annot);
    assertTrue(
        "the newly exported package must be API visibility",
        annot.getVisibility() == VisibilityModifiers.API);

    // remove exported packages
    IBundleProjectService service = ProjectUtils.getBundleProjectService();
    IBundleProjectDescription description = service.getDescription(project.getProject());
    description.setPackageExports(null);
    description.apply(null);

    // check the API description
    annot = getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1"));
    assertNotNull("should still be an annotation for the package", annot);
    assertTrue(
        "unexported package must be private", VisibilityModifiers.isPrivate(annot.getVisibility()));
  }

  /**
   * sets the given package name to be an Exported-Package
   *
   * @param name
   */
  private void setPackageToApi(IJavaProject project, String name) throws CoreException {
    ProjectUtils.addExportedPackage(project.getProject(), name, false, null);
  }

  IJavaProject getTestingProject() {
    return JavaCore.create(
        ResourcesPlugin.getWorkspace().getRoot().getProject(TESTING_PLUGIN_PROJECT_NAME));
  }

  /* (non-Javadoc)
   * @see junit.framework.TestCase#setUp()
   */
  @Override
  protected void setUp() throws Exception {
    createProject(TESTING_PLUGIN_PROJECT_NAME, new String[] {TESTING_PACKAGE});
    setPackageToApi(getTestingProject(), TESTING_PACKAGE);
  }

  /* (non-Javadoc)
   * @see junit.framework.TestCase#tearDown()
   */
  @Override
  protected void tearDown() throws Exception {
    deleteProject(TESTING_PLUGIN_PROJECT_NAME);
    getWorkspaceBaseline().dispose();
  }
}
예제 #14
0
 /**
  * Creates a problem for a specific reference in the workspace
  *
  * @param reference reference
  * @param associated java project (with reference source location)
  * @return problem or <code>null</code> if none
  * @exception CoreException if something goes wrong
  */
 protected IApiProblem createProblem(IReference reference, IJavaProject javaProject) {
   IProject project = javaProject.getProject();
   if (ApiPlugin.getDefault().getSeverityLevel(getSeverityKey(), project)
       == ApiPlugin.SEVERITY_IGNORE) {
     return null;
   }
   try {
     String lookupName = getTypeName(reference.getMember()).replace('$', '.');
     IType type = javaProject.findType(lookupName, new NullProgressMonitor());
     if (type == null) {
       return null;
     }
     ICompilationUnit compilationUnit = type.getCompilationUnit();
     if (compilationUnit == null) {
       return null;
     }
     IResource resource = Util.getResource(project, type);
     if (resource == null) {
       return null;
     }
     int charStart = -1;
     int charEnd = -1;
     int lineNumber = reference.getLineNumber();
     IJavaElement element = compilationUnit;
     if (!Util.isManifest(resource.getProjectRelativePath()) && !type.isBinary()) {
       IDocument document = Util.getDocument(compilationUnit);
       // retrieve line number, char start and char end
       if (lineNumber > 0) {
         lineNumber--;
       }
       // get the source range for the problem
       try {
         Position pos = getSourceRange(type, document, reference);
         if (pos != null) {
           charStart = pos.getOffset();
           if (charStart != -1) {
             charEnd = charStart + pos.getLength();
             lineNumber = document.getLineOfOffset(charStart);
           }
         }
       } catch (CoreException e) {
         ApiPlugin.log(e);
         return null;
       } catch (BadLocationException e) {
         ApiPlugin.log(e);
         return null;
       }
       if (charStart > -1) {
         element = compilationUnit.getElementAt(charStart);
       }
     }
     return ApiProblemFactory.newApiUsageProblem(
         resource.getProjectRelativePath().toPortableString(),
         type.getFullyQualifiedName(),
         getMessageArgs(reference),
         new String[] {
           IApiMarkerConstants.MARKER_ATTR_HANDLE_ID, IApiMarkerConstants.API_MARKER_ATTR_ID
         },
         new Object[] {
           (element == null
               ? compilationUnit.getHandleIdentifier()
               : element.getHandleIdentifier()),
           new Integer(IApiMarkerConstants.API_USAGE_MARKER_ID)
         },
         lineNumber,
         charStart,
         charEnd,
         getElementType(reference),
         getProblemKind(),
         getProblemFlags(reference));
   } catch (CoreException e) {
     ApiPlugin.log(e);
   }
   return null;
 }