/*
* Copyright 2012-2014 Sergey Ignatov
*
* 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 org.intellij.erlang.formatter;
import com.intellij.formatting.FormattingModel;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.formatting.FormattingModelProvider;
import com.intellij.formatting.SpacingBuilder;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.tree.TokenSet;
import org.intellij.erlang.ErlangLanguage;
import org.intellij.erlang.formatter.settings.ErlangCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import static org.intellij.erlang.ErlangTypes.*;
public class ErlangFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
CommonCodeStyleSettings commonSettings = settings.getCommonSettings(ErlangLanguage.INSTANCE);
ErlangCodeStyleSettings erlangSettings = settings.getCustomSettings(ErlangCodeStyleSettings.class);
SpacingBuilder spacingBuilder = createSpacingBuilder(commonSettings, erlangSettings);
ErlangFormattingBlock block = new ErlangFormattingBlock(element.getNode(), null, null, null, commonSettings, erlangSettings, spacingBuilder, -1);
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings);
}
private static SpacingBuilder createSpacingBuilder(@NotNull CommonCodeStyleSettings settings, @NotNull ErlangCodeStyleSettings erlangSettings) {
TokenSet rules = TokenSet.create(ERL_RULE, ERL_RECORD_DEFINITION, ERL_INCLUDE, ERL_MACROS_DEFINITION, ERL_ATTRIBUTE);
TokenSet keywords = TokenSet.create(
ERL_AFTER, ERL_WHEN, ERL_BEGIN, ERL_END, ERL_OF, ERL_CASE, ERL_CATCH, ERL_IF, ERL_RECEIVE,
ERL_TRY, ERL_DIV, ERL_REM, ERL_OR, ERL_XOR, ERL_BOR, ERL_BXOR, ERL_BSL, ERL_BSR, ERL_AND, ERL_BAND);
//noinspection SuspiciousNameCombination
return new SpacingBuilder(settings.getRootSettings(), ErlangLanguage.INSTANCE)
.before(ERL_COMMA).spaceIf(settings.SPACE_BEFORE_COMMA)
.after(ERL_COMMA).spaceIf(settings.SPACE_AFTER_COMMA)
.before(ERL_SEMI).none()
.between(ERL_OP_EQ, ERL_BINARY_EXPRESSION).spaces(1)
.between(ERL_OP_EQ, ERL_BINARY_TYPE).spaces(1)
.aroundInside(ERL_OP_EQ, ERL_RECORD_FIELD).spaceIf(erlangSettings.SPACE_AROUND_EQ_IN_RECORDS)
.aroundInside(ERL_OP_EQ, ERL_TYPED_EXPR).spaceIf(erlangSettings.SPACE_AROUND_EQ_IN_RECORDS)
.around(ERL_OP_EQ).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS)
.around(ERL_OP_LT_MINUS).spaceIf(erlangSettings.SPACE_AROUND_LEFT_ARROW)
.around(ERL_OP_EXL).spaceIf(erlangSettings.SPACE_AROUND_SEND)
.after(ERL_ARROW).spaceIf(erlangSettings.SPACE_AROUND_ARROW)
.before(ERL_CLAUSE_BODY).spaceIf(erlangSettings.SPACE_AROUND_ARROW)
.around(ERL_OP_PLUS).spaceIf(settings.SPACE_AROUND_ADDITIVE_OPERATORS)
.around(ERL_OP_PLUS_PLUS).spaceIf(settings.SPACE_AROUND_ADDITIVE_OPERATORS)
.aroundInside(ERL_OP_MINUS, ERL_ADDITIVE_EXPRESSION).spaceIf(settings.SPACE_AROUND_ADDITIVE_OPERATORS)
.aroundInside(ERL_OP_AR_DIV, ERL_MULTIPLICATIVE_EXPRESSION).spaceIf(settings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS)
.around(ERL_OP_AR_MUL).spaceIf(settings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS)
.around(ERL_OP_EQ_EQ).spaceIf(settings.SPACE_AROUND_EQUALITY_OPERATORS)
.around(ERL_OP_DIV_EQ).spaceIf(settings.SPACE_AROUND_EQUALITY_OPERATORS)
.around(ERL_OP_EQ_DIV_EQ).spaceIf(settings.SPACE_AROUND_EQUALITY_OPERATORS)
.around(ERL_OP_EQ_COL_EQ).spaceIf(settings.SPACE_AROUND_EQUALITY_OPERATORS)
.aroundInside(ERL_OP_OR, ERL_LIST_EXPRESSION).spaceIf(erlangSettings.SPACE_AROUND_OR_IN_LISTS)
.around(ERL_OP_LT).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_OP_EQ_LT).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_OP_GT).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_OP_GT_EQ).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_OR_OR).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_OR).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_ANDALSO).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.around(ERL_ORELSE).spaceIf(settings.SPACE_AROUND_LOGICAL_OPERATORS)
.after(ERL_BRACKET_LEFT).none()
.before(ERL_BRACKET_RIGHT).none()
.after(ERL_CURLY_LEFT).none()
.before(ERL_CURLY_RIGHT).none()
.after(ERL_BIN_START).none()
.before(ERL_BIN_END).none()
.before(ERL_ARGUMENT_DEFINITION_LIST).none()
.before(ERL_ARGUMENT_LIST).none()
.withinPair(ERL_PAR_LEFT, ERL_PAR_RIGHT).spaceIf(settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES)
.withinPair(ERL_BRACKET_LEFT, ERL_BRACKET_RIGHT).spaceIf(true)
.withinPair(ERL_CURLY_LEFT, ERL_CURLY_RIGHT).spaceIf(true)
.withinPair(ERL_BIN_START, ERL_BIN_END).spaceIf(true)
.beforeInside(rules, ERL_PAR_LEFT).none()
.around(keywords).spaces(1)
.before(ERL_FUN_TYPE_SIGS_BRACES).none()
.between(ERL_SPEC_FUN, ERL_TYPE_SIG).none()
.aroundInside(ERL_OP_AR_DIV, ERL_SPEC_FUN).none()
.beforeInside(ERL_PAR_LEFT, ERL_EXPORT).none()
.beforeInside(ERL_PAR_LEFT, ERL_EXPORT_TYPE_ATTRIBUTE).none()
.beforeInside(ERL_PAR_LEFT, ERL_INCLUDE).none()
.beforeInside(ERL_PAR_LEFT, ERL_RECORD_DEFINITION).none()
.beforeInside(ERL_PAR_LEFT, ERL_MODULE).none()
.beforeInside(ERL_PAR_LEFT, ERL_MACROS_DEFINITION).none()
.beforeInside(ERL_PAR_LEFT, ERL_BEHAVIOUR).none()
.beforeInside(ERL_TYPED_ATTR_VAL, ERL_ATOM_ATTRIBUTE).spaces(1)
.afterInside(ERL_Q_ATOM, ERL_ATOM_ATTRIBUTE).none()
.beforeInside(ERL_PAR_LEFT, ERL_SPECIFICATION).none()
.beforeInside(ERL_FUN_TYPE_SIGS, ERL_SPECIFICATION).spaces(1)
.beforeInside(ERL_PAR_LEFT, ERL_CALLBACK_SPEC).none()
.beforeInside(ERL_FUN_TYPE_SIGS, ERL_CALLBACK_SPEC).spaces(1)
.aroundInside(ERL_OP_AR_DIV, ERL_FUN_TYPE_SIGS).none()
.aroundInside(ERL_OP_AR_DIV, ERL_EXPORT_FUNCTION).none()
.aroundInside(ERL_OP_AR_DIV, ERL_EXPORT_TYPE).none()
.aroundInside(ERL_OP_AR_DIV, ERL_FUNCTION_WITH_ARITY).none()
.aroundInside(ERL_COLON_COLON, ERL_FUN_TYPE_SIGS).spaces(1)
.betweenInside(ERL_COLON_COLON, ERL_TYPE_SIG, ERL_FUN_TYPE_SIGS).spaces(1)
.between(ERL_FUN_TYPE_ARGUMENTS, ERL_TOP_TYPE_CLAUSE).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS)
.betweenInside(ERL_Q_ATOM, ERL_PAR_LEFT, ERL_TYPE).none()
.before(ERL_CLAUSE_GUARD).spaces(1)
.before(ERL_FUN_TYPE_SIGS).spaces(1)
.around(ERL_FUN_TYPE).spaces(1)
.around(ERL_TYPE_SIG).spaces(1)
.beforeInside(ERL_PAR_LEFT, ERL_FUN_TYPE).spaces(1)
.afterInside(ERL_PAR_RIGHT, ERL_FUN_TYPE).spaces(1)
.aroundInside(ERL_COLON, ERL_BIN_ELEMENT).none()
.aroundInside(ERL_COLON, ERL_BIT_TYPE).none()
.betweenInside(ERL_BIT_TYPE, ERL_OP_MINUS, ERL_OPT_BIT_TYPE_LIST).none()
.betweenInside(ERL_OP_MINUS, ERL_BIT_TYPE, ERL_OPT_BIT_TYPE_LIST).none()
.aroundInside(ERL_COLON, ERL_GLOBAL_FUNCTION_CALL_EXPRESSION).none()
.around(ERL_COLON_COLON).spaces(1)
.aroundInside(ERL_DOT, ERL_RECORD_FIELD).none()
.before(ERL_RECORD_FIELD).none()
.aroundInside(ERL_RADIX, ERL_RECORD_EXPRESSION).none()
.afterInside(ERL_RADIX, ERL_MAP_TUPLE).none()
.beforeInside(ERL_MAP_TUPLE, ERL_MAP_EXPRESSION).none()
.before(ERL_DOT).none()
.around(ERL_QMARK).none()
.before(ERL_RECORD_TUPLE).none()
.between(ERL_FUN, ERL_MODULE_REF).spaces(1)
.between(ERL_FUN, ERL_FUNCTION_WITH_ARITY).spaces(1)
.betweenInside(ERL_FUN, ERL_Q_VAR, ERL_FUN_EXPRESSION).spaces(1)
.betweenInside(ERL_FUN, ERL_MODULE_REF, ERL_FUN_EXPRESSION).spaces(1)
.between(ERL_MODULE_REF, ERL_COLON).none()
.between(ERL_COLON, ERL_FUNCTION_WITH_ARITY).none()
.between(ERL_COLON, ERL_FUNCTION_WITH_ARITY_VARIABLES).none()
.betweenInside(ERL_Q_VAR, ERL_COLON, ERL_FUN_EXPRESSION).none()
.between(ERL_FUN, ERL_FUN_CLAUSES).none()
.before(ERL_END).spaces(1)
.before(ERL_OPT_BIT_TYPE_LIST).none()
.betweenInside(ERL_OP_AR_DIV, ERL_BIT_TYPE, ERL_OPT_BIT_TYPE_LIST).none()
.afterInside(ERL_OP_MINUS, ERL_RECORD_DEFINITION).none()
.afterInside(ERL_OP_MINUS, ERL_TYPE_DEFINITION).none()
.afterInside(ERL_OP_MINUS, ERL_INCLUDE_LIB).none()
.afterInside(ERL_OP_MINUS, ERL_INCLUDE).none()
.afterInside(ERL_OP_MINUS, ERL_ATTRIBUTE).none()
;
}
@Override
public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) {
return null;
}
}