private static void addNewLineToTag(CompositeElement tag, Project project) {
    LOG.assertTrue(tag != null && tag.getElementType() == DOC_TAG);
    ASTNode current = tag.getLastChildNode();
    while (current != null
        && current.getElementType() == DOC_COMMENT_DATA
        && isWhitespaceCommentData(current)) {
      current = current.getTreePrev();
    }
    if (current != null && current.getElementType() == DOC_COMMENT_LEADING_ASTERISKS) return;
    final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(tag);
    final ASTNode newLine =
        Factory.createSingleLeafElement(
            DOC_COMMENT_DATA, "\n", 0, 1, treeCharTab, SharedImplUtil.getManagerByTree(tag));
    tag.addChild(newLine, null);

    ASTNode leadingWhitespaceAnchor = null;
    if (JavaCodeStyleSettingsFacade.getInstance(project).isJavaDocLeadingAsterisksEnabled()) {
      final TreeElement leadingAsterisk =
          Factory.createSingleLeafElement(
              DOC_COMMENT_LEADING_ASTERISKS,
              "*",
              0,
              1,
              treeCharTab,
              SharedImplUtil.getManagerByTree(tag));

      leadingWhitespaceAnchor =
          tag.addInternal(leadingAsterisk, leadingAsterisk, null, Boolean.TRUE);
    }

    final TreeElement commentData =
        Factory.createSingleLeafElement(
            DOC_COMMENT_DATA, " ", 0, 1, treeCharTab, SharedImplUtil.getManagerByTree(tag));
    tag.addInternal(commentData, commentData, leadingWhitespaceAnchor, Boolean.TRUE);
  }
  @Override
  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
    boolean needToAddNewline = false;
    if (first == last && first.getElementType() == DOC_TAG) {
      if (anchor == null) {
        anchor = getLastChildNode(); // this is a '*/'
        final ASTNode prevBeforeWS =
            TreeUtil.skipElementsBack(anchor.getTreePrev(), ElementType.JAVA_WHITESPACE_BIT_SET);
        if (prevBeforeWS != null) {
          anchor = prevBeforeWS;
          before = Boolean.FALSE;
        } else {
          before = Boolean.TRUE;
        }
        needToAddNewline = true;
      }
      if (anchor.getElementType() != DOC_TAG) {
        final CharTable charTable = SharedImplUtil.findCharTableByTree(this);
        final TreeElement newLine =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, "\n", 0, 1, charTable, getManager());
        final TreeElement leadingAsterisk =
            Factory.createSingleLeafElement(
                DOC_COMMENT_LEADING_ASTERISKS, "*", 0, 1, charTable, getManager());
        final TreeElement commentData =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
        final TreeElement indentWS =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
        newLine.getTreeParent().addChild(indentWS);
        newLine.getTreeParent().addChild(leadingAsterisk);
        newLine.getTreeParent().addChild(commentData);
        super.addInternal(newLine, commentData, anchor, Boolean.FALSE);

        anchor = commentData;
        before = Boolean.FALSE;
      } else {
        needToAddNewline = true;
      }
    }
    if (before) anchor.getTreeParent().addChildren(first, last.getTreeNext(), anchor);
    else anchor.getTreeParent().addChildren(first, last.getTreeNext(), anchor.getTreeNext());

    if (needToAddNewline) {
      if (first.getTreePrev() != null && first.getTreePrev().getElementType() == DOC_TAG) {
        addNewLineToTag((CompositeElement) first.getTreePrev(), getProject());
      }
      if (first.getTreeNext() != null && first.getTreeNext().getElementType() == DOC_TAG) {
        addNewLineToTag((CompositeElement) first, getProject());
      } else {
        removeEndingAsterisksFromTag((CompositeElement) first);
      }
    }
    return first;
  }
  @Override
  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
    if (first.getElementType() == NAME_VALUE_PAIR && last.getElementType() == NAME_VALUE_PAIR) {
      final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
      ASTNode lparenth = findChildByRole(ChildRole.LPARENTH);
      if (lparenth == null) {
        LeafElement created =
            Factory.createSingleLeafElement(LPARENTH, "(", 0, 1, treeCharTab, getManager());
        super.addInternal(created, created, getFirstChildNode(), true);
      }
      ASTNode rparenth = findChildByRole(ChildRole.RPARENTH);
      if (rparenth == null) {
        LeafElement created =
            Factory.createSingleLeafElement(RPARENTH, ")", 0, 1, treeCharTab, getManager());
        super.addInternal(created, created, getLastChildNode(), false);
      }

      final ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
      if (nodes.length == 1) {
        final ASTNode node = nodes[0];
        if (node instanceof PsiNameValuePair) {
          final PsiNameValuePair pair = (PsiNameValuePair) node;
          if (pair.getName() == null) {
            final String text = pair.getValue().getText();
            try {
              final PsiAnnotation annotation =
                  JavaPsiFacade.getInstance(getProject())
                      .getElementFactory()
                      .createAnnotationFromText("@AAA(value = " + text + ")", null);
              replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
            } catch (IncorrectOperationException e) {
              LOG.error(e);
            }
          }
        }
      }

      if (anchor == null && before != null) {
        anchor = findChildByRole(before.booleanValue() ? ChildRole.RPARENTH : ChildRole.LPARENTH);
      }
    }

    return super.addInternal(first, last, anchor, before);
  }
  /**
   * There is a possible case that we want to adjust white space which is not represented at the
   * AST/PSI tree, e.g. we might have a multiline comment which uses tabs for inner lines indents
   * and want to replace them by spaces. There is no white space element then, the only leaf is the
   * comment itself.
   *
   * <p>This method allows such 'inner element modifications', i.e. it receives information on what
   * new text should be used at the target inner element range and performs corresponding
   * replacement by generating new leaf with adjusted text and replacing the old one by it.
   *
   * @param newWhiteSpaceText new text to use at the target inner element range
   * @param holder target range holder
   * @param whiteSpaceRange target range which text should be replaced by the given one
   */
  public static void replaceInnerWhiteSpace(
      @NotNull final String newWhiteSpaceText,
      @NotNull final ASTNode holder,
      @NotNull final TextRange whiteSpaceRange) {
    final CharTable charTable = SharedImplUtil.findCharTableByTree(holder);
    StringBuilder newText = createNewLeafChars(holder, whiteSpaceRange, newWhiteSpaceText);
    LeafElement newElement =
        Factory.createSingleLeafElement(
            holder.getElementType(), newText, charTable, holder.getPsi().getManager());

    holder.getTreeParent().replaceChild(holder, newElement);
  }
  @NotNull
  public GrStatement addStatementBefore(@NotNull GrStatement element, @Nullable GrStatement anchor)
      throws IncorrectOperationException {
    if (anchor == null && getRBrace() == null) {
      throw new IncorrectOperationException();
    }

    if (anchor != null && !this.equals(anchor.getParent())) {
      throw new IncorrectOperationException();
    }

    final LeafElement nls =
        Factory.createSingleLeafElement(GroovyTokenTypes.mNLS, "\n", 0, 1, null, getManager());

    PsiElement actualAnchor = anchor == null ? getRBrace() : anchor;
    if (mayUseNewLinesAsSeparators()) {
      PsiElement prev = actualAnchor.getPrevSibling();
      if (prev instanceof GrParameterList
          && prev.getTextLength() == 0
          && prev.getPrevSibling() != null) {
        prev = prev.getPrevSibling();
      }
      if (!PsiUtil.isLineFeed(prev)) {
        addBefore(nls.getPsi(), actualAnchor);
      }
    }
    element = (GrStatement) addBefore(element, actualAnchor);
    if (mayUseNewLinesAsSeparators()) {
      addBefore(nls.getPsi(), actualAnchor);
    } else {
      addBefore(
          Factory.createSingleLeafElement(GroovyTokenTypes.mNLS, "\n", 0, 1, null, getManager())
              .getPsi(),
          actualAnchor);
    }
    return element;
  }
示例#6
0
    public PomModelEvent runInner() {
      final String value = ((XmlAttribute) myChild).getValue();
      final String name = ((XmlAttribute) myChild).getName();
      if (myAnchor == null) {
        ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(XmlTagImpl.this);
        if (startTagEnd == null)
          startTagEnd = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(XmlTagImpl.this);

        if (startTagEnd == null) {
          ASTNode anchor = getLastChildNode();

          while (anchor instanceof PsiWhiteSpace) {
            anchor = anchor.getTreePrev();
          }

          if (anchor instanceof PsiErrorElement) {
            final LeafElement token =
                Factory.createSingleLeafElement(
                    XmlTokenType.XML_EMPTY_ELEMENT_END,
                    "/>",
                    0,
                    2,
                    SharedImplUtil.findCharTableByTree(anchor),
                    getManager());
            replaceChild(anchor, token);
            startTagEnd = token;
          }
        }

        if (startTagEnd == null) {
          ASTNode anchor = XmlChildRole.START_TAG_NAME_FINDER.findChild(XmlTagImpl.this);
          myFirstInserted = XmlTagImpl.super.addInternal(myChild, myChild, anchor, Boolean.FALSE);
        } else {
          myFirstInserted =
              XmlTagImpl.super.addInternal(myChild, myChild, startTagEnd, Boolean.TRUE);
        }
      } else {
        myFirstInserted =
            XmlTagImpl.super.addInternal(myChild, myChild, myAnchor, Boolean.valueOf(myBefore));
      }
      return XmlAttributeSetImpl.createXmlAttributeSet(myModel, XmlTagImpl.this, name, value);
    }
 private static void generateRaw(final @NotNull XmlTag newTag) {
   XmlElementDescriptor selected = newTag.getDescriptor();
   if (selected == null) return;
   switch (selected.getContentType()) {
     case XmlElementDescriptor.CONTENT_TYPE_EMPTY:
       newTag.collapseIfEmpty();
       ASTNode node = newTag.getNode();
       assert node != null;
       ASTNode elementEnd = node.findChildByType(XmlTokenType.XML_EMPTY_ELEMENT_END);
       if (elementEnd == null) {
         LeafElement emptyTagEnd =
             Factory.createSingleLeafElement(
                 XmlTokenType.XML_EMPTY_ELEMENT_END, "/>", 0, 2, null, newTag.getManager());
         node.addChild(emptyTagEnd);
       }
       break;
     case XmlElementDescriptor.CONTENT_TYPE_MIXED:
       newTag.getValue().setText("");
   }
   for (XmlAttributeDescriptor descriptor : selected.getAttributesDescriptors(newTag)) {
     if (descriptor.isRequired()) {
       newTag.setAttribute(descriptor.getName(), "");
     }
   }
   List<XmlElementDescriptor> tags = getRequiredSubTags(selected);
   for (XmlElementDescriptor descriptor : tags) {
     if (descriptor == null) {
       XmlTag tag =
           XmlElementFactory.getInstance(newTag.getProject())
               .createTagFromText("<", newTag.getLanguage());
       newTag.addSubTag(tag, false);
     } else {
       XmlTag subTag = newTag.addSubTag(createTag(newTag, descriptor), false);
       generateRaw(subTag);
     }
   }
 }
  public static void replaceWhiteSpace(
      final String whiteSpace,
      final ASTNode leafElement,
      final IElementType whiteSpaceToken,
      @Nullable final TextRange textRange) {
    final CharTable charTable = SharedImplUtil.findCharTableByTree(leafElement);

    ASTNode treePrev = findPreviousWhiteSpace(leafElement, whiteSpaceToken);
    if (treePrev == null) {
      treePrev = getWsCandidate(leafElement);
    }

    if (treePrev != null
        && treePrev.getText().trim().isEmpty()
        && treePrev.getElementType() != whiteSpaceToken
        && treePrev.getTextLength() > 0
        && !whiteSpace.isEmpty()) {
      LeafElement whiteSpaceElement =
          Factory.createSingleLeafElement(
              treePrev.getElementType(),
              whiteSpace,
              charTable,
              SharedImplUtil.getManagerByTree(leafElement));

      ASTNode treeParent = treePrev.getTreeParent();
      treeParent.replaceChild(treePrev, whiteSpaceElement);
    } else {
      LeafElement whiteSpaceElement =
          Factory.createSingleLeafElement(
              whiteSpaceToken, whiteSpace, charTable, SharedImplUtil.getManagerByTree(leafElement));

      if (treePrev == null) {
        if (!whiteSpace.isEmpty()) {
          addWhiteSpace(leafElement, whiteSpaceElement);
        }
      } else {
        if (!(treePrev.getElementType() == whiteSpaceToken)) {
          if (!whiteSpace.isEmpty()) {
            addWhiteSpace(treePrev, whiteSpaceElement);
          }
        } else {
          if (treePrev.getElementType() == whiteSpaceToken) {
            final CompositeElement treeParent = (CompositeElement) treePrev.getTreeParent();
            if (!whiteSpace.isEmpty()) {
              //          LOG.assertTrue(textRange == null ||
              // treeParent.getTextRange().equals(textRange));
              treeParent.replaceChild(treePrev, whiteSpaceElement);
            } else {
              treeParent.removeChild(treePrev);
            }

            // There is a possible case that more than one PSI element is matched by the target text
            // range.
            // That is the case, for example, for Python's multi-line expression. It may looks like
            // below:
            //     import contextlib,\
            //       math, decimal
            // Here single range contains two blocks: '\' & '\n  '. So, we may want to replace that
            // range to another text, hence,
            // we replace last element located there with it ('\n  ') and want to remove any
            // remaining elements ('\').
            ASTNode removeCandidate = findPreviousWhiteSpace(whiteSpaceElement, whiteSpaceToken);
            while (textRange != null
                && removeCandidate != null
                && removeCandidate.getStartOffset() >= textRange.getStartOffset()) {
              treePrev = findPreviousWhiteSpace(removeCandidate, whiteSpaceToken);
              removeCandidate.getTreeParent().removeChild(removeCandidate);
              removeCandidate = treePrev;
            }
            // treeParent.subtreeChanged();
          }
        }
      }
    }
  }
  private static void processMethodUsage(
      PsiElement element,
      JavaChangeInfo changeInfo,
      boolean toChangeArguments,
      boolean toCatchExceptions,
      GrClosureSignatureUtil.ArgInfo<PsiElement>[] map,
      PsiSubstitutor substitutor) {
    if (map == null) return;
    if (changeInfo.isNameChanged()) {
      if (element instanceof GrReferenceElement) {
        element = ((GrReferenceElement) element).handleElementRename(changeInfo.getNewName());
      }
    }
    if (toChangeArguments) {
      JavaParameterInfo[] parameters = changeInfo.getNewParameters();
      GrArgumentList argumentList = PsiUtil.getArgumentsList(element);
      GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject());
      if (argumentList == null) {
        if (element instanceof GrEnumConstant) {
          argumentList = factory.createArgumentList();
          argumentList = (GrArgumentList) element.add(argumentList);
        } else {
          return;
        }
      }
      Set<PsiElement> argsToDelete = new HashSet<PsiElement>(map.length * 2);
      for (GrClosureSignatureUtil.ArgInfo<PsiElement> argInfo : map) {
        argsToDelete.addAll(argInfo.args);
      }

      for (JavaParameterInfo parameter : parameters) {
        int index = parameter.getOldIndex();
        if (index >= 0) {
          argsToDelete.removeAll(map[index].args);
        }
      }

      for (PsiElement arg : argsToDelete) {
        arg.delete();
      }

      boolean skipOptionals = false;
      PsiElement anchor = null; // PsiTreeUtil.getChildOfAnyType(argumentList, GrExpression.class,
      // GrNamedArgument.class);
      for (int i = 0; i < parameters.length; i++) {
        JavaParameterInfo parameter = parameters[i];
        int index = parameter.getOldIndex();
        if (index >= 0) {
          GrClosureSignatureUtil.ArgInfo<PsiElement> argInfo = map[index];
          List<PsiElement> arguments = argInfo.args;
          if (argInfo.isMultiArg) { // arguments for Map and varArg
            if ((i != 0
                    || !(!arguments.isEmpty()
                        && arguments.iterator().next() instanceof GrNamedArgument))
                && (i != parameters.length - 1 || !parameter.isVarargType())) {
              final PsiType type =
                  parameter.createType(
                      changeInfo.getMethod().getParameterList(), argumentList.getManager());
              final GrExpression arg =
                  GroovyRefactoringUtil.generateArgFromMultiArg(
                      substitutor, arguments, type, element.getProject());
              for (PsiElement argument : arguments) {
                argument.delete();
              }
              anchor = argumentList.addAfter(arg, anchor);
              JavaCodeStyleManager.getInstance(anchor.getProject()).shortenClassReferences(anchor);
            }
          } else { // arguments for simple parameters
            if (arguments.size() == 1) { // arg exists
              PsiElement arg = arguments.iterator().next();
              if (i == parameters.length - 1 && parameter.isVarargType()) {
                if (arg instanceof GrSafeCastExpression) {
                  PsiElement expr = ((GrSafeCastExpression) arg).getOperand();
                  if (expr instanceof GrListOrMap && !((GrListOrMap) expr).isMap()) {
                    final PsiElement copy = expr.copy();
                    PsiElement[] newVarargs = ((GrListOrMap) copy).getInitializers();
                    for (PsiElement vararg : newVarargs) {
                      anchor = argumentList.addAfter(vararg, anchor);
                    }
                    arg.delete();
                    continue;
                  }
                }
              }

              PsiElement curArg = getNextOfType(argumentList, anchor, GrExpression.class);
              if (curArg == arg) {
                anchor = arg;
              } else {
                final PsiElement copy = arg.copy();
                anchor = argumentList.addAfter(copy, anchor);
                arg.delete();
              }
            } else { // arg is skipped. Parameter is optional
              skipOptionals = true;
            }
          }
        } else {
          if (skipOptionals && isParameterOptional(parameter)) continue;

          if (forceOptional(parameter)) {
            skipOptionals = true;
            continue;
          }
          try {

            GrExpression value = createDefaultValue(factory, changeInfo, parameter, argumentList);
            if (i > 0 && (value == null || anchor == null)) {
              PsiElement comma =
                  Factory.createSingleLeafElement(
                          GroovyTokenTypes.mCOMMA,
                          ",",
                          0,
                          1,
                          SharedImplUtil.findCharTableByTree(argumentList.getNode()),
                          argumentList.getManager())
                      .getPsi();
              if (anchor == null) anchor = argumentList.getLeftParen();

              anchor = argumentList.addAfter(comma, anchor);
            }
            if (value != null) {
              anchor = argumentList.addAfter(value, anchor);
            }
          } catch (IncorrectOperationException e) {
            LOG.error(e.getMessage());
          }
        }
      }

      GrCall call = GroovyRefactoringUtil.getCallExpressionByMethodReference(element);
      if (argumentList.getText().trim().isEmpty()
          && (call == null || !PsiImplUtil.hasClosureArguments(call))) {
        argumentList = argumentList.replaceWithArgumentList(factory.createArgumentList());
      }
      CodeStyleManager.getInstance(argumentList.getProject()).reformat(argumentList);
    }

    if (toCatchExceptions) {
      final ThrownExceptionInfo[] exceptionInfos = changeInfo.getNewExceptions();
      PsiClassType[] exceptions = getExceptions(exceptionInfos, element, element.getManager());
      fixExceptions(element, exceptions);
    }
  }