/* * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.coldFusion.model.formatter; import com.intellij.coldFusion.model.lexer.CfmlTokenTypes; import com.intellij.coldFusion.model.lexer.CfscriptTokenTypes; import com.intellij.coldFusion.model.parsers.CfmlElementTypes; import com.intellij.formatting.Block; import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.tree.IElementType; public class CfmlSpacingProcessor extends CfmlFormatterUtil { private final CommonCodeStyleSettings mySettings; private final CfmlCodeStyleSettings myCfmlSettings; private final ASTNode myNode; public CfmlSpacingProcessor(ASTNode node, CommonCodeStyleSettings settings, CfmlCodeStyleSettings cfmlSettings) { mySettings = settings; myCfmlSettings = cfmlSettings; myNode = node; } private static Spacing getSpacesInsideAttribute(final IElementType type1, final IElementType type2) { if (type1 == CfmlTokenTypes.ASSIGN || type2 == CfmlTokenTypes.ASSIGN) { return Spacing .createSpacing(0, 0, 0, true, 1); } else { return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, false, 1); } } 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); } //Cfscript spacing // // Spacing before parentheses // 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); } // // Spacing around assignment operators (=, -=, etc.) // 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); } // // Spacing around logical operators (&&, OR, etc.) // if (isLogicalOperator(type1) || isLogicalOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_LOGICAL_OPERATORS); } // // Spacing around equality operators (==, != etc.) // if (isEqualityOperator(type1) || isEqualityOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_EQUALITY_OPERATORS); } // // Spacing around relational operators (<, <= etc.) // if (isRelationalOperator(type1) || isRelationalOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_RELATIONAL_OPERATORS); } // // Spacing around additive operators ( |, &, etc.) // if (isAdditiveOperator(type1) || isAdditiveOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_ADDITIVE_OPERATORS); } // // Spacing around multiplicative operators ( |, &, etc.) // if (isMultiplicativeOperator(type1) || isMultiplicativeOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS); } // // Spacing around unary operators ( NOT, ++, etc.) // if (isUnaryOperator(type1) || isUnaryOperator(type2)) { return addSingleSpaceIf(mySettings.SPACE_AROUND_UNARY_OPERATOR); } // // Spacing around concatenation operator ( &, etc.) // if (type1 == CfscriptTokenTypes.CONCAT || type2 == CfscriptTokenTypes.CONCAT) { return addSingleSpaceIf(myCfmlSettings.CONCAT_SPACES); } // // //Spacing before left braces // 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()); } // //Spacing before keyword (else, catch, etc) // 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); } // //Spacing within // 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); } } // //Spacing in ternary operator(?:) // 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); } } // //Other spacing (',',';') // 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); } private Spacing addSingleSpaceIf(boolean condition) { int spaces = condition ? 1 : 0; return Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } private Spacing addSingleSpaceIf(boolean condition, boolean linesFeed) { int spaces = condition ? 1 : 0; int lines = linesFeed ? 1 : 0; return Spacing.createSpacing(spaces, spaces, lines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } private Spacing setBraceSpace(boolean needSpaceSetting, @CommonCodeStyleSettings.BraceStyleConstant int braceStyleSetting, TextRange textRange) { int spaces = needSpaceSetting ? 1 : 0; if (braceStyleSetting == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED && textRange != null) { return Spacing.createDependentLFSpacing(spaces, spaces, textRange, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } else { int lineBreaks = braceStyleSetting == CommonCodeStyleSettings.END_OF_LINE || braceStyleSetting == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED ? 0 : 1; return Spacing.createSpacing(spaces, spaces, lineBreaks, false, 0); } } }