Search in sources :

Example 6 with AbstractBlock

use of com.intellij.psi.formatter.common.AbstractBlock in project intellij-plugins by JetBrains.

the class CfmlSpacingProcessor method getSpacing.

public Spacing getSpacing(Block child1, Block child2) {
    if (!(child1 instanceof AbstractBlock) || !(child2 instanceof AbstractBlock)) {
        return null;
    }
    final IElementType elementType = myNode.getElementType();
    final ASTNode node1 = ((AbstractBlock) child1).getNode();
    final IElementType type1 = node1.getElementType();
    final ASTNode node2 = ((AbstractBlock) child2).getNode();
    final IElementType type2 = node2.getElementType();
    //ColdFusion Tag Spacing//
    if (type2 == CfmlElementTypes.TAG || type2 == CfmlElementTypes.FORTAGEXPRESSION || type2 == CfmlElementTypes.ARGUMENT_TAG || type2 == CfmlElementTypes.FUNCTION_DEFINITION || type2 == CfmlElementTypes.SCRIPT_TAG) {
        return Spacing.createSpacing(0, 0, 1, false, 1);
    } else if (type1 == CfmlTokenTypes.OPENER || type2 == CfmlTokenTypes.R_ANGLEBRACKET || type2 == CfmlTokenTypes.CLOSER) {
        return Spacing.createSpacing(0, 0, 0, false, 0);
    } else if (elementType == CfmlElementTypes.ATTRIBUTE) {
        return getSpacesInsideAttribute(type1, type2);
    } else if (type1 == CfmlTokenTypes.CF_TAG_NAME && node1.getTreePrev().getElementType() == CfmlTokenTypes.LSLASH_ANGLEBRACKET) {
        return Spacing.createSpacing(0, 0, 0, false, 0);
    } else if (type1 == CfmlTokenTypes.CF_TAG_NAME && type2 == CfmlElementTypes.ASSIGNMENT) {
        return Spacing.createSpacing(1, 1, 0, false, 0);
    }
    //
    if (type2 == CfmlElementTypes.ARGUMENT_LIST) {
        if ((elementType == CfmlElementTypes.FUNCTION_CALL_EXPRESSION) && type1 == CfmlElementTypes.REFERENCE_EXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
        }
    } else if (type2 == CfscriptTokenTypes.L_BRACKET) {
        if ((elementType == CfmlElementTypes.IFEXPRESSION) && type1 == CfscriptTokenTypes.IF_KEYWORD) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_IF_PARENTHESES);
        } else if ((elementType == CfmlElementTypes.WHILEEXPRESSION) && type1 == CfscriptTokenTypes.WHILE_KEYWORD) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_WHILE_PARENTHESES);
        } else if ((elementType == CfmlElementTypes.FOREXPRESSION) && type1 == CfscriptTokenTypes.FOR_KEYWORD) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_FOR_PARENTHESES);
        } else if ((elementType == CfmlElementTypes.SWITCHEXPRESSION) && type1 == CfscriptTokenTypes.SWITCH_KEYWORD) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES);
        } else if ((elementType == CfmlElementTypes.CATCHEXPRESSION) && type1 == CfscriptTokenTypes.CATCH_KEYWORD) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_CATCH_PARENTHESES);
        }
    } else if ((elementType == CfmlElementTypes.FUNCTION_DEFINITION) && type1 == CfscriptTokenTypes.IDENTIFIER && type2 == CfmlElementTypes.PARAMETERS_LIST) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_METHOD_PARENTHESES);
    }
    //
    if (type1 == CfmlTokenTypes.ATTRIBUTE || (type1 == CfmlTokenTypes.ASSIGN && type2 == CfmlTokenTypes.DOUBLE_QUOTE)) {
        return Spacing.createSpacing(0, 0, 0, false, 0);
    }
    if (isAssignmentOperator(type1) || isAssignmentOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
    }
    //
    if (isLogicalOperator(type1) || isLogicalOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_LOGICAL_OPERATORS);
    }
    //
    if (isEqualityOperator(type1) || isEqualityOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_EQUALITY_OPERATORS);
    }
    //
    if (isRelationalOperator(type1) || isRelationalOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_RELATIONAL_OPERATORS);
    }
    //
    if (isAdditiveOperator(type1) || isAdditiveOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ADDITIVE_OPERATORS);
    }
    //
    if (isMultiplicativeOperator(type1) || isMultiplicativeOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS);
    }
    //
    if (isUnaryOperator(type1) || isUnaryOperator(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_UNARY_OPERATOR);
    }
    //
    if (type1 == CfscriptTokenTypes.CONCAT || type2 == CfscriptTokenTypes.CONCAT) {
        return addSingleSpaceIf(myCfmlSettings.CONCAT_SPACES);
    }
    //
    if (type1 == CfscriptTokenTypes.R_BRACKET) {
        if (type2 == CfscriptTokenTypes.L_CURLYBRACKET && elementType == CfmlElementTypes.SWITCHEXPRESSION) {
            return setBraceSpace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (type2 == CfmlElementTypes.BLOCK_OF_STATEMENTS) {
            if (elementType == CfmlElementTypes.IFEXPRESSION) {
                return setBraceSpace(mySettings.SPACE_BEFORE_IF_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
            } else if (elementType == CfmlElementTypes.FOREXPRESSION) {
                return setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
            } else if (elementType == CfmlElementTypes.WHILEEXPRESSION) {
                return setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
            }
        }
    } else if (type1 == CfscriptTokenTypes.ELSE_KEYWORD) {
        if (type2 == CfmlElementTypes.IFEXPRESSION) {
            return Spacing.createSpacing(1, 1, mySettings.SPECIAL_ELSE_IF_TREATMENT ? 0 : 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
        } else if (type2 == CfmlElementTypes.BLOCK_OF_STATEMENTS) {
            return setBraceSpace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        }
        return Spacing.createSpacing(1, 1, 0, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
    } else if (type1 == CfscriptTokenTypes.TRY_KEYWORD) {
        return setBraceSpace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
    } else if (type1 == CfscriptTokenTypes.CATCH_KEYWORD) {
        return setBraceSpace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
    } else if (type1 == CfscriptTokenTypes.DO_KEYWORD) {
        return setBraceSpace(mySettings.SPACE_BEFORE_DO_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
    } else if (type1 == CfmlElementTypes.PARAMETERS_LIST && type2 == CfmlElementTypes.FUNCTIONBODY) {
        return setBraceSpace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, child1.getTextRange());
    }
    //
    if (type2 == CfscriptTokenTypes.ELSE_KEYWORD) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_ELSE_KEYWORD, mySettings.ELSE_ON_NEW_LINE);
    } else if (type2 == CfscriptTokenTypes.WHILE_KEYWORD) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_WHILE_KEYWORD, mySettings.WHILE_ON_NEW_LINE);
    } else if (type2 == CfmlElementTypes.CATCHEXPRESSION) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_CATCH_KEYWORD, mySettings.CATCH_ON_NEW_LINE);
    }
    //
    if ((type1 == CfscriptTokenTypes.L_BRACKET || type2 == CfscriptTokenTypes.R_BRACKET)) {
        if (elementType == CfmlElementTypes.ARGUMENT_LIST) {
            if (type1 == CfscriptTokenTypes.L_BRACKET) {
                return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, mySettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE);
            }
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, mySettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE);
        } else if (elementType == CfmlElementTypes.PARAMETERS_LIST) {
            if (type1 == CfscriptTokenTypes.L_BRACKET) {
                return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_PARENTHESES, mySettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE);
            }
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_PARENTHESES, mySettings.METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE);
        } else if (elementType == CfmlElementTypes.IFEXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_IF_PARENTHESES);
        } else if (elementType == CfmlElementTypes.FOREXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
        } else if (elementType == CfmlElementTypes.WHILEEXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_WHILE_PARENTHESES);
        } else if (elementType == CfmlElementTypes.SWITCHEXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES);
        } else if (elementType == CfmlElementTypes.CATCHEXPRESSION) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_CATCH_PARENTHESES);
        }
        if (mySettings.BINARY_OPERATION_WRAP != CommonCodeStyleSettings.DO_NOT_WRAP && type2 == CfmlElementTypes.BINARY_EXPRESSION) {
            return Spacing.createSpacing(0, 0, mySettings.PARENTHESES_EXPRESSION_LPAREN_WRAP ? 1 : 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        } else if (mySettings.BINARY_OPERATION_WRAP != CommonCodeStyleSettings.DO_NOT_WRAP && type1 == CfmlElementTypes.BINARY_EXPRESSION) {
            return Spacing.createSpacing(0, 0, mySettings.PARENTHESES_EXPRESSION_RPAREN_WRAP ? 1 : 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
    }
    //
    if (elementType == CfmlElementTypes.TERNARY_EXPRESSION) {
        if (type2 == CfscriptTokenTypes.QUESTION) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_QUEST);
        } else if (type1 == CfscriptTokenTypes.QUESTION) {
            return addSingleSpaceIf(mySettings.SPACE_AFTER_QUEST);
        } else if (type2 == CfscriptTokenTypes.DOTDOT) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_COLON);
        } else if (type1 == CfscriptTokenTypes.DOTDOT) {
            return addSingleSpaceIf(mySettings.SPACE_AFTER_COLON);
        }
    }
    if (type2 == CfscriptTokenTypes.COMMA) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_COMMA);
    }
    if (type1 == CfscriptTokenTypes.COMMA) {
        return addSingleSpaceIf(mySettings.SPACE_AFTER_COMMA);
    }
    if (type2 == CfscriptTokenTypes.SEMICOLON) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_SEMICOLON);
    }
    if (type1 == CfscriptTokenTypes.SEMICOLON) {
        return addSingleSpaceIf(mySettings.SPACE_AFTER_SEMICOLON);
    }
    return Spacing.createSpacing(0, 1, 0, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ASTNode(com.intellij.lang.ASTNode) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock)

Example 7 with AbstractBlock

use of com.intellij.psi.formatter.common.AbstractBlock in project intellij-community by JetBrains.

the class CodeBlockBlock method createCaseSectionBlock.

private SyntheticCodeBlock createCaseSectionBlock(final List<Block> localResult, final Alignment childAlignment, final Indent indent, final Wrap childWrap) {
    final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, childAlignment, getSettings(), myJavaSettings, indent, childWrap) {

        @Override
        @NotNull
        public ChildAttributes getChildAttributes(final int newChildIndex) {
            IElementType prevElementType = null;
            if (newChildIndex > 0) {
                final Block previousBlock = getSubBlocks().get(newChildIndex - 1);
                if (previousBlock instanceof AbstractBlock) {
                    prevElementType = ((AbstractBlock) previousBlock).getNode().getElementType();
                }
            }
            if (prevElementType == JavaElementType.BLOCK_STATEMENT || prevElementType == JavaElementType.BREAK_STATEMENT || prevElementType == JavaElementType.RETURN_STATEMENT) {
                return new ChildAttributes(Indent.getNoneIndent(), null);
            } else {
                return super.getChildAttributes(newChildIndex);
            }
        }
    };
    result.setChildAttributes(new ChildAttributes(Indent.getNormalIndent(), null));
    result.setIsIncomplete(true);
    return result;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock)

Example 8 with AbstractBlock

use of com.intellij.psi.formatter.common.AbstractBlock in project intellij-community by JetBrains.

the class SimpleTemplateLanguageFormattingModelBuilder method createModel.

@Override
@NotNull
public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
    if (element instanceof PsiFile) {
        final FileViewProvider viewProvider = ((PsiFile) element).getViewProvider();
        if (viewProvider instanceof TemplateLanguageFileViewProvider) {
            final Language language = ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage();
            FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forLanguage(language);
            if (builder != null) {
                return builder.createModel(viewProvider.getPsi(language), settings);
            }
        }
    }
    final PsiFile file = element.getContainingFile();
    return new DocumentBasedFormattingModel(new AbstractBlock(element.getNode(), Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment()) {

        @Override
        protected List<Block> buildChildren() {
            return Collections.emptyList();
        }

        @Override
        public Spacing getSpacing(final Block child1, @NotNull final Block child2) {
            return Spacing.getReadOnlySpacing();
        }

        @Override
        public boolean isLeaf() {
            return true;
        }
    }, element.getProject(), settings, file.getFileType(), file);
}
Also used : DocumentBasedFormattingModel(com.intellij.psi.formatter.DocumentBasedFormattingModel) FileViewProvider(com.intellij.psi.FileViewProvider) Language(com.intellij.lang.Language) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock) PsiFile(com.intellij.psi.PsiFile) List(java.util.List) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with AbstractBlock

use of com.intellij.psi.formatter.common.AbstractBlock in project intellij-community by JetBrains.

the class XmlBlock method getSpacing.

@Override
public Spacing getSpacing(Block child1, @NotNull Block child2) {
    if (!(child1 instanceof AbstractBlock) || !(child2 instanceof AbstractBlock)) {
        return null;
    }
    final IElementType elementType = myNode.getElementType();
    final ASTNode node1 = ((AbstractBlock) child1).getNode();
    final IElementType type1 = node1.getElementType();
    final ASTNode node2 = ((AbstractBlock) child2).getNode();
    final IElementType type2 = node2.getElementType();
    if ((isXmlTag(node2) || type2 == XmlTokenType.XML_END_TAG_START || type2 == XmlElementType.XML_TEXT) && myXmlFormattingPolicy.getShouldKeepWhiteSpaces()) {
        return Spacing.getReadOnlySpacing();
    }
    if (elementType == XmlElementType.XML_TEXT) {
        return getSpacesInsideText(type1, type2);
    } else if (elementType == XmlElementType.XML_ATTRIBUTE) {
        return getSpacesInsideAttribute(type1, type2);
    }
    if (type1 == XmlElementType.XML_PROLOG) {
        return createDefaultSpace(true, false);
    }
    if (elementType == XmlElementType.XML_DOCTYPE) {
        return createDefaultSpace(true, false);
    }
    return createDefaultSpace(false, false);
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ASTNode(com.intellij.lang.ASTNode) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock)

Example 10 with AbstractBlock

use of com.intellij.psi.formatter.common.AbstractBlock in project intellij-plugins by JetBrains.

the class DartSpacingProcessor method getSpacing.

public Spacing getSpacing(final Block child1, final Block child2) {
    if (!(child1 instanceof AbstractBlock) || !(child2 instanceof AbstractBlock)) {
        return null;
    }
    final IElementType elementType = myNode.getElementType();
    final IElementType parentType = myNode.getTreeParent() == null ? null : myNode.getTreeParent().getElementType();
    final ASTNode node1 = ((AbstractBlock) child1).getNode();
    final IElementType type1 = node1.getElementType();
    final ASTNode node2 = ((AbstractBlock) child2).getNode();
    final IElementType type2 = node2.getElementType();
    if (type2 == SINGLE_LINE_COMMENT && !isDirectlyPrecededByNewline(node2)) {
        // but after '{' in class or function definition Dart Style inserts line break, so let's do the same
        if (type1 != LBRACE || (elementType != CLASS_BODY && (!BLOCKS.contains(elementType) || parentType != FUNCTION_BODY))) {
            return Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE, 0);
        }
    }
    if (elementType == DART_FILE && COMMENTS.contains(type1) && !COMMENTS.contains(type2)) {
        final ASTNode prev = getPrevSiblingOnTheSameLineSkipCommentsAndWhitespace(((AbstractBlock) child1).getNode());
        if (prev != null) {
            final int lineBreaks = getMinLineBreaksBetweenTopLevelNodes(prev.getElementType(), type2);
            return Spacing.createSpacing(0, 0, lineBreaks, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
    }
    if (type1 == SINGLE_LINE_COMMENT) {
        return Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (type2 == SINGLE_LINE_DOC_COMMENT) {
        int nsp = 2;
        if (type1 == SINGLE_LINE_DOC_COMMENT || (elementType != DART_FILE && type1 == LBRACE))
            nsp = 1;
        return Spacing.createSpacing(0, 0, nsp, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (DIRECTIVE_GROUPS.contains(type1)) {
        if (type2 == MULTI_LINE_COMMENT) {
            ASTNode next = FormatterUtil.getNextNonWhitespaceSibling(node2);
            if (next != null && next.getElementType() == type1) {
                boolean needsNewline = isEmbeddedComment(type2, child2) && !isDirectlyPrecededByNewline(next);
                int space = needsNewline ? 0 : 1;
                int newline = needsNewline ? 1 : 0;
                return Spacing.createSpacing(0, space, newline, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
            }
        }
        if (type2 != IMPORT_STATEMENT && type2 != EXPORT_STATEMENT && !isEmbeddedComment(type2, child2)) {
            int numNewlines = COMMENTS.contains(type2) && isBlankLineAfterComment(node2) ? 1 : 2;
            return Spacing.createSpacing(0, 0, numNewlines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
    }
    if (type1 == LIBRARY_STATEMENT) {
        int newlines = COMMENTS.contains(type2) && isBlankLineAfterComment(node2) ? 1 : 2;
        return Spacing.createSpacing(0, 0, newlines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (elementType == LIBRARY_STATEMENT || parentType == LIBRARY_STATEMENT) {
        if (isEmbeddedComment(type2, child2)) {
            return Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
        if (type1 == MULTI_LINE_COMMENT && isEmbeddedComment(type1, child1)) {
            return Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
    }
    if (parentType == LIBRARY_STATEMENT) {
        return noSpace();
    }
    if (SEMICOLON == type2) {
        if (type1 == SEMICOLON && elementType == STATEMENTS) {
            // Empty statement on new line.
            return addSingleSpaceIf(false, true);
        }
        return Spacing.createSpacing(0, 0, 0, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (AT == type1)
        return Spacing.createSpacing(0, 0, 0, false, 0);
    if (METADATA == type1) {
        if (parentType == TYPE_PARAMETERS) {
            // Metadata on type parameters must be inlined.
            return Spacing.createSpacing(1, 1, 0, false, 0);
        }
        if (COMMENTS.contains(type2)) {
            return Spacing.createSpacing(1, 1, 0, true, 0);
        }
        if (parentType == DART_FILE) {
            //false here
            return Spacing.createSpacing(0, 0, 1, false, 0);
        }
        if (parentType == CLASS_MEMBERS || FUNCTION_DEFINITION.contains(parentType)) {
            if (type2 == METADATA || FormatterUtil.isPrecededBy(node1, METADATA, WHITE_SPACE)) {
                // Multiple metadata each goes on its own line.
                return Spacing.createSpacing(0, 0, 1, false, 0);
            }
            // Metadata on constructors and methods may be inlined.
            return Spacing.createSpacing(1, 1, 0, true, 0);
        }
        if (parentType == VAR_DECLARATION_LIST) {
            if (myNode.getTreeParent().getTreeParent().getElementType() == STATEMENTS) {
                // Metadata on local variables must be on its own line.
                return Spacing.createSpacing(0, 0, 1, false, 0);
            }
            if (type2 == METADATA || FormatterUtil.isPrecededBy(node1, METADATA, WHITE_SPACE)) {
                // Multiple metadata each goes on its own line.
                return Spacing.createSpacing(0, 0, 1, false, 0);
            }
            // Metadata on fields may be inlined.
            return Spacing.createSpacing(1, 1, 0, true, 0);
        }
        if (parentType == NORMAL_FORMAL_PARAMETER) {
            // Metadata on parameter declarations must be inlined.
            return Spacing.createSpacing(1, 1, 0, false, 0);
        }
        // Other metadata occurrences may be inlined.
        return Spacing.createSpacing(1, 1, 0, true, 0);
    }
    if (FUNCTION_DEFINITION.contains(type2)) {
        boolean needsBlank = needsBlankLineBeforeFunction(elementType);
        if (needsBlank && !mySettings.KEEP_LINE_BREAKS) {
            if (parentType == CLASS_BODY || elementType == DART_FILE) {
                if (type1 == SEMICOLON || hasEmptyBlock(node1)) {
                    needsBlank = false;
                }
            }
        }
        final int lineFeeds = COMMENTS.contains(type1) || !needsBlank ? 1 : 2;
        return Spacing.createSpacing(0, 0, lineFeeds, needsBlank, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (DOC_COMMENT_CONTENTS.contains(type2)) {
        return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (BLOCKS_EXT.contains(elementType)) {
        boolean topLevel = elementType == DART_FILE || elementType == EMBEDDED_CONTENT;
        int lineFeeds = 1;
        int spaces = 0;
        int blanks = mySettings.KEEP_BLANK_LINES_IN_CODE;
        boolean keepBreaks = false;
        if (!COMMENTS.contains(type1) && (elementType == CLASS_MEMBERS || topLevel && DECLARATIONS.contains(type2))) {
            if (type1 == SEMICOLON && type2 == VAR_DECLARATION_LIST) {
                final ASTNode node1TreePrev = node1.getTreePrev();
                if (node1TreePrev == null || node1TreePrev.getElementType() != VAR_DECLARATION_LIST) {
                    lineFeeds = 2;
                }
            } else {
                if (type2 == VAR_DECLARATION_LIST && hasEmptyBlock(node1) || type1 == FUNCTION_TYPE_ALIAS && type2 == FUNCTION_TYPE_ALIAS) {
                    lineFeeds = 1;
                } else {
                    lineFeeds = 2;
                }
            }
        } else if (type1 == LBRACE && type2 == RBRACE) {
            if (parentType == ON_PART && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == FUNCTION_BODY) {
                if ((myNode.getTreeParent().getTreeParent() != null) && (myNode.getTreeParent().getTreeParent().getElementType() == METHOD_DECLARATION) && mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE) {
                    // Empty method.
                    lineFeeds = 0;
                    keepBreaks = mySettings.KEEP_LINE_BREAKS;
                    blanks = keepBreaks ? mySettings.KEEP_BLANK_LINES_IN_CODE : 0;
                } else if (mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                    // Empty function, either top-level or statement.
                    lineFeeds = 0;
                    keepBreaks = mySettings.KEEP_LINE_BREAKS;
                    blanks = keepBreaks ? mySettings.KEEP_BLANK_LINES_IN_CODE : 0;
                }
            } else if (parentType == IF_STATEMENT && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == FOR_STATEMENT && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == WHILE_STATEMENT && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == DO_WHILE_STATEMENT && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == TRY_STATEMENT && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == FINALLY_PART && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == FUNCTION_EXPRESSION_BODY && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            } else if (parentType == STATEMENTS && mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
                lineFeeds = 0;
            }
        } else if (topLevel && COMMENTS.contains(type2)) {
            lineFeeds = 0;
            spaces = 1;
            keepBreaks = true;
        } else if (type1 != LBRACE && isEmbeddedComment(type2, child2)) {
            lineFeeds = 0;
            spaces = 1;
            keepBreaks = false;
        } else if ((type1 == LBRACE && type2 == STATEMENTS) || (type2 == RBRACE && type1 == STATEMENTS)) {
            lineFeeds = 1;
            keepBreaks = false;
            blanks = 0;
        } else if (type1 == LBRACE && type2 == SINGLE_LINE_COMMENT) {
            lineFeeds = 1;
            keepBreaks = false;
            blanks = 0;
        } else if (type1 == MULTI_LINE_COMMENT && type2 == STATEMENTS) {
            spaces = 1;
            lineFeeds = 0;
            keepBreaks = true;
        }
        return Spacing.createSpacing(spaces, spaces, lineFeeds, keepBreaks, blanks);
    }
    if (elementType == STATEMENTS && (parentType == SWITCH_CASE || parentType == DEFAULT_CASE)) {
        return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (!COMMENTS.contains(type2) && BLOCKS.contains(parentType)) {
        return addLineBreak();
    }
    // Special checks for switch formatting according to dart_style, which conflicts with settings.
    if (type2 == RBRACE && (type1 == SWITCH_CASE || type1 == DEFAULT_CASE)) {
        // No blank line before closing brace in switch statement.
        return Spacing.createSpacing(0, 0, 1, false, 0);
    }
    if (type1 == COLON && (elementType == SWITCH_CASE || elementType == DEFAULT_CASE)) {
        // No blank line before first statement of a case.
        return Spacing.createSpacing(0, 0, 1, false, 0);
    }
    if (elementType == SWITCH_STATEMENT && type1 == LBRACE) {
        // No blank line before first case of a switch.
        return Spacing.createSpacing(0, 0, 1, false, 0);
    }
    if (type1 == STATEMENTS || type2 == STATEMENTS) {
        return addLineBreak();
    }
    if (type1 == CLASS_MEMBERS || type2 == CLASS_MEMBERS) {
        if (type1 == MULTI_LINE_COMMENT) {
            return addSingleSpaceIf(true, false);
        } else {
            return addSingleSpaceIf(false, true);
        }
    }
    if (type2 == LPAREN) {
        if (elementType == IF_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_IF_PARENTHESES);
        } else if (elementType == WHILE_STATEMENT || elementType == DO_WHILE_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_WHILE_PARENTHESES);
        } else if (elementType == SWITCH_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES);
        } else if (elementType == ON_PART || elementType == CATCH_PART) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_CATCH_PARENTHESES);
        }
    }
    if (elementType == IF_STATEMENT) {
        if (type1 == RPAREN && mySettings.BRACE_STYLE == CommonCodeStyleSettings.END_OF_LINE) {
            // Always have a single space following the closing paren of an if-condition.
            int nsp = mySettings.SPACE_BEFORE_IF_LBRACE ? 1 : 0;
            int lf = 0;
            if (!BLOCKS.contains(type2) && mySettings.SPECIAL_ELSE_IF_TREATMENT) {
                if (FormatterUtil.isFollowedBy(node2, ELSE, SEMICOLON))
                    lf = 1;
            }
            return Spacing.createSpacing(nsp, nsp, lf, !BLOCKS.contains(type2) && mySettings.KEEP_LINE_BREAKS, 0);
        }
        if (type1 == SEMICOLON && type2 == ELSE) {
            // If the then-part is on the line with the condition put the else-part on the next line.
            return Spacing.createSpacing(0, 0, 1, false, 0);
        }
    }
    if (type2 == FOR_LOOP_PARTS_IN_BRACES) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_FOR_PARENTHESES);
    }
    if (type2 == FORMAL_PARAMETER_LIST && (FUNCTION_DEFINITION.contains(elementType) || elementType == FUNCTION_EXPRESSION)) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_METHOD_PARENTHESES);
    }
    if (elementType == DEFAULT_FORMAL_NAMED_PARAMETER && (type1 == EQ || type2 == EQ)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
    }
    if (type2 == ARGUMENTS && elementType == CALL_EXPRESSION) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
    }
    //
    if (BLOCKS.contains(type2)) {
        if (elementType == IF_STATEMENT && type1 != ELSE) {
            return setBraceSpace(mySettings.SPACE_BEFORE_IF_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == IF_STATEMENT && type1 == ELSE) {
            return setBraceSpace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == WHILE_STATEMENT || elementType == DO_WHILE_STATEMENT) {
            return setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == FOR_STATEMENT) {
            return setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == TRY_STATEMENT) {
            return setBraceSpace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == ON_PART) {
            return setBraceSpace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        } else if (elementType == FINALLY_PART) {
            return setBraceSpace(mySettings.SPACE_BEFORE_FINALLY_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        }
    }
    if (type2 == LBRACE && elementType == SWITCH_STATEMENT) {
        return setBraceSpace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
    }
    if (FUNCTION_DEFINITION.contains(elementType) && type2 == FUNCTION_BODY) {
        return setBraceSpace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, child1.getTextRange());
    }
    if (elementType == FUNCTION_EXPRESSION && type2 == FUNCTION_EXPRESSION_BODY) {
        return setBraceSpace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, child1.getTextRange());
    }
    if (elementType == CLASS_DEFINITION) {
        if (type2 == CLASS_BODY) {
            return setBraceSpace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        }
        if (type2 == TYPE_PARAMETERS) {
            return noSpace();
        }
        if (type2 == INTERFACES || type2 == MIXINS) {
            ASTNode typeNameNode = FormatterUtil.getNextNonWhitespaceSibling(myNode.getFirstChildNode());
            ASTNode bodyNode = myNode.getLastChildNode();
            if (typeNameNode != null && bodyNode != null) {
                // For some reason we need to start at the beginning of the type name, not the end.
                TextRange range = TextRange.create(typeNameNode.getTextRange().getStartOffset(), bodyNode.getStartOffset());
                return Spacing.createDependentLFSpacing(1, 1, range, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
            }
        }
        return Spacing.createSpacing(1, 1, 0, false, 0);
    }
    if (elementType == MIXIN_APPLICATION) {
        return Spacing.createSpacing(1, 1, 0, false, 0);
    }
    if (elementType == ENUM_DEFINITION) {
        if (mySettings.BRACE_STYLE == CommonCodeStyleSettings.END_OF_LINE) {
            if (type1 == LBRACE && type2 == RBRACE) {
                return noSpace();
            }
            if (type1 == LBRACE || type2 == RBRACE) {
                return Spacing.createDependentLFSpacing(1, 1, textRangeFollowingMetadata(), false, 0);
            }
            if (type2 == ENUM_CONSTANT_DECLARATION) {
                return Spacing.createDependentLFSpacing(1, 1, textRangeFollowingMetadata(), false, 0);
            }
        }
        if (type2 == LBRACE) {
            return setBraceSpace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.BRACE_STYLE, child1.getTextRange());
        }
    }
    if (type1 == LPAREN || type2 == RPAREN) {
        if (elementType == IF_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_IF_PARENTHESES);
        } else if (elementType == WHILE_STATEMENT || elementType == DO_WHILE_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_WHILE_PARENTHESES);
        } else if (elementType == FOR_LOOP_PARTS_IN_BRACES) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
        } else if (elementType == SWITCH_STATEMENT) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES);
        } else if (elementType == CATCH_PART) {
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_CATCH_PARENTHESES);
        } else if (elementType == FORMAL_PARAMETER_LIST) {
            final boolean newLineNeeded = type1 == LPAREN ? mySettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE : mySettings.METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE;
            if (newLineNeeded || mySettings.SPACE_WITHIN_METHOD_PARENTHESES) {
                return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_PARENTHESES, newLineNeeded);
            }
            return Spacing.createSpacing(0, 0, 0, false, 0);
        } else if (elementType == ARGUMENTS) {
            final boolean newLineNeeded = type1 == LPAREN ? mySettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE : mySettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE;
            return addSingleSpaceIf(mySettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, newLineNeeded);
        } else if (mySettings.BINARY_OPERATION_WRAP != CommonCodeStyleSettings.DO_NOT_WRAP && elementType == PARENTHESIZED_EXPRESSION) {
            final boolean newLineNeeded = type1 == LPAREN ? mySettings.PARENTHESES_EXPRESSION_LPAREN_WRAP : mySettings.PARENTHESES_EXPRESSION_RPAREN_WRAP;
            return addSingleSpaceIf(false, newLineNeeded);
        }
    }
    if (elementType == TERNARY_EXPRESSION) {
        if (type2 == QUEST) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_QUEST);
        } else if (type2 == COLON) {
            return addSingleSpaceIf(mySettings.SPACE_BEFORE_COLON);
        } else if (type1 == QUEST) {
            return addSingleSpaceIf(mySettings.SPACE_AFTER_QUEST);
        } else if (type1 == COLON) {
            return addSingleSpaceIf(mySettings.SPACE_AFTER_COLON);
        }
    }
    if (type1 == ASSIGNMENT_OPERATOR || type2 == ASSIGNMENT_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
    }
    if (type1 == EQ && elementType == VAR_INIT) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
    }
    if (type2 == VAR_INIT) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
    }
    //
    if (LOGIC_OPERATORS.contains(type1) || LOGIC_OPERATORS.contains(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_LOGICAL_OPERATORS);
    }
    //
    if (type1 == EQUALITY_OPERATOR || type2 == EQUALITY_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_EQUALITY_OPERATORS);
    }
    //
    if (type1 == RELATIONAL_OPERATOR || type2 == RELATIONAL_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_RELATIONAL_OPERATORS);
    }
    //
    if (BITWISE_OPERATORS.contains(type1) || BITWISE_OPERATORS.contains(type2)) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_BITWISE_OPERATORS);
    }
    //
    if ((type1 == ADDITIVE_OPERATOR || type2 == ADDITIVE_OPERATOR) && elementType != PREFIX_EXPRESSION) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_ADDITIVE_OPERATORS);
    }
    //
    if (type1 == MULTIPLICATIVE_OPERATOR || type2 == MULTIPLICATIVE_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS);
    }
    //
    if (type1 == PREFIX_OPERATOR && type2 == PREFIX_EXPRESSION) {
        ASTNode[] childs = node2.getChildren(PREFIX_OPERATOR_SET);
        if (childs.length > 0) {
            return addSingleSpaceIf(isSpaceNeededBetweenPrefixOps(node1, childs[0]));
        }
    }
    //
    if (type1 == PREFIX_OPERATOR || type2 == PREFIX_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_UNARY_OPERATOR);
    }
    //
    if (type1 == SHIFT_OPERATOR || type2 == SHIFT_OPERATOR) {
        return addSingleSpaceIf(mySettings.SPACE_AROUND_SHIFT_OPERATORS);
    }
    //
    if (type2 == ELSE) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_ELSE_KEYWORD, mySettings.ELSE_ON_NEW_LINE);
    }
    if (type2 == WHILE) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_WHILE_KEYWORD, mySettings.WHILE_ON_NEW_LINE);
    }
    if (type2 == ON_PART) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_CATCH_KEYWORD, mySettings.CATCH_ON_NEW_LINE);
    }
    if (type2 == FINALLY_PART) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_FINALLY_KEYWORD, mySettings.CATCH_ON_NEW_LINE);
    }
    if (type1 == ELSE) {
        if (type2 == IF_STATEMENT) {
            return Spacing.createSpacing(1, 1, mySettings.SPECIAL_ELSE_IF_TREATMENT ? 0 : 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
        if (type2 != LBRACE) {
            // Keep single-statement else-part on same line?
            int lf = mySettings.SPECIAL_ELSE_IF_TREATMENT ? 1 : 0;
            return Spacing.createSpacing(1, 1, lf, !BLOCKS.contains(type2) && mySettings.KEEP_LINE_BREAKS, 0);
        }
    }
    if (type1 == LBRACE && type2 == RBRACE) {
        // Empty class.
        if (elementType == CLASS_BODY && mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE)
            return noSpace();
        // Empty MAP_LITERAL_EXPRESSION or LIST_LITERAL_EXPRESSION.
        if (mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE)
            return noSpace();
    }
    boolean isBraces = type1 == LBRACE || type2 == RBRACE;
    if ((isBraces && elementType != OPTIONAL_FORMAL_PARAMETERS && elementType != OPTIONAL_PARAMETER_TYPES && elementType != MAP_LITERAL_EXPRESSION) || BLOCKS_EXT.contains(type1) || FUNCTION_DEFINITION.contains(type1)) {
        return addLineBreak();
    }
    if (COMMENTS.contains(type1)) {
        if (isBraces || type2 == SEMICOLON) {
            return addLineBreak();
        }
        if (parentType == DART_FILE && FUNCTION_DEFINITION.contains(elementType) && !(type1 == MULTI_LINE_COMMENT && type2 == COMPONENT_NAME)) {
            return addLineBreak();
        }
        if (type2 == RBRACKET && elementType != OPTIONAL_FORMAL_PARAMETERS) {
            return addLineBreak();
        }
        if (type2 == ARGUMENT_LIST || type2 == COMPONENT_NAME) {
            if (type1 == MULTI_LINE_COMMENT && isEmbeddedComment(type1, child1)) {
                if (!hasNewlineInText(node1)) {
                    return addSingleSpaceIf(true);
                }
            }
            return addLineBreak();
        }
    }
    if ((elementType == INTERFACES || elementType == MIXINS) && type2 == TYPE_LIST) {
        return Spacing.createDependentLFSpacing(1, 1, myNode.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (elementType == TYPE_LIST && type2 == TYPE) {
        return Spacing.createDependentLFSpacing(1, 1, myNode.getTreeParent().getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (type1 == LBRACKET && type2 == RBRACKET) {
        return noSpace();
    }
    if (type1 == COMMA && (elementType == FORMAL_PARAMETER_LIST || elementType == ARGUMENT_LIST)) {
        return addSingleSpaceIf(mySettings.SPACE_AFTER_COMMA);
    }
    if (type1 == COMMA) {
        if (type2 == RBRACKET) {
            TextRange range = myNode.getTextRange();
            return Spacing.createDependentLFSpacing(0, 0, range, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
        }
        return addSingleSpaceIf(mySettings.SPACE_AFTER_COMMA && type2 != RBRACE && type2 != RBRACKET);
    }
    if (type2 == COMMA) {
        return addSingleSpaceIf(mySettings.SPACE_BEFORE_COMMA);
    }
    if (type1 == EXPRESSION_BODY_DEF) {
        // =>
        if (type2 == STRING_LITERAL_EXPRESSION) {
            // We might want to add a check that the string contains a newline as in regression/0000/0036.unit
            return addSingleSpaceIf(true);
        }
        TextRange range = node2.getTextRange();
        return Spacing.createDependentLFSpacing(1, 1, range, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (type2 == EXPRESSION_BODY_DEF) {
        return addSingleSpaceIf(true);
    }
    if (type1 == FOR_LOOP_PARTS_IN_BRACES && !BLOCKS_EXT.contains(type2)) {
        return addLineBreak();
    }
    if (type1 == IF_STATEMENT || type1 == SWITCH_STATEMENT || type1 == TRY_STATEMENT || type1 == DO_WHILE_STATEMENT || type1 == FOR_STATEMENT || type1 == SWITCH_CASE || type1 == DEFAULT_CASE || type1 == WHILE_STATEMENT) {
        return addLineBreak();
    }
    if (COMMENTS.contains(type2)) {
        int forceSpace = 1;
        if (type2 == MULTI_LINE_COMMENT && (type1 == COMPONENT_NAME || type1 == TYPE || type1 == VAR || type1 == RETURN_TYPE)) {
            forceSpace = 0;
        }
        return Spacing.createSpacing(forceSpace, 1, 0, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (TOKENS_WITH_SPACE_AFTER.contains(type1) || KEYWORDS_WITH_SPACE_BEFORE.contains(type2)) {
        return addSingleSpaceIf(true);
    }
    if (elementType == FOR_LOOP_PARTS && type1 == SEMICOLON) {
        return addSingleSpaceIf(true);
    }
    if (elementType == VALUE_EXPRESSION && type2 == CASCADE_REFERENCE_EXPRESSION) {
        if (type1 == CASCADE_REFERENCE_EXPRESSION) {
            if (cascadesAreSameMethod(((AbstractBlock) child1).getNode(), ((AbstractBlock) child2).getNode())) {
                return Spacing.createSpacing(0, 0, 0, false, 0);
            }
        } else if (type1 == REFERENCE_EXPRESSION || isSimpleLiteral(type1)) {
            CompositeElement elem = (CompositeElement) myNode;
            ASTNode[] childs = elem.getChildren(CASCADE_REFERENCE_EXPRESSION_SET);
            if (childs.length == 1) {
                return Spacing.createDependentLFSpacing(0, 0, myNode.getTextRange(), true, 0);
            }
            if (allCascadesAreSameMethod(childs)) {
                return Spacing.createSpacing(0, 0, 0, false, 0);
            }
        } else if (type1 == NEW_EXPRESSION && parentType == ARGUMENT_LIST) {
            return Spacing.createDependentLFSpacing(0, 0, myNode.getTextRange(), true, 0);
        }
        return addLineBreak();
    }
    if (type1 == CLOSING_QUOTE && type2 == OPEN_QUOTE && elementType == STRING_LITERAL_EXPRESSION) {
        ASTNode sib = node1;
        int preserveNewline = 0;
        // Adjacent strings on the same line should not be split.
        while ((sib = sib.getTreeNext()) != null) {
            // TODO Create a test for this loop after adjacent-string wrapping is implemented.
            if (sib.getElementType() == WHITE_SPACE) {
                String ws = sib.getText();
                if (ws.contains("\n")) {
                    preserveNewline++;
                    break;
                }
                continue;
            }
            break;
        }
        // Adjacent strings on separate lines should not include blank lines.
        return Spacing.createSpacing(0, 1, preserveNewline, true, 0);
    }
    // Put the constructor colon on the next line unless only one initializer.
    if (type2 == INITIALIZERS) {
        if (hasMultipleInitializers(node2)) {
            return addSingleSpaceIf(false, true);
        } else {
            return addSingleSpaceIf(true, false);
        }
    }
    if (elementType == LIST_LITERAL_EXPRESSION && type2 == RBRACKET) {
        return Spacing.createDependentLFSpacing(0, 0, node1.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
    }
    if (elementType == NAMED_ARGUMENT || elementType == DEFAULT_FORMAL_NAMED_PARAMETER || elementType == MAP_LITERAL_ENTRY) {
        if (type1 == COLON) {
            return addSingleSpaceIf(true);
        }
        if (type2 == COLON) {
            return noSpace();
        }
    }
    if (elementType == TYPE_ARGUMENTS || elementType == TYPE_PARAMETERS) {
        if (type1 == LT || type2 == GT || type2 == LT || type1 == GT) {
            // Might want a user setting to control space within type
            return noSpace();
        }
    }
    if (elementType == IS_EXPRESSION) {
        if (type1 == NOT) {
            return addSingleSpaceIf(true);
        }
        if (type2 == NOT) {
            return noSpace();
        }
    }
    if (type1 == TYPE_ARGUMENTS && (type2 == LBRACKET || type2 == LBRACE)) {
        // Might want a user setting to control space before/after type
        return noSpace();
    }
    if (type2 == RBRACE && type1 == MAP_LITERAL_ENTRY) {
        return noSpace();
    }
    if (type2 == RBRACKET && type1 == LIST_LITERAL_EXPRESSION) {
        return noSpace();
    }
    if (type2 == RBRACKET && type1 == EXPRESSION_LIST) {
        return noSpace();
    }
    // Spacing in async functions.
    if (elementType == FUNCTION_BODY || elementType == FUNCTION_EXPRESSION_BODY) {
        if (type1 == ASYNC || type1 == SYNC) {
            if (type2 == MUL)
                return noSpace();
            return addSingleSpaceIf(true);
        }
        if (type1 == MUL)
            return addSingleSpaceIf(true);
    }
    if (elementType == REFERENCE_EXPRESSION && (type2 == DOT || type2 == QUEST_DOT)) {
        return createSpacingForCallChain(collectSurroundingMessageSends(), node2);
    }
    if (type1 == DOT || type1 == QUEST_DOT || type1 == HASH) {
        // Seems odd that no plugin has a setting for spaces around DOT -- need a Lisp mode!
        return noSpace();
    }
    if (type2 == HASH) {
        // No space before closurization.
        return addSingleSpaceIf(parentType == SYMBOL_LITERAL_EXPRESSION);
    }
    if (type1 == RETURN && type2 != SEMICOLON) {
        return addSingleSpaceIf(true);
    }
    return Spacing.createSpacing(0, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ASTNode(com.intellij.lang.ASTNode) TextRange(com.intellij.openapi.util.TextRange) CompositeElement(com.intellij.psi.impl.source.tree.CompositeElement) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock)

Aggregations

AbstractBlock (com.intellij.psi.formatter.common.AbstractBlock)10 IElementType (com.intellij.psi.tree.IElementType)6 ASTNode (com.intellij.lang.ASTNode)5 TextRange (com.intellij.openapi.util.TextRange)2 PsiElement (com.intellij.psi.PsiElement)2 PsiFile (com.intellij.psi.PsiFile)2 Language (com.intellij.lang.Language)1 FileViewProvider (com.intellij.psi.FileViewProvider)1 DocumentBasedFormattingModel (com.intellij.psi.formatter.DocumentBasedFormattingModel)1 CompositeElement (com.intellij.psi.impl.source.tree.CompositeElement)1 XmlAttribute (com.intellij.psi.xml.XmlAttribute)1 XmlTag (com.intellij.psi.xml.XmlTag)1 List (java.util.List)1 NotNull (org.jetbrains.annotations.NotNull)1