private static void addFoldingDescriptors(
      final List<FoldingDescriptor> descriptors, final PsiElement tag, @NotNull Document document) {

    TextRange elementRange = tag.getTextRange();
    final int start = elementRange.getStartOffset();
    final int end = elementRange.getEndOffset();

    if (start + 1 < end) {
      TextRange range = null;
      ASTNode astNode = tag.getNode();
      IElementType astType = astNode.getElementType();

      if (tag instanceof CfmlTag) {
        // if (tag instanceof CfmlTagFunctionImpl || tag instanceof CfmlTagComponentImpl || tag
        // instanceof CfmlTagScriptImpl) {
        range =
            buildRangeForBraces(
                range, astNode, CfmlTokenTypes.R_ANGLEBRACKET, CfmlTokenTypes.LSLASH_ANGLEBRACKET);
        // }
      } else if (astType == CfmlElementTypes.FUNCTIONBODY
          || astType == CfmlElementTypes.BLOCK_OF_STATEMENTS) {
        range = buildRange(range, start, end);
      } else if (astType == CfmlElementTypes.SWITCHEXPRESSION) {
        ASTNode lparen = astNode.findChildByType(CfscriptTokenTypes.L_CURLYBRACKET);
        ASTNode rparen = astNode.findChildByType(CfscriptTokenTypes.R_CURLYBRACKET);
        if (lparen != null && rparen != null) {
          range = buildRange(range, lparen.getStartOffset(), rparen.getTextRange().getEndOffset());
        }
      } else if (tag instanceof PsiComment) {
        boolean isColdFusionComment = astNode.getElementType() == CfmlTokenTypes.COMMENT;
        int endIndex = astNode.getText().lastIndexOf(isColdFusionComment ? "--->" : "*/");
        if (endIndex != -1) {
          String commentText = astNode.getText().substring(0, endIndex);
          if (commentText.contains("\n")) {
            int startOffset = tag.getTextRange().getStartOffset();
            range =
                buildRange(
                    range,
                    startOffset + (isColdFusionComment ? "<!---" : "/*").length(),
                    startOffset + commentText.length());
          }
        }
      }

      if (range != null) {
        descriptors.add(new FoldingDescriptor(astNode, range));
      }

      // TODO: insert condition
      addFoldingDescriptorsFromChildren(descriptors, tag, document);
    }
  }
 @Override
 public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
   final Pair<PsiElement, TextRange> data =
       node.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
   if (data != null) {
     final PsiElement parent = data.getFirst();
     final String text = parent.getText();
     final Pair<String, String> detectedQuotes = PythonStringUtil.getQuotes(text);
     final Pair<String, String> quotes =
         detectedQuotes != null ? detectedQuotes : Pair.create("'", "'");
     final TextRange range = data.getSecond();
     final String substring = range.substring(text);
     myResult.append(quotes.getFirst() + substring + quotes.getSecond());
   } else {
     ASTNode child = node.getNode().getFirstChildNode();
     while (child != null) {
       String text = child.getText();
       if (child.getElementType() == TokenType.WHITE_SPACE) {
         if (text.contains("\n")) {
           if (!text.contains("\\")) {
             myResult.append("\\");
           }
           myResult.append(text);
         }
       } else {
         myResult.append(text);
       }
       child = child.getTreeNext();
     }
   }
 }
 private static void reportInconsistentLength(
     PsiFile file, CharSequence newFileText, ASTNode node, int start, int end) {
   String message =
       "Index out of bounds: type="
           + node.getElementType()
           + "; file="
           + file
           + "; file.class="
           + file.getClass()
           + "; start="
           + start
           + "; end="
           + end
           + "; length="
           + node.getTextLength();
   String newTextBefore = newFileText.subSequence(0, start).toString();
   String oldTextBefore = file.getText().subSequence(0, start).toString();
   if (oldTextBefore.equals(newTextBefore)) {
     message += "; oldTextBefore==newTextBefore";
   }
   LOG.error(
       message,
       new Attachment(file.getName() + "_oldNodeText.txt", node.getText()),
       new Attachment(file.getName() + "_oldFileText.txt", file.getText()),
       new Attachment(file.getName() + "_newFileText.txt", newFileText.toString()));
 }
示例#4
0
  @NotNull
  public PsiReference[] getReferences() {
    ProgressManager.checkCanceled();
    final ASTNode startTagName = XmlChildRole.START_TAG_NAME_FINDER.findChild(this);
    if (startTagName == null) return PsiReference.EMPTY_ARRAY;
    final ASTNode endTagName = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(this);
    List<PsiReference> refs = new ArrayList<PsiReference>();
    String prefix = getNamespacePrefix();

    TagNameReference startTagRef =
        TagNameReference.createTagNameReference(this, startTagName, true);
    refs.add(startTagRef);
    if (prefix.length() > 0) {
      refs.add(createPrefixReference(startTagName, prefix, startTagRef));
    }
    if (endTagName != null) {
      TagNameReference endTagRef = TagNameReference.createTagNameReference(this, endTagName, false);
      refs.add(endTagRef);
      prefix = XmlUtil.findPrefixByQualifiedName(endTagName.getText());
      if (StringUtil.isNotEmpty(prefix)) {
        refs.add(createPrefixReference(endTagName, prefix, endTagRef));
      }
    }

    // ArrayList.addAll() makes a clone of the collection
    //noinspection ManualArrayToCollectionCopy
    for (PsiReference ref :
        ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlTag.class)) {
      refs.add(ref);
    }

    return ContainerUtil.toArray(refs, new PsiReference[refs.size()]);
  }
 public static String getName(X816SymbolAffectation element) {
   ASTNode symbol = element.getNode().findChildByType(X816Types.SYMBOL);
   if (symbol != null) {
     return symbol.getText();
   }
   return null;
 }
 @Nullable
 public String getActualStepPrefix() {
   ASTNode keyword = getKeyword();
   if (keyword == null) { // that's weird!
     return null;
   }
   return keyword.getText();
 }
  @Override
  protected String replaceWithPsiInLeaf(
      final TextRange textRange, String whiteSpace, ASTNode leafElement) {
    if (!myCanModifyAllWhiteSpaces) {
      if (leafElement.getElementType() == TokenType.WHITE_SPACE) return null;
      LOG.assertTrue(leafElement.getPsi().isValid());
      ASTNode prevNode = TreeUtil.prevLeaf(leafElement);

      if (prevNode != null) {
        IElementType type = prevNode.getElementType();
        if (type == TokenType.WHITE_SPACE) {
          final String text = prevNode.getText();

          final @NonNls String cdataStartMarker = "<![CDATA[";
          final int cdataPos = text.indexOf(cdataStartMarker);
          if (cdataPos != -1 && whiteSpace.indexOf(cdataStartMarker) == -1) {
            whiteSpace = mergeWsWithCdataMarker(whiteSpace, text, cdataPos);
            if (whiteSpace == null) return null;
          }

          prevNode = TreeUtil.prevLeaf(prevNode);
          type = prevNode != null ? prevNode.getElementType() : null;
        }

        final @NonNls String cdataEndMarker = "]]>";
        if (type == XmlTokenType.XML_CDATA_END && whiteSpace.indexOf(cdataEndMarker) == -1) {
          final ASTNode at = findElementAt(prevNode.getStartOffset());

          if (at != null && at.getPsi() instanceof PsiWhiteSpace) {
            final String s = at.getText();
            final int cdataEndPos = s.indexOf(cdataEndMarker);
            whiteSpace = mergeWsWithCdataMarker(whiteSpace, s, cdataEndPos);
            leafElement = at;
          } else {
            whiteSpace = null;
          }
          if (whiteSpace == null) return null;
        }
      }
    }
    FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, TokenType.WHITE_SPACE, textRange);
    return whiteSpace;
  }
  @Override
  public String getIncludeText() {
    final JSIncludeDirectiveStub stub = getStub();
    if (stub != null) {
      return stub.getIncludeText();
    }
    final ASTNode astNode = getIncludedFileNode();

    return astNode != null ? StringUtil.stripQuotesAroundValue(astNode.getText()) : null;
  }
  @Nullable
  @Override
  public String getName() {
    final PyFunctionStub stub = getStub();
    if (stub != null) {
      return stub.getName();
    }

    ASTNode node = getNameNode();
    return node != null ? node.getText() : null;
  }
 public boolean isOperator(String chars) {
   ASTNode child = getNode().getFirstChildNode();
   StringBuilder buf = new StringBuilder();
   while (child != null) {
     IElementType elType = child.getElementType();
     if (elType instanceof PyElementType && PyElementTypes.BINARY_OPS.contains(elType)) {
       buf.append(child.getText());
     }
     child = child.getTreeNext();
   }
   return buf.toString().equals(chars);
 }
示例#11
0
 @NotNull
 public String getName() {
   String name = myName;
   if (name == null) {
     final ASTNode nameElement = XmlChildRole.START_TAG_NAME_FINDER.findChild(this);
     if (nameElement != null) {
       name = nameElement.getText();
     } else {
       name = "";
     }
     myName = name;
   }
   return name;
 }
 private static HashSet<String> findAllVariables(
     ASTNode[] children, HashSet<String> resultSet, IElementType type, boolean limitResults) {
   int amount =
       (false)
           ? Math.min(AUTO_POPUP_VARS_ITEMS_LIMIT, children.length)
           : children.length; // get all results only if users press ctrl+space
   for (int i = 0; i < amount; i++) {
     ASTNode astNode = children[i].findChildByType(type);
     if (astNode != null) {
       resultSet.add(astNode.getText());
     } else if (children[i].getChildren(null) != null) {
       findAllVariables(children[i].getChildren(null), resultSet, type, false);
     }
   }
   return resultSet;
 }
  @Override
  @NotNull
  public PsiReference[] getReferences() {
    ASTNode node = getIncludedFileNode();

    if (node != null) {
      return new FileReferenceSet(
              StringUtil.stripQuotesAroundValue(node.getText()),
              this,
              node.getPsi().getStartOffsetInParent() + 1,
              null,
              SystemInfo.isFileSystemCaseSensitive)
          .getAllReferences();
    }
    return PsiReference.EMPTY_ARRAY;
  }
    protected void applyFix(
        final Project project,
        final PsiElement psiElement,
        final PsiFile file,
        final Editor editor) {
      final ASTNode oldValueNode = ((JSAttributeNameValuePair) psiElement).getValueNode();
      final String oldText = oldValueNode.getText();
      char quoteChar = oldText.length() > 0 ? oldText.charAt(0) : '"';
      if (quoteChar != '\'' && quoteChar != '"') {
        quoteChar = '"';
      }

      final String newText =
          quoteChar + "/" + StringUtil.stripQuotesAroundValue(oldText) + quoteChar;
      final ASTNode newNode = JSChangeUtil.createExpressionFromText(project, newText);
      psiElement.getNode().replaceChild(oldValueNode, newNode.getFirstChildNode());
    }
 private void postponeFormatting(final FileViewProvider viewProvider, final ASTNode child) {
   if (!CodeEditUtil.isNodeGenerated(child) && child.getElementType() != TokenType.WHITE_SPACE) {
     final int oldIndent = CodeEditUtil.getOldIndentation(child);
     LOG.assertTrue(
         oldIndent >= 0,
         "for not generated items old indentation must be defined: element="
             + child
             + ", text="
             + child.getText());
   }
   List<ASTNode> list = myReformatElements.get(viewProvider);
   if (list == null) {
     list = new ArrayList<ASTNode>();
     myReformatElements.put(viewProvider, list);
   }
   list.add(child);
 }
 private void postponeFormatting(@NotNull FileViewProvider viewProvider, @NotNull ASTNode child) {
   if (!CodeEditUtil.isNodeGenerated(child) && child.getElementType() != TokenType.WHITE_SPACE) {
     final int oldIndent = CodeEditUtil.getOldIndentation(child);
     LOG.assertTrue(
         oldIndent >= 0,
         "for not generated items old indentation must be defined: element="
             + child
             + ", text="
             + child.getText());
   }
   List<ASTNode> list = myReformatElements.get(viewProvider);
   if (list == null) {
     list = new ArrayList<ASTNode>();
     myReformatElements.put(viewProvider, list);
     if (STORE_REFORMAT_ORIGINATOR_STACKTRACE) {
       viewProvider.putUserData(REFORMAT_ORIGINATOR, new Throwable());
     }
   }
   list.add(child);
 }
  private static StringBuilder createNewLeafChars(
      final ASTNode leafElement, final TextRange textRange, final String whiteSpace) {
    final TextRange elementRange = leafElement.getTextRange();
    final String elementText = leafElement.getText();

    final StringBuilder result = new StringBuilder();

    if (elementRange.getStartOffset() < textRange.getStartOffset()) {
      result.append(
          elementText.substring(0, textRange.getStartOffset() - elementRange.getStartOffset()));
    }

    result.append(whiteSpace);

    if (elementRange.getEndOffset() > textRange.getEndOffset()) {
      result.append(
          elementText.substring(textRange.getEndOffset() - elementRange.getStartOffset()));
    }

    return result;
  }
示例#18
0
  @Override
  protected List<Block> buildChildren() {
    final ArrayList<Block> result = new ArrayList<Block>();

    ASTNode child = getNode().getFirstChildNode();
    while (child != null) {
      IElementType childType = child.getElementType();
      if (childType != TokenType.WHITE_SPACE
          && !FormatterUtil.containsWhiteSpacesOnly(child)
          && !child.getText().trim().isEmpty()) {
        result.add(
            createBlock(
                child,
                calcIndent(child),
                null,
                AlignmentStrategy.getNullStrategy(),
                settings,
                spacingBuilder));
      }

      child = child.getTreeNext();
    }
    return result;
  }
 /**
  * @param node Tree node
  * @return true, if the current node can be myBlock node, else otherwise
  */
 private static boolean canBeCorrectBlock(final ASTNode node) {
   return (node.getText().trim().length() > 0);
 }
示例#20
0
  public Result beforeCharTyped(
      final char c,
      final Project project,
      final Editor editor,
      final PsiFile editedFile,
      final FileType fileType) {
    final XmlEditorOptions xmlEditorOptions = XmlEditorOptions.getInstance();
    if (c == '>'
        && xmlEditorOptions != null
        && xmlEditorOptions.isAutomaticallyInsertClosingTag()
        && (editedFile.getLanguage() instanceof XMLLanguage
            || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage)) {
      PsiDocumentManager.getInstance(project).commitAllDocuments();

      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
      FileViewProvider provider = editedFile.getViewProvider();
      int offset = editor.getCaretModel().getOffset();

      PsiElement element, elementAtCaret = null;

      if (offset < editor.getDocument().getTextLength()) {
        elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);

        if (!(element instanceof PsiWhiteSpace)) {
          boolean nonAcceptableDelimiter = true;

          if (element instanceof XmlToken) {
            IElementType tokenType = ((XmlToken) element).getTokenType();

            if (tokenType == XmlTokenType.XML_START_TAG_START
                || tokenType == XmlTokenType.XML_END_TAG_START) {
              if (offset > 0) {
                PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);

                if (previousElement instanceof XmlToken) {
                  tokenType = ((XmlToken) previousElement).getTokenType();
                  element = previousElement;
                  nonAcceptableDelimiter = false;
                }
              }
            } else if (tokenType == XmlTokenType.XML_NAME) {
              if (element.getNextSibling() instanceof PsiErrorElement) {
                nonAcceptableDelimiter = false;
              }
            }

            if (tokenType == XmlTokenType.XML_TAG_END
                || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END
                    && element.getTextOffset() == offset - 1) {
              editor.getCaretModel().moveToOffset(offset + 1);
              editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
              return Result.STOP;
            }
          }
          if (nonAcceptableDelimiter) return Result.CONTINUE;
        } else {
          // check if right after empty end
          PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
          if (previousElement instanceof XmlToken) {
            final IElementType tokenType = ((XmlToken) previousElement).getTokenType();

            if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
              return Result.STOP;
            }
          }
        }

        PsiElement parent = element.getParent();
        if (parent instanceof XmlText) {
          final String text = parent.getText();
          // check /
          final int index = offset - parent.getTextOffset() - 1;

          if (index >= 0 && text.charAt(index) == '/') {
            return Result.CONTINUE; // already seen /
          }
          element = parent.getPrevSibling();
        } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag)) {
          element = parent;
        } else if (parent instanceof XmlAttributeValue) {
          element = parent;
        }
      } else {
        element =
            provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
        if (element == null) return Result.CONTINUE;
        element = element.getParent();
      }

      if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
        if (editor.getDocument().getCharsSequence().charAt(offset - 1)
            == '/') { // Some languages (e.g. GSP) allow character '/' in tag name.
          return Result.CONTINUE;
        }
      }

      if (element instanceof XmlAttributeValue) {
        element = element.getParent().getParent();
      }

      while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();
      if (element instanceof XmlDocument) { // hack for closing tags in RHTML
        element = element.getLastChild();
      }
      if (element == null) return Result.CONTINUE;
      if (!(element instanceof XmlTag)) {
        if (element instanceof XmlTokenImpl
            && element.getPrevSibling() != null
            && element.getPrevSibling().getText().equals("<")) {
          // tag is started and there is another text in the end
          editor.getDocument().insertString(offset, "</" + element.getText() + ">");
        }
        return Result.CONTINUE;
      }

      XmlTag tag = (XmlTag) element;
      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null) return Result.CONTINUE;
      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
        return Result.CONTINUE;
      final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
      if (startToken == null || !startToken.getText().equals("<")) return Result.CONTINUE;

      String name = tag.getName();
      if (elementAtCaret instanceof XmlToken
          && ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME) {
        name = name.substring(0, offset - elementAtCaret.getTextOffset());
      }
      if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name)) return Result.CONTINUE;
      if ("".equals(name)) return Result.CONTINUE;

      int tagOffset = tag.getTextRange().getStartOffset();

      final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
      if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset)
        return Result.CONTINUE;

      HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
      if (BraceMatchingUtil.matchBrace(
          editor.getDocument().getCharsSequence(),
          editedFile.getFileType(),
          iterator,
          true,
          true)) {
        PsiElement parent = tag.getParent();
        boolean hasBalance = true;

        while (parent instanceof XmlTag && name.equals(((XmlTag) parent).getName())) {
          ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
          if (astNode == null) {
            hasBalance = false;
            break;
          }

          parent = parent.getParent();
        }

        if (hasBalance) {
          hasBalance = false;
          for (ASTNode node = parent.getNode().getLastChildNode();
              node != null;
              node = node.getTreePrev()) {
            ASTNode leaf = node;
            if (leaf.getElementType() == TokenType.ERROR_ELEMENT) {
              ASTNode firstChild = leaf.getFirstChildNode();
              if (firstChild != null) leaf = firstChild;
              else {
                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
                leaf = psiElement != null ? psiElement.getNode() : null;
              }
              if (leaf != null && leaf.getElementType() == TokenType.WHITE_SPACE) {
                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
                if (psiElement != null) leaf = psiElement.getNode();
              }
            }

            if (leaf != null && leaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
              ASTNode treeNext = leaf.getTreeNext();
              IElementType treeNextType;
              if (treeNext != null
                  && ((treeNextType = treeNext.getElementType()) == XmlTokenType.XML_NAME
                      || treeNextType == XmlTokenType.XML_TAG_NAME)) {
                if (name.equals(treeNext.getText())) {
                  ASTNode parentEndName =
                      parent instanceof XmlTag
                          ? XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode())
                          : null;
                  hasBalance =
                      !(parent instanceof XmlTag)
                          || parentEndName != null && !parentEndName.getText().equals(name);
                  break;
                }
              }
            }
          }
        }

        if (hasBalance) return Result.CONTINUE;
      }

      TextRange cdataReformatRange = null;
      final XmlElementDescriptor descriptor = tag.getDescriptor();

      if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
        final XmlElementDescriptorWithCDataContent cDataContainer =
            (XmlElementDescriptorWithCDataContent) descriptor;

        if (cDataContainer.requiresCdataBracesInContext(tag)) {
          int rangeStart = offset;
          @NonNls final String cDataStart = "><![CDATA[";
          final String inserted = cDataStart + "\n]]>";
          editor.getDocument().insertString(offset, inserted);
          final int newoffset = offset + cDataStart.length();
          editor.getCaretModel().moveToOffset(newoffset);
          offset += inserted.length();
          cdataReformatRange = new TextRange(rangeStart, offset + 1);
        }
      }

      editor.getDocument().insertString(offset, "</" + name + ">");

      if (cdataReformatRange != null) {
        PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
        try {
          CodeStyleManager.getInstance(project)
              .reformatText(
                  file, cdataReformatRange.getStartOffset(), cdataReformatRange.getEndOffset());
        } catch (IncorrectOperationException e) {
          LOG.error(e);
        }
      }
      return cdataReformatRange != null ? Result.STOP : Result.CONTINUE;
    }
    return Result.CONTINUE;
  }
 private static boolean isWhitespaceCommentData(ASTNode docCommentData) {
   return WS_PATTERN.matcher(docCommentData.getText()).matches();
 }
  public static Spacing getSpacing(
      GroovyBlock child1, GroovyBlock child2, CommonCodeStyleSettings settings) {

    ASTNode leftNode = child1.getNode();
    ASTNode rightNode = child2.getNode();
    final PsiElement left = leftNode.getPsi();
    final PsiElement right = rightNode.getPsi();

    IElementType leftType = leftNode.getElementType();
    IElementType rightType = rightNode.getElementType();

    // Braces Placement
    // For multi-line strings
    if (!mirrorsAst(child1) || !mirrorsAst(child2)) {
      return NO_SPACING;
    }

    if (leftType == mGDOC_COMMENT_START && rightType == mGDOC_COMMENT_DATA
        || leftType == mGDOC_COMMENT_DATA && rightType == mGDOC_COMMENT_END) {
      return LAZY_SPACING;
    }

    // For type parameters
    if (mLT == leftType && rightNode.getPsi() instanceof GrTypeParameter
        || mGT == rightType && leftNode.getPsi() instanceof GrTypeParameter
        || mIDENT == leftType && rightNode.getPsi() instanceof GrTypeParameterList) {
      return NO_SPACING;
    }

    // For left parentheses in method declarations or calls
    if (mLPAREN.equals(rightType)
        && rightNode.getPsi().getParent().getNode() != null
        && METHOD_DEFS.contains(rightNode.getPsi().getParent().getNode().getElementType())) {
      return NO_SPACING;
    }

    if (ARGUMENTS.equals(rightType)) {
      return NO_SPACING;
    }
    // For left square bracket in array declarations and selections by index
    if ((mLBRACK.equals(rightType)
            && rightNode.getPsi().getParent().getNode() != null
            && INDEX_OR_ARRAY.contains(rightNode.getPsi().getParent().getNode().getElementType()))
        || ARRAY_DECLARATOR.equals(rightType)) {
      return NO_SPACING;
    }

    if (METHOD_DEFS.contains(leftType)) {
      if (rightType == mSEMI) {
        return NO_SPACING;
      }
      return Spacing.createSpacing(
          0, 0, settings.BLANK_LINES_AROUND_METHOD + 1, settings.KEEP_LINE_BREAKS, 100);
    }

    if (METHOD_DEFS.contains(rightType)) {
      if (leftNode.getElementType() == GROOVY_DOC_COMMENT) {
        return Spacing.createSpacing(
            0, 0, settings.BLANK_LINES_AROUND_METHOD, settings.KEEP_LINE_BREAKS, 0);
      }
      return Spacing.createSpacing(
          0, 0, settings.BLANK_LINES_AROUND_METHOD + 1, settings.KEEP_LINE_BREAKS, 100);
    }

    if (leftType == mLCURLY && rightType == PARAMETERS_LIST) { // closure
      return LAZY_SPACING;
    }

    // For parentheses in arguments and typecasts
    if (LEFT_BRACES.contains(leftType) || RIGHT_BRACES.contains(rightType)) {
      PsiElement parent = (LEFT_BRACES.contains(leftType) ? left : right).getParent();
      boolean shouldHaveSpace =
          parent instanceof GrTypeCastExpression && settings.SPACE_WITHIN_CAST_PARENTHESES;
      return shouldHaveSpace ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }
    // For type parameters
    if ((mLT.equals(leftType) || mGT.equals(rightType))
        && leftNode.getPsi().getParent() != null
        && leftNode.getPsi().getParent() instanceof GrTypeArgumentList) {
      return NO_SPACING_WITH_NEWLINE;
    }

    if (rightNode.getPsi() != null && rightNode.getPsi() instanceof GrTypeArgumentList) {
      return NO_SPACING_WITH_NEWLINE;
    }

    if (rightType == mCOLON
        && left instanceof GrParameter
        && left.getParent() instanceof GrForInClause) {
      return COMMON_SPACING;
    }

    /** ******** punctuation marks *********** */
    // For dots, commas etc.
    if ((PUNCTUATION_SIGNS.contains(rightType))
        || (mCOLON.equals(rightType)
            && !(rightNode.getPsi().getParent() instanceof GrConditionalExpression))) {
      return NO_SPACING_WITH_NEWLINE;
    }

    if (DOTS.contains(leftType)) {
      return NO_SPACING_WITH_NEWLINE;
    }

    /** ******** imports *********** */
    if (IMPORT_STATEMENT.equals(leftType) && IMPORT_STATEMENT.equals(rightType)) {
      return IMPORT_BETWEEN_SPACING;
    }
    if ((IMPORT_STATEMENT.equals(leftType)
            && (!IMPORT_STATEMENT.equals(rightType) && !mSEMI.equals(rightType)))
        || ((!IMPORT_STATEMENT.equals(leftType) && !mSEMI.equals(leftType))
            && IMPORT_STATEMENT.equals(rightType))) {
      return IMPORT_OTHER_SPACING;
    }

    // todo:check it for multiple assignments
    if ((VARIABLE_DEFINITION.equals(leftType) || VARIABLE_DEFINITION.equals(rightType))
        && !(leftNode.getTreeNext() instanceof PsiErrorElement)) {
      return Spacing.createSpacing(0, 0, 1, false, 100);
    }

    /** ******** exclusions *********** */
    // For << and >> ...
    if ((mLT.equals(leftType) && mLT.equals(rightType))
        || (mGT.equals(leftType) && mGT.equals(rightType))) {
      return NO_SPACING_WITH_NEWLINE;
    }

    // Unary and postfix expressions
    if (PREFIXES.contains(leftType)
        || POSTFIXES.contains(rightType)
        || (PREFIXES_OPTIONAL.contains(leftType)
            && leftNode.getPsi().getParent() instanceof GrUnaryExpression)) {
      return NO_SPACING_WITH_NEWLINE;
    }

    if (RANGES.contains(leftType) || RANGES.contains(rightType)) {
      return NO_SPACING_WITH_NEWLINE;
    }

    // For Gstrings and regexes
    if (left.getParent() != null
        && left.getParent().equals(right.getParent())
        && (left.getParent() instanceof GrString
            || leftNode.getTreeParent().getElementType() == mREGEX_LITERAL
            || leftNode.getTreeParent().getElementType() == mDOLLAR_SLASH_REGEX_LITERAL)) {
      return NO_SPACING;
    }
    if (isDollarInGStringInjection(leftNode) || isDollarInGStringInjection(rightNode)) {
      return NO_SPACING;
    }
    if (leftNode.getPsi().getParent() instanceof GrStringInjection
        && rightNode.getPsi().getParent() instanceof GrString
        && rightNode.getPsi().getParent().equals(leftNode.getPsi().getParent().getParent())) {
      return NO_SPACING;
    }

    if (mGDOC_ASTERISKS == leftType && mGDOC_COMMENT_DATA == rightType) {
      String text = rightNode.getText();
      if (text.length() > 0 && !text.startsWith(" ")) {
        return COMMON_SPACING;
      }
      return NO_SPACING;
    }

    if (leftType == mGDOC_TAG_VALUE_TOKEN && rightType == mGDOC_COMMENT_DATA) {
      return LAZY_SPACING;
    }

    if (left instanceof GrStatement
        && right instanceof GrStatement
        && left.getParent() instanceof GrStatementOwner
        && right.getParent() instanceof GrStatementOwner) {
      return COMMON_SPACING_WITH_NL;
    }

    if (rightType == mGDOC_INLINE_TAG_END
        || leftType == mGDOC_INLINE_TAG_START
        || rightType == mGDOC_INLINE_TAG_START
        || leftType == mGDOC_INLINE_TAG_END) {
      return NO_SPACING;
    }

    if ((leftType == GDOC_INLINED_TAG && rightType == mGDOC_COMMENT_DATA)
        || (leftType == mGDOC_COMMENT_DATA && rightType == GDOC_INLINED_TAG)) {
      // Keep formatting between groovy doc text and groovy doc reference tag as is.
      return NO_SPACING;
    }

    if (leftType == CLASS_TYPE_ELEMENT && rightType == mTRIPLE_DOT) {
      return NO_SPACING;
    }

    // diamonds
    if (rightType == mLT || rightType == mGT) {
      if (right.getParent() instanceof GrCodeReferenceElement) {
        PsiElement p = right.getParent().getParent();
        if (p instanceof GrNewExpression || p instanceof GrAnonymousClassDefinition) {
          return NO_SPACING;
        }
      }
    }

    if (leftType == mRPAREN && left.getParent() instanceof GrTypeCastExpression) {
      return settings.SPACE_AFTER_TYPE_CAST ? COMMON_SPACING : NO_SPACING;
    }

    return COMMON_SPACING;
  }
 public String getDeclName() {
   ASTNode node = getNode().findChildByType(PLSqlTypesAdopted.TYPE_NAME);
   return node.getText();
 }
  @Override
  public PsiReference getReference() {
    final PsiDocComment comment = PsiTreeUtil.getParentOfType(this, PsiDocComment.class);
    if (comment == null) return null;
    final PsiDocCommentOwner owner = comment.getOwner();
    if (!(owner instanceof PsiMethod) && !(owner instanceof PsiClass)) return null;
    final ASTNode valueToken = findChildByType(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
    if (valueToken == null) return null;
    final String name = valueToken.getText();
    PsiElement reference = null;
    final PsiElement firstChild = getFirstChild();
    if (firstChild instanceof PsiDocToken
        && ((PsiDocToken) firstChild).getTokenType().equals(JavaDocTokenType.DOC_TAG_VALUE_LT)) {
      final PsiTypeParameter[] typeParameters =
          ((PsiTypeParameterListOwner) owner).getTypeParameters();
      for (PsiTypeParameter typeParameter : typeParameters) {
        if (typeParameter.getName().equals(name)) {
          reference = typeParameter;
        }
      }
    } else if (owner instanceof PsiMethod) {
      final PsiParameter[] parameters = ((PsiMethod) owner).getParameterList().getParameters();
      for (PsiParameter parameter : parameters) {
        if (parameter.getName().equals(name)) {
          reference = parameter;
        }
      }
    }

    final PsiElement resultReference = reference;
    return new PsiJavaReference() {
      @Override
      public PsiElement resolve() {
        return resultReference;
      }

      @Override
      @NotNull
      public String getCanonicalText() {
        return valueToken.getText();
      }

      @Override
      public PsiElement handleElementRename(String newElementName) {
        final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(getNode());
        LeafElement newElement =
            Factory.createSingleLeafElement(
                JavaDocTokenType.DOC_TAG_VALUE_TOKEN,
                newElementName,
                charTableByTree,
                getManager());
        replaceChild(valueToken, newElement);
        return PsiDocParamRef.this;
      }

      @Override
      public PsiElement bindToElement(@NotNull PsiElement element)
          throws IncorrectOperationException {
        if (isReferenceTo(element)) return PsiDocParamRef.this;
        if (!(element instanceof PsiParameter)) {
          throw new IncorrectOperationException("Unsupported operation");
        }
        return handleElementRename(((PsiParameter) element).getName());
      }

      @Override
      public boolean isReferenceTo(PsiElement element) {
        if (!(element instanceof PsiNamedElement)) return false;
        PsiNamedElement namedElement = (PsiNamedElement) element;
        if (!getCanonicalText().equals(namedElement.getName())) return false;
        return getManager().areElementsEquivalent(resolve(), element);
      }

      @Override
      @NotNull
      public PsiElement[] getVariants() {
        final PsiElement firstChild = getFirstChild();

        Set<String> usedNames = new HashSet<String>();
        for (PsiDocTag tag : comment.getTags()) {
          if (tag.getName().equals("param")) {
            PsiDocTagValue valueElement = tag.getValueElement();
            if (valueElement != null) {
              usedNames.add(valueElement.getText());
            }
          }
        }

        PsiNamedElement[] result = PsiNamedElement.EMPTY_ARRAY;
        if (firstChild instanceof PsiDocToken
            && ((PsiDocToken) firstChild)
                .getTokenType()
                .equals(JavaDocTokenType.DOC_TAG_VALUE_LT)) {
          result = ((PsiTypeParameterListOwner) owner).getTypeParameters();
        } else if (owner instanceof PsiMethod) {
          result = ((PsiMethod) owner).getParameterList().getParameters();
        }
        List<PsiElement> filtered = new ArrayList<PsiElement>();
        for (PsiNamedElement namedElement : result) {
          if (!usedNames.contains(namedElement.getName())) {
            filtered.add(namedElement);
          }
        }
        return filtered.toArray(new PsiElement[filtered.size()]);
      }

      @Override
      public boolean isSoft() {
        return false;
      }

      @Override
      public TextRange getRangeInElement() {
        final int startOffsetInParent = valueToken.getPsi().getStartOffsetInParent();
        return new TextRange(startOffsetInParent, startOffsetInParent + valueToken.getTextLength());
      }

      @Override
      public PsiElement getElement() {
        return PsiDocParamRef.this;
      }

      @Override
      public void processVariants(PsiScopeProcessor processor) {
        for (final PsiElement element : getVariants()) {
          if (!processor.execute(element, ResolveState.initial())) {
            return;
          }
        }
      }

      @Override
      @NotNull
      public JavaResolveResult advancedResolve(boolean incompleteCode) {
        return resultReference == null
            ? JavaResolveResult.EMPTY
            : new CandidateInfo(resultReference, PsiSubstitutor.EMPTY);
      }

      @Override
      @NotNull
      public JavaResolveResult[] multiResolve(boolean incompleteCode) {
        return resultReference == null
            ? JavaResolveResult.EMPTY_ARRAY
            : new JavaResolveResult[] {new CandidateInfo(resultReference, PsiSubstitutor.EMPTY)};
      }
    };
  }
  public Indent getChildIndent(final ASTNode node) {
    final IElementType elementType = node.getElementType();
    final ASTNode prevSibling = UsefulPsiTreeUtil.getPrevSiblingSkipWhiteSpacesAndComments(node);
    final IElementType prevSiblingType = prevSibling == null ? null : prevSibling.getElementType();
    final ASTNode parent = node.getTreeParent();
    final IElementType parentType = parent != null ? parent.getElementType() : null;
    final ASTNode superParent = parent == null ? null : parent.getTreeParent();
    final IElementType superParentType = superParent == null ? null : superParent.getElementType();

    final int braceStyle =
        superParentType == FUNCTION_BODY ? settings.METHOD_BRACE_STYLE : settings.BRACE_STYLE;

    if (parent == null || parent.getTreeParent() == null || parentType == EMBEDDED_CONTENT) {
      return Indent.getNoneIndent();
    }

    if (elementType == MULTI_LINE_COMMENT_BODY) {
      return Indent.getContinuationIndent();
    }
    if (elementType == DOC_COMMENT_LEADING_ASTERISK || elementType == MULTI_LINE_COMMENT_END) {
      return Indent.getSpaceIndent(1, true);
    }

    if (settings.KEEP_FIRST_COLUMN_COMMENT
        && (elementType == SINGLE_LINE_COMMENT || elementType == MULTI_LINE_COMMENT)) {
      final ASTNode previousNode = node.getTreePrev();
      if (previousNode != null
          && previousNode.getElementType() == WHITE_SPACE
          && previousNode.getText().endsWith("\n")) {
        return Indent.getAbsoluteNoneIndent();
      }
    }

    if (COMMENTS.contains(elementType) && prevSiblingType == LBRACE && parentType == CLASS_BODY) {
      return Indent.getNormalIndent();
    }

    if (parentType == ENUM_DEFINITION && isBetweenBraces(node)) {
      // instead of isBetweenBraces(node) we can parse enum block as a separate ASTNode, or build
      // formatter blocks not tied to AST.
      return Indent.getNormalIndent();
    }

    if (parentType == MAP_LITERAL_EXPRESSION || parentType == LIST_LITERAL_EXPRESSION) {
      if (elementType == LBRACE
          || elementType == RBRACE
          || elementType == LBRACKET
          || elementType == RBRACKET) {
        return Indent.getNoneIndent();
      }
      if (elementType == TYPE_ARGUMENTS) {
        return Indent.getNoneIndent();
      }
      // Be careful to preserve typing behavior.
      if (elementType == MAP_LITERAL_ENTRY
          || elementType == EXPRESSION_LIST
          || elementType == COMMA) {
        return Indent.getNormalIndent();
      }
      if (COMMENTS.contains(elementType)) {
        return Indent.getNormalIndent();
      }
      return Indent.getNoneIndent();
    }

    if (elementType == LBRACE || elementType == RBRACE) {
      switch (braceStyle) {
        case CommonCodeStyleSettings.END_OF_LINE:
          if (elementType == LBRACE
              && FormatterUtil.isPrecededBy(parent, SINGLE_LINE_COMMENT, WHITE_SPACE)) {
            // Use Nystrom style rather than Allman.
            return Indent.getContinuationIndent();
          } // FALL THROUGH
        case CommonCodeStyleSettings.NEXT_LINE:
        case CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED:
          return Indent.getNoneIndent();
        case CommonCodeStyleSettings.NEXT_LINE_SHIFTED:
        case CommonCodeStyleSettings.NEXT_LINE_SHIFTED2:
          return Indent.getNormalIndent();
        default:
          return Indent.getNoneIndent();
      }
    }

    if (parentType == PARENTHESIZED_EXPRESSION) {
      if (elementType == LPAREN || elementType == RPAREN) {
        return Indent.getNoneIndent();
      }
      return Indent.getContinuationIndent();
    }

    if (elementType == CLASS_MEMBERS) {
      return Indent.getNormalIndent();
    }
    if (parentType == BLOCK) {
      final PsiElement psi = node.getPsi();
      if (psi.getParent() instanceof PsiFile) {
        return Indent.getNoneIndent();
      }
      return Indent.getNormalIndent();
    }
    if (parentType == ARGUMENT_LIST) {
      // TODO In order to handle some dart_style examples we need to set indent for each arg.
      // The formatter does not appear to honor indent on individual argument expressions
      // when KEEP_LINE_BREAKS==true. That means two DartFormatterTest tests fail. Those tests
      // have been changed since the recommended setting for Dart programming is
      // KEEP_LINE_BREAKS==false. The two tests are testAlignment() and testWrappingMeth().
      if (EXPRESSIONS.contains(elementType) && elementType != FUNCTION_EXPRESSION) {
        return Indent.getContinuationIndent();
      }
    }
    if (parentType == FORMAL_PARAMETER_LIST) {
      return Indent.getContinuationIndent();
    }
    if (parentType == FOR_STATEMENT
        && prevSiblingType == FOR_LOOP_PARTS_IN_BRACES
        && elementType != BLOCK) {
      return Indent.getNormalIndent();
    }
    if (parentType == SWITCH_STATEMENT
        && (elementType == SWITCH_CASE || elementType == DEFAULT_CASE)) {
      return Indent.getNormalIndent();
    }
    if ((parentType == SWITCH_CASE || parentType == DEFAULT_CASE) && elementType == STATEMENTS) {
      return Indent.getNormalIndent();
    }
    if (parentType == WHILE_STATEMENT && prevSiblingType == RPAREN && elementType != BLOCK) {
      return Indent.getNormalIndent();
    }
    if (parentType == DO_WHILE_STATEMENT && prevSiblingType == DO && elementType != BLOCK) {
      return Indent.getNormalIndent();
    }
    if ((parentType == RETURN_STATEMENT) && prevSiblingType == RETURN && elementType != BLOCK) {
      return Indent.getNormalIndent();
    }
    if (parentType == IF_STATEMENT
        && elementType != BLOCK
        && (prevSiblingType == RPAREN
            || (prevSiblingType == ELSE && elementType != IF_STATEMENT))) {
      return Indent.getNormalIndent();
    }
    if (elementType == CASCADE_REFERENCE_EXPRESSION) {
      return Indent.getNormalIndent();
    }
    if (elementType == OPEN_QUOTE
        && prevSiblingType == CLOSING_QUOTE
        && parentType == STRING_LITERAL_EXPRESSION) {
      return Indent.getContinuationIndent();
    }
    if (BINARY_EXPRESSIONS.contains(parentType) && prevSibling != null) {
      return Indent.getContinuationIndent();
    }
    if (elementType == COLON || parentType == TERNARY_EXPRESSION && elementType == QUEST) {
      return Indent.getContinuationIndent();
    }
    if (elementType == NAMED_ARGUMENT) {
      return Indent.getContinuationIndent();
    }
    if (elementType == HIDE_COMBINATOR || elementType == SHOW_COMBINATOR) {
      return Indent.getContinuationIndent();
    }
    if (parentType == FUNCTION_BODY) {
      if (FormatterUtil.isPrecededBy(node, EXPRESSION_BODY_DEF)) {
        return Indent.getContinuationIndent();
      }
    }
    if (elementType == CALL_EXPRESSION) {
      if (FormatterUtil.isPrecededBy(node, EXPRESSION_BODY_DEF)) {
        return Indent.getContinuationIndent();
      }
      if (FormatterUtil.isPrecededBy(node, ASSIGNMENT_OPERATOR)) {
        return Indent.getContinuationIndent();
      }
    }
    if ((elementType == REFERENCE_EXPRESSION || BINARY_EXPRESSIONS.contains(elementType))
        && FormatterUtil.isPrecededBy(node, ASSIGNMENT_OPERATOR)) {
      return Indent.getContinuationIndent();
    }
    if (elementType == VAR_DECLARATION_LIST_PART) {
      return Indent.getContinuationIndent();
    }

    if (elementType == SUPER_CALL_OR_FIELD_INITIALIZER) {
      return Indent.getContinuationIndent();
    }
    if (parentType == SUPER_CALL_OR_FIELD_INITIALIZER && elementType != COLON) {
      return Indent.getNormalIndent();
    }

    if (parentType == CLASS_DEFINITION) {
      if (elementType == SUPERCLASS || elementType == INTERFACES || elementType == MIXINS) {
        return Indent.getContinuationIndent();
      }
    }
    if (parentType == MIXIN_APPLICATION && elementType == MIXINS) {
      return Indent.getContinuationIndent();
    }

    if (parentType == LIBRARY_NAME_ELEMENT) {
      return Indent.getContinuationIndent();
    }

    if (elementType == SEMICOLON
        && FormatterUtil.isPrecededBy(node, SINGLE_LINE_COMMENT, WHITE_SPACE)) {
      return Indent.getContinuationIndent();
    }

    if (elementType == DOT || elementType == QUEST_DOT) {
      return Indent.getContinuationIndent();
    }

    if (parentType == TYPE_LIST && elementType == TYPE) {
      return Indent.getContinuationIndent();
    }

    if (elementType == OPEN_QUOTE
        && parentType == STRING_LITERAL_EXPRESSION
        && superParentType == VAR_INIT) {
      if (node.getText().length() < 3) {
        return Indent.getContinuationIndent();
      }
    }

    if (elementType == RAW_SINGLE_QUOTED_STRING
        && parentType == STRING_LITERAL_EXPRESSION
        && superParentType == VAR_INIT) {
      return Indent.getContinuationIndent();
    }

    if (parentType == LONG_TEMPLATE_ENTRY && EXPRESSIONS.contains(elementType)) {
      return Indent.getContinuationIndent();
    }
    return Indent.getNoneIndent();
  }
  public List<Block> generateSubBlocks() {

    // For binary expressions
    PsiElement blockPsi = myNode.getPsi();

    if (blockPsi instanceof GrBinaryExpression
        && !(blockPsi.getParent() instanceof GrBinaryExpression)) {
      return generateForBinaryExpr();
    }

    // For multiline strings
    if ((myNode.getElementType() == mSTRING_LITERAL || myNode.getElementType() == mGSTRING_LITERAL)
        && myBlock.getTextRange().equals(myNode.getTextRange())) {
      String text = myNode.getText();
      if (text.length() > 6) {
        if (text.substring(0, 3).equals("'''") && text.substring(text.length() - 3).equals("'''")
            || text.substring(0, 3).equals("\"\"\"")
                & text.substring(text.length() - 3).equals("\"\"\"")) {
          return generateForMultiLineString();
        }
      }
    }

    if (myNode.getElementType() == mGSTRING_BEGIN
        && myBlock.getTextRange().equals(myNode.getTextRange())) {
      String text = myNode.getText();
      if (text.length() > 3) {
        if (text.substring(0, 3).equals("\"\"\"")) {
          return generateForMultiLineGStringBegin();
        }
      }
    }

    // for gstrings
    if (myNode.getElementType() == GSTRING) {
      final ArrayList<Block> subBlocks = new ArrayList<Block>();
      ASTNode[] children = getGroovyChildren(myNode);
      for (ASTNode childNode : children) {
        if (childNode.getTextRange().getLength() > 0) {
          final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
          subBlocks.add(
              new GroovyBlock(
                  childNode,
                  myAlignment,
                  indent,
                  myWrap,
                  mySettings,
                  myGroovySettings,
                  myInnerAlignments));
        }
      }
      return subBlocks;
    }

    // chained properties, calls, indexing, etc
    if (NESTED.contains(myNode.getElementType())
        && blockPsi.getParent() != null
        && !NESTED.contains(blockPsi.getParent().getNode().getElementType())) {
      final List<Block> subBlocks = new ArrayList<Block>();
      Alignment dotsAlignment =
          mySettings.ALIGN_MULTILINE_CHAINED_METHODS ? Alignment.createAlignment() : null;
      addNestedChildren(myNode.getPsi(), subBlocks, dotsAlignment, true);
      return subBlocks;
    }

    // For Parameter lists
    if (isListLikeClause(blockPsi)) {
      final ArrayList<Block> subBlocks = new ArrayList<Block>();
      List<ASTNode> astNodes = visibleChildren(myNode);
      final Alignment newAlignment =
          mustAlign(blockPsi, astNodes) ? Alignment.createAlignment() : null;
      for (ASTNode childNode : astNodes) {
        final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
        subBlocks.add(
            new GroovyBlock(
                childNode,
                isKeyword(childNode) ? null : newAlignment,
                indent,
                myWrap,
                mySettings,
                myGroovySettings,
                myInnerAlignments));
      }
      return subBlocks;
    }

    boolean classLevel = blockPsi instanceof GrTypeDefinitionBody;
    if (blockPsi instanceof GrCodeBlock || blockPsi instanceof GroovyFile || classLevel) {
      List<ASTNode> children = visibleChildren(myNode);
      calculateAlignments(children, classLevel);
      final ArrayList<Block> subBlocks = new ArrayList<Block>();
      for (ASTNode childNode : children) {
        final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
        Alignment alignmentToUse =
            classLevel ? myAlignment : myInnerAlignments.get(childNode.getPsi());
        subBlocks.add(
            new GroovyBlock(
                childNode,
                alignmentToUse,
                indent,
                myWrap,
                mySettings,
                myGroovySettings,
                myInnerAlignments));
      }
      return subBlocks;
    }

    // For other cases
    final ArrayList<Block> subBlocks = new ArrayList<Block>();
    for (ASTNode childNode : visibleChildren(myNode)) {
      final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
      subBlocks.add(
          new GroovyBlock(
              childNode,
              myInnerAlignments.get(childNode.getPsi()),
              indent,
              myWrap,
              mySettings,
              myGroovySettings,
              myInnerAlignments));
    }
    return subBlocks;
  }
 @Nullable
 public String getReferencedName() {
   final ASTNode nameElement = getNameElement();
   return nameElement != null ? nameElement.getText() : null;
 }
  @NotNull
  @Override
  public Runnable processFile(final PsiFile file) {
    VirtualFile vFile = file.getVirtualFile();
    if (vFile instanceof VirtualFileWindow) vFile = ((VirtualFileWindow) vFile).getDelegate();
    final Project project = file.getProject();
    if (vFile == null
        || !ProjectRootManager.getInstance(project).getFileIndex().isInSourceContent(vFile)) {
      return EmptyRunnable.INSTANCE;
    }
    final List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>();
    final Set<String> demandedForNested = new HashSet<>();
    collectNamesToImport(names, demandedForNested, (XmlFile) file);
    Collections.sort(names, (o1, o2) -> StringUtil.compare(o1.first, o2.first, true));
    final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project);
    final List<Pair<String, Boolean>> sortedNames =
        ImportHelper.sortItemsAccordingToSettings(names, settings);
    final HashSet<String> onDemand = new HashSet<String>();
    ImportHelper.collectOnDemandImports(sortedNames, onDemand, settings);
    onDemand.addAll(demandedForNested);
    final Set<String> imported = new HashSet<String>();
    final List<String> imports = new ArrayList<String>();
    for (Pair<String, Boolean> pair : sortedNames) {
      final String qName = pair.first;
      final String packageName = StringUtil.getPackageName(qName);
      if (imported.contains(packageName) || imported.contains(qName)) {
        continue;
      }
      if (onDemand.contains(packageName)) {
        imported.add(packageName);
        imports.add("<?import " + packageName + ".*?>");
      } else {
        imported.add(qName);
        imports.add("<?import " + qName + "?>");
      }
    }
    final PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject());

    final XmlFile dummyFile =
        (XmlFile)
            factory.createFileFromText(
                "_Dummy_.fxml", StdFileTypes.XML, StringUtil.join(imports, "\n"));
    final XmlDocument document = dummyFile.getDocument();
    final XmlProlog newImportList = document != null ? document.getProlog() : null;
    if (newImportList == null) return EmptyRunnable.getInstance();
    return () -> {
      final XmlDocument xmlDocument = ((XmlFile) file).getDocument();
      final XmlProlog prolog = xmlDocument != null ? xmlDocument.getProlog() : null;
      if (prolog != null) {
        final Collection<XmlProcessingInstruction> instructions =
            PsiTreeUtil.findChildrenOfType(prolog, XmlProcessingInstruction.class);
        for (final XmlProcessingInstruction instruction : instructions) {
          final ASTNode node = instruction.getNode();
          final ASTNode nameNode = node.findChildByType(XmlTokenType.XML_NAME);
          if (nameNode != null && nameNode.getText().equals("import")) {
            instruction.delete();
          }
        }
        prolog.add(newImportList);
      } else {
        document.addBefore(newImportList, document.getRootTag());
      }
    };
  }
  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();
          }
        }
      }
    }
  }
  public List<Block> generateSubBlocks() {

    // For binary expressions
    PsiElement blockPsi = myNode.getPsi();

    if (blockPsi instanceof GrBinaryExpression
        && !(blockPsi.getParent() instanceof GrBinaryExpression)) {
      return generateForBinaryExpr();
    }

    // For multiline strings
    if ((myNode.getElementType() == mSTRING_LITERAL || myNode.getElementType() == mGSTRING_LITERAL)
        && myBlock.getTextRange().equals(myNode.getTextRange())) {
      String text = myNode.getText();
      if (text.length() > 6) {
        if (text.substring(0, 3).equals("'''") && text.substring(text.length() - 3).equals("'''")
            || text.substring(0, 3).equals("\"\"\"")
                & text.substring(text.length() - 3).equals("\"\"\"")) {
          return generateForMultiLineString();
        }
      }
    }

    if (myNode.getElementType() == mGSTRING_BEGIN
        && myBlock.getTextRange().equals(myNode.getTextRange())) {
      String text = myNode.getText();
      if (text.length() > 3) {
        if (text.substring(0, 3).equals("\"\"\"")) {
          return generateForMultiLineGStringBegin();
        }
      }
    }

    // for gstrings
    if (myNode.getElementType() == GSTRING) {
      final ArrayList<Block> subBlocks = new ArrayList<Block>();
      ASTNode[] children = getGroovyChildren(myNode);
      for (ASTNode childNode : children) {
        if (childNode.getTextRange().getLength() > 0) {
          final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
          subBlocks.add(
              new GroovyBlock(
                  childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
        }
      }
      return subBlocks;
    }

    // chained properties, calls, indexing, etc
    if (NESTED.contains(myNode.getElementType())
        && blockPsi.getParent() != null
        && !NESTED.contains(blockPsi.getParent().getNode().getElementType())) {
      final List<Block> subBlocks = new ArrayList<Block>();
      AlignmentProvider.Aligner dotsAligner =
          mySettings.ALIGN_MULTILINE_CHAINED_METHODS
              ? myAlignmentProvider.createAligner(true)
              : null;
      addNestedChildren(myNode.getPsi(), subBlocks, dotsAligner, true);
      return subBlocks;
    }

    if (blockPsi instanceof GrListOrMap
        && ((GrListOrMap) blockPsi).isMap()
        && myGroovySettings.ALIGN_NAMED_ARGS_IN_MAP) {
      AlignmentProvider.Aligner labels = myAlignmentProvider.createAligner(false);
      AlignmentProvider.Aligner exprs = myAlignmentProvider.createAligner(true);
      GrNamedArgument[] namedArgs = ((GrListOrMap) blockPsi).getNamedArguments();
      for (GrNamedArgument arg : namedArgs) {
        GrArgumentLabel label = arg.getLabel();
        if (label != null) labels.append(label);

        PsiElement colon = arg.getColon();
        if (colon == null) colon = arg.getExpression();
        if (colon != null) exprs.append(colon);
      }
    }

    // For Parameter lists
    if (isListLikeClause(blockPsi)) {
      final ArrayList<Block> subBlocks = new ArrayList<Block>();
      List<ASTNode> astNodes = visibleChildren(myNode);

      if (mustAlign(blockPsi, astNodes)) {
        final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner(false);
        for (ASTNode node : astNodes) {
          if (!isKeyword(node)) aligner.append(node.getPsi());
        }
      }
      for (ASTNode childNode : astNodes) {
        final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
        subBlocks.add(
            new GroovyBlock(
                childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
      }
      return subBlocks;
    }

    boolean classLevel = blockPsi instanceof GrTypeDefinitionBody;
    if (blockPsi instanceof GrCodeBlock || blockPsi instanceof GroovyFile || classLevel) {
      List<ASTNode> children = visibleChildren(myNode);
      calculateAlignments(children, classLevel);
      final ArrayList<Block> subBlocks = new ArrayList<Block>();

      if (classLevel && myAlignment != null) {
        final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner(true);
        for (ASTNode child : children) {
          aligner.append(child.getPsi());
        }
      }
      for (ASTNode childNode : children) {
        final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
        subBlocks.add(
            new GroovyBlock(
                childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
      }
      return subBlocks;
    }

    // For other cases
    final ArrayList<Block> subBlocks = new ArrayList<Block>();
    for (ASTNode childNode : visibleChildren(myNode)) {
      final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
      subBlocks.add(
          new GroovyBlock(
              childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
    }
    return subBlocks;
  }