public static Spacing getSpacing(GroovyBlock child1,
                                   GroovyBlock child2,
                                   FormattingContext context) {

    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();

    final CommonCodeStyleSettings settings = context.getSettings();
    final GroovyCodeStyleSettings groovySettings = context.getGroovySettings();

    if (!(mirrorsAst(child1) && mirrorsAst(child2))) {
      return NO_SPACING;
    }

    if (child2 instanceof ClosureBodyBlock) {
      return settings.SPACE_WITHIN_BRACES ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }

    if (child1 instanceof ClosureBodyBlock) {
      return createDependentSpacingForClosure(settings, groovySettings, (GrClosableBlock)left.getParent(), false);
    }

    if (groovySettings.isGroovyDocFormattingAllowed() && leftType == GroovyDocElementTypes.GROOVY_DOC_COMMENT) {
      return COMMON_SPACING_WITH_NL;
    }

    if (right instanceof GrTypeArgumentList) {
      return NO_SPACING_WITH_NEWLINE;
    }

// ********** punctuation marks ************
    if (GroovyTokenTypes.mCOMMA == leftType) {
      return settings.SPACE_AFTER_COMMA ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }
    if (GroovyTokenTypes.mCOMMA == rightType) {
      return settings.SPACE_BEFORE_COMMA ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }
    if (GroovyTokenTypes.mSEMI == leftType) {
      return settings.SPACE_AFTER_SEMICOLON ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }
    if (GroovyTokenTypes.mSEMI == rightType) {
      return settings.SPACE_BEFORE_SEMICOLON ? COMMON_SPACING : NO_SPACING_WITH_NEWLINE;
    }
    // For dots, commas etc.
    if ((TokenSets.DOTS.contains(rightType)) ||
        (GroovyTokenTypes.mCOLON.equals(rightType) && !(right.getParent() instanceof GrConditionalExpression))) {
      return NO_SPACING_WITH_NEWLINE;
    }

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

    //todo:check it for multiple assignments
    if ((GroovyStubElementTypes.VARIABLE_DECLARATION.equals(leftType) || GroovyStubElementTypes.VARIABLE_DECLARATION.equals(rightType)) &&
        !(leftNode.getTreeNext() instanceof PsiErrorElement)) {
      return getStatementSpacing(context);
    }

    // For regexes
    if (leftNode.getTreeParent().getElementType() == GroovyTokenTypes.mREGEX_LITERAL ||
        leftNode.getTreeParent().getElementType() == GroovyTokenTypes.mDOLLAR_SLASH_REGEX_LITERAL) {
      return NO_SPACING;
    }

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

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

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

    if (GroovyDocTokenTypes.mGDOC_ASTERISKS == leftType && GroovyDocTokenTypes.mGDOC_COMMENT_DATA == rightType) {
      if (!groovySettings.isGroovyDocFormattingAllowed()) {
        return LAZY_SPACING;
      }
      String text = rightNode.getText();
      if (!text.isEmpty() && !StringUtil.startsWithChar(text, ' ')) {
        return COMMON_SPACING;
      }
      return NO_SPACING;
    }

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

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

    Spacing rightSpacing = getGroovyDocBraceSpacing(right);
    Spacing actualSpacing = rightSpacing == null ? getGroovyDocBraceSpacing(left) : rightSpacing;
    if (actualSpacing != null) {
      if (!groovySettings.isGroovyDocFormattingAllowed()) {
        return LAZY_SPACING;
      }
      return actualSpacing;
    }

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

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

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

    return COMMON_SPACING;
  }
public static Spacing getSpacing(GroovyBlock child1,
                                   GroovyBlock child2,
                                   FormattingContext context)