/**
  * Collects the existing tags on the {@link IJavaElement} we have been activated on
  *
  * @param element
  * @param jcontext
  * @throws JavaModelException
  * @throws BadLocationException
  */
 private void collectExistingTags(
     IJavaElement element, JavaContentAssistInvocationContext jcontext) throws JavaModelException {
   if (element instanceof IMember) {
     IMember member = (IMember) element;
     ICompilationUnit cunit = jcontext.getCompilationUnit();
     if (cunit != null) {
       if (cunit.isWorkingCopy()) {
         cunit.reconcile(ICompilationUnit.NO_AST, false, false, null, null);
       }
       fParser.setSource(member.getSource().toCharArray());
       fParser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
       Map<String, String> options = element.getJavaProject().getOptions(true);
       options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
       fParser.setCompilerOptions(options);
       fParser.setStatementsRecovery(false);
       fParser.setResolveBindings(false);
       fParser.setBindingsRecovery(false);
       ASTNode ast = fParser.createAST(null);
       TagCollector collector = new TagCollector();
       if (ast.getNodeType() == ASTNode.TYPE_DECLARATION) {
         TypeDeclaration typeDeclaration = (TypeDeclaration) ast;
         List<BodyDeclaration> bodyDeclarations = typeDeclaration.bodyDeclarations();
         if (bodyDeclarations.size() == 1) {
           // only one element should be there as we are parsing a
           // specific member
           BodyDeclaration bodyDeclaration = bodyDeclarations.iterator().next();
           Javadoc javadoc = bodyDeclaration.getJavadoc();
           if (javadoc != null) {
             javadoc.accept(collector);
           }
         }
       }
     }
   }
 }
 /**
  * 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);
   }
 }
  public static void getMissingJavadocTagProposals(
      IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
    ASTNode node = problem.getCoveringNode(context.getASTRoot());
    if (node == null) {
      return;
    }
    node = ASTNodes.getNormalizedNode(node);

    BodyDeclaration bodyDeclaration = ASTResolving.findParentBodyDeclaration(node);
    if (bodyDeclaration == null) {
      return;
    }
    Javadoc javadoc = bodyDeclaration.getJavadoc();
    if (javadoc == null) {
      return;
    }

    String label;
    StructuralPropertyDescriptor location = node.getLocationInParent();
    if (location == SingleVariableDeclaration.NAME_PROPERTY) {
      label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_paramtag_description;
      if (node.getParent().getLocationInParent() != MethodDeclaration.PARAMETERS_PROPERTY) {
        return; // paranoia checks
      }
    } else if (location == TypeParameter.NAME_PROPERTY) {
      label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_paramtag_description;
      StructuralPropertyDescriptor parentLocation = node.getParent().getLocationInParent();
      if (parentLocation != MethodDeclaration.TYPE_PARAMETERS_PROPERTY
          && parentLocation != TypeDeclaration.TYPE_PARAMETERS_PROPERTY) {
        return; // paranoia checks
      }
    } else if (location == MethodDeclaration.RETURN_TYPE2_PROPERTY) {
      label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_returntag_description;
    } else if (location == MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) {
      label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_throwstag_description;
    } else {
      return;
    }
    ASTRewriteCorrectionProposal proposal =
        new AddMissingJavadocTagProposal(
            label,
            context.getCompilationUnit(),
            bodyDeclaration,
            node,
            IProposalRelevance.ADD_MISSING_TAG);
    proposals.add(proposal);

    String label2 = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_allmissing_description;
    ASTRewriteCorrectionProposal addAllMissing =
        new AddAllMissingJavadocTagsProposal(
            label2,
            context.getCompilationUnit(),
            bodyDeclaration,
            IProposalRelevance.ADD_ALL_MISSING_TAGS);
    proposals.add(addAllMissing);
  }
  // Método para configurar os modificadores
  @SuppressWarnings("unchecked")
  private void setModifiers(ApiElement apiElement, BodyDeclaration node) {

    for (Object o : node.modifiers()) {
      if (o instanceof Modifier) {
        Modifier modifier = (Modifier) o;
        if (modifier.isAbstract()) {
          apiElement.setAbstract(true);
        } else if (modifier.isFinal()) {
          apiElement.setFinal(true);
        } else if (modifier.isPrivate()) {
          apiElement.setPrivate(true);
        } else if (modifier.isProtected()) {
          apiElement.setProtected(true);
        } else if (modifier.isPublic()) {
          apiElement.setPublic(true);
        } else if (modifier.isStatic()) {
          apiElement.setFinal(true);
        }
      }
    }

    apiElement.setDefault(
        !(apiElement.isPrivate() || apiElement.isPublic() || apiElement.isProtected()));

    Javadoc javadoc = node.getJavadoc();
    if (javadoc != null) {
      apiElement.setHasJavadoc(true);
      apiElement.setHidden(false);
      Stack<Object> tags = new Stack<Object>();
      tags.addAll(javadoc.tags());
      while (!tags.isEmpty()) {
        Object tag = tags.pop();
        if (tag instanceof TagElement) {
          String tagName = ((TagElement) tag).getTagName();
          if (tagName != null && tagName.equalsIgnoreCase("@hide")) {
            apiElement.setHidden(true);
            break;
          }
          tags.addAll(((TagElement) tag).fragments());
        }
      }
    } else {
      apiElement.setHasJavadoc(false);
      apiElement.setHidden(true);
    }
  }
    private void insertMissingJavadocTag(
        ASTRewrite rewrite, ASTNode missingNode, BodyDeclaration bodyDecl) {
      AST ast = bodyDecl.getAST();
      Javadoc javadoc = bodyDecl.getJavadoc();
      if (javadoc == null) {
        javadoc = ast.newJavadoc();
        rewrite.set(bodyDecl, bodyDecl.getJavadocProperty(), javadoc, null);
      }

      ListRewrite tagsRewriter = rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY);

      StructuralPropertyDescriptor location = missingNode.getLocationInParent();
      TagElement newTag;
      if (location == SingleVariableDeclaration.NAME_PROPERTY) {
        // normal parameter
        SingleVariableDeclaration decl = (SingleVariableDeclaration) missingNode.getParent();

        String name = ((SimpleName) missingNode).getIdentifier();
        newTag = ast.newTagElement();
        newTag.setTagName(TagElement.TAG_PARAM);
        newTag.fragments().add(ast.newSimpleName(name));

        MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDecl;
        List<SingleVariableDeclaration> params = methodDeclaration.parameters();

        Set<String> sameKindLeadingNames = getPreviousParamNames(params, decl);

        List<TypeParameter> typeParams = methodDeclaration.typeParameters();
        for (int i = 0; i < typeParams.size(); i++) {
          String curr = '<' + typeParams.get(i).getName().getIdentifier() + '>';
          sameKindLeadingNames.add(curr);
        }
        insertTag(tagsRewriter, newTag, sameKindLeadingNames);
      } else if (location == TypeParameter.NAME_PROPERTY) {
        // type parameter
        TypeParameter typeParam = (TypeParameter) missingNode.getParent();

        String name = '<' + ((SimpleName) missingNode).getIdentifier() + '>';
        newTag = ast.newTagElement();
        newTag.setTagName(TagElement.TAG_PARAM);
        TextElement text = ast.newTextElement();
        text.setText(name);
        newTag.fragments().add(text);
        List<TypeParameter> params;
        if (bodyDecl instanceof TypeDeclaration) {
          params = ((TypeDeclaration) bodyDecl).typeParameters();
        } else {
          params = ((MethodDeclaration) bodyDecl).typeParameters();
        }
        insertTag(tagsRewriter, newTag, getPreviousTypeParamNames(params, typeParam));
      } else if (location == MethodDeclaration.RETURN_TYPE2_PROPERTY) {
        newTag = ast.newTagElement();
        newTag.setTagName(TagElement.TAG_RETURN);
        insertTag(tagsRewriter, newTag, null);
      } else if (location == MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) {
        newTag = ast.newTagElement();
        newTag.setTagName(TagElement.TAG_THROWS);
        TextElement excNode = ast.newTextElement();
        excNode.setText(ASTNodes.getQualifiedTypeName((Type) missingNode));
        newTag.fragments().add(excNode);
        List<Type> exceptions = ((MethodDeclaration) bodyDecl).thrownExceptionTypes();
        insertTag(tagsRewriter, newTag, getPreviousExceptionNames(exceptions, missingNode));
      } else {
        Assert.isTrue(
            false, "AddMissingJavadocTagProposal: unexpected node location"); // $NON-NLS-1$
        return;
      }

      TextElement textElement = ast.newTextElement();
      textElement.setText(""); // $NON-NLS-1$
      newTag.fragments().add(textElement);

      addLinkedPosition(rewrite.track(textElement), false, "comment_start"); // $NON-NLS-1$

      if (bodyDecl.getJavadoc() == null) {
        // otherwise the linked position spans over a line delimiter
        newTag.fragments().add(ast.newTextElement());
      }
    }