/*
* Copyright 2013-2017 consulo.io
*
* 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 consulo.csharp.lang.formatter.processors;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import consulo.csharp.ide.codeStyle.CSharpCodeStyleSettings;
import consulo.csharp.lang.doc.psi.CSharpDocTokenType;
import consulo.csharp.lang.formatter.CSharpFormattingBlock;
import consulo.csharp.lang.psi.CSharpElements;
import consulo.csharp.lang.psi.CSharpStubElements;
import consulo.csharp.lang.psi.CSharpTokenSets;
import consulo.csharp.lang.psi.CSharpTokens;
import consulo.csharp.lang.psi.impl.source.CSharpOperatorReferenceImpl;
import com.intellij.formatting.ASTBlock;
import com.intellij.formatting.Spacing;
import com.intellij.formatting.SpacingBuilder;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtilCore;
/**
* @author VISTALL
* @since 11.11.14
*/
public class CSharpSpacingProcessor implements CSharpTokens, CSharpElements
{
private static class OperatorReferenceSpacingBuilder
{
private final CommonCodeStyleSettings myCommonSettings;
private TokenSet myParentSet;
private final TokenSet myTokenSet;
private final boolean myCondition;
OperatorReferenceSpacingBuilder(CommonCodeStyleSettings commonSettings, @NotNull TokenSet parentSet, IElementType[] types, boolean condition)
{
myCommonSettings = commonSettings;
myParentSet = parentSet;
myTokenSet = TokenSet.create(types);
myCondition = condition;
}
public boolean match(@Nullable ASTBlock child1, @NotNull ASTBlock child2)
{
CSharpOperatorReferenceImpl operatorReference = findOperatorReference(child1, child2);
if(operatorReference != null && myParentSet != TokenSet.EMPTY)
{
IElementType elementType = PsiUtilCore.getElementType(operatorReference.getParent());
if(!myParentSet.contains(elementType))
{
return false;
}
}
return operatorReference != null && myTokenSet.contains(operatorReference.getOperatorElementType());
}
@Nullable
private static CSharpOperatorReferenceImpl findOperatorReference(@Nullable ASTBlock child1, @NotNull ASTBlock child2)
{
if(child1 != null)
{
PsiElement psi = child1.getNode().getPsi();
if(psi instanceof CSharpOperatorReferenceImpl)
{
return (CSharpOperatorReferenceImpl) psi;
}
}
PsiElement psi = child2.getNode().getPsi();
if(psi instanceof CSharpOperatorReferenceImpl)
{
return (CSharpOperatorReferenceImpl) psi;
}
return null;
}
@NotNull
public Spacing createSpacing()
{
int count = myCondition ? 1 : 0;
return Spacing.createSpacing(count, count, 0, myCommonSettings.KEEP_LINE_BREAKS, myCommonSettings.KEEP_BLANK_LINES_IN_CODE);
}
}
private static TokenSet ourMultiDeclarationSet = TokenSet.create(CSharpStubElements.FIELD_DECLARATION, CSharpElements.LOCAL_VARIABLE, CSharpStubElements.EVENT_DECLARATION);
private final CSharpFormattingBlock myParent;
private final CommonCodeStyleSettings myCommonSettings;
private SpacingBuilder myBuilder;
private List<OperatorReferenceSpacingBuilder> myOperatorReferenceSpacingBuilders = new ArrayList<OperatorReferenceSpacingBuilder>();
public CSharpSpacingProcessor(CSharpFormattingBlock parent, CommonCodeStyleSettings commonSettings, CSharpCodeStyleSettings customSettings)
{
myParent = parent;
myCommonSettings = commonSettings;
myBuilder = new SpacingBuilder(commonSettings);
myBuilder.between(CSharpTokens.IF_KEYWORD, CSharpTokens.LPAR).spaceIf(commonSettings.SPACE_BEFORE_IF_PARENTHESES);
myBuilder.between(CSharpTokens.FOR_KEYWORD, CSharpTokens.LPAR).spaceIf(commonSettings.SPACE_BEFORE_FOR_PARENTHESES);
myBuilder.between(CSharpTokens.FOREACH_KEYWORD, CSharpTokens.LPAR).spaceIf(customSettings.SPACE_BEFORE_FOREACH_PARENTHESES);
myBuilder.between(CSharpTokens.WHILE_KEYWORD, CSharpTokens.LPAR).spaceIf(commonSettings.SPACE_BEFORE_WHILE_PARENTHESES);
myBuilder.between(CSharpTokens.SWITCH_KEYWORD, CSharpTokens.LPAR).spaceIf(commonSettings.SPACE_BEFORE_SWITCH_PARENTHESES);
myBuilder.between(CSharpTokens.CATCH_KEYWORD, CSharpTokens.LPAR).spaceIf(commonSettings.SPACE_BEFORE_CATCH_PARENTHESES);
myBuilder.between(CSharpTokens.USING_KEYWORD, CSharpTokens.LPAR).spaceIf(customSettings.SPACE_BEFORE_USING_PARENTHESES);
myBuilder.between(CSharpTokens.LOCK_KEYWORD, CSharpTokens.LPAR).spaceIf(customSettings.SPACE_BEFORE_LOCK_PARENTHESES);
myBuilder.between(CSharpTokens.FIXED_KEYWORD, CSharpTokens.LPAR).spaceIf(customSettings.SPACE_BEFORE_FIXED_PARENTHESES);
IElementType[] arrayInitializerElementsTypes = {
CSharpElements.ARRAY_INITIALIZER,
CSharpElements.IMPLICIT_ARRAY_INITIALIZATION_EXPRESSION,
CSharpElements.ARRAY_INITIALIZER_COMPOSITE_VALUE
};
//myBuilder.afterInside(CSharpTokens.LBRACE, CSharpElements.ARRAY_INITIALIZER).none();
//myBuilder.afterInside(CSharpTokens.LBRACE, CSharpElements.IMPLICIT_ARRAY_INITIALIZATION_EXPRESSION).none();
//myBuilder.afterInside(CSharpTokens.LBRACE, CSharpElements.ARRAY_INITIALIZER_COMPOSITE_VALUE).none();
//myBuilder.beforeInside(CSharpTokens.RBRACE, CSharpElements.ARRAY_INITIALIZER).none();
//myBuilder.beforeInside(CSharpTokens.RBRACE, CSharpElements.IMPLICIT_ARRAY_INITIALIZATION_EXPRESSION).none();
//myBuilder.beforeInside(CSharpTokens.RBRACE, CSharpElements.ARRAY_INITIALIZER_COMPOSITE_VALUE).none();
for(IElementType arrayInitializerElementsType : arrayInitializerElementsTypes)
{
myBuilder.betweenInside(CSharpTokens.COMMA, CSharpElements.ARRAY_INITIALIZER_SINGLE_VALUE, arrayInitializerElementsType).spaces(1);
myBuilder.betweenInside(CSharpTokens.COMMA, CSharpElements.ARRAY_INITIALIZER_COMPOSITE_VALUE, arrayInitializerElementsType).spaces(1);
}
spaceIfNoBlankLines(myBuilder.beforeInside(LBRACE, TYPE_DECLARATION), commonSettings.SPACE_BEFORE_CLASS_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(LBRACE, PROPERTY_DECLARATION), customSettings.SPACE_BEFORE_PROPERTY_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(LBRACE, EVENT_DECLARATION), customSettings.SPACE_BEFORE_EVENT_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(LBRACE, ARRAY_METHOD_DECLARATION), customSettings.SPACE_BEFORE_INDEX_METHOD_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(LBRACE, NAMESPACE_DECLARATION), customSettings.SPACE_BEFORE_NAMESPACE_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, METHOD_DECLARATION), commonSettings.SPACE_BEFORE_METHOD_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, CONSTRUCTOR_DECLARATION), commonSettings.SPACE_BEFORE_METHOD_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, CONVERSION_METHOD_DECLARATION), commonSettings.SPACE_BEFORE_METHOD_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, XXX_ACCESSOR), commonSettings.SPACE_BEFORE_METHOD_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, SWITCH_STATEMENT), commonSettings.SPACE_BEFORE_SWITCH_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, FOR_STATEMENT), commonSettings.SPACE_BEFORE_FOR_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, FOREACH_STATEMENT), customSettings.SPACE_BEFORE_FOREACH_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, WHILE_STATEMENT), commonSettings.SPACE_BEFORE_WHILE_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, TRY_STATEMENT), commonSettings.SPACE_BEFORE_TRY_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, CATCH_STATEMENT), commonSettings.SPACE_BEFORE_CATCH_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, FINALLY_STATEMENT), commonSettings.SPACE_BEFORE_FINALLY_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, UNSAFE_STATEMENT), customSettings.SPACE_BEFORE_UNSAFE_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, USING_STATEMENT), customSettings.SPACE_BEFORE_USING_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, LOCK_STATEMENT), customSettings.SPACE_BEFORE_LOCK_LBRACE);
spaceIfNoBlankLines(myBuilder.beforeInside(BLOCK_STATEMENT, FIXED_STATEMENT), customSettings.SPACE_BEFORE_FIXED_LBRACE);
if(customSettings.KEEP_AUTO_PROPERTY_IN_ONE_LINE)
{
spaceIfNoBlankLines(myBuilder.afterInside(LBRACE, PROPERTY_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.afterInside(LBRACE, EVENT_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.afterInside(LBRACE, ARRAY_METHOD_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.between(XXX_ACCESSOR, XXX_ACCESSOR), true);
spaceIfNoBlankLines(myBuilder.beforeInside(RBRACE, PROPERTY_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.beforeInside(RBRACE, EVENT_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.beforeInside(RBRACE, ARRAY_METHOD_DECLARATION), true);
}
// between members - one line
myBuilder.between(CSharpStubElements.FIELD_DECLARATION, CSharpStubElements.FIELD_DECLARATION).blankLines(commonSettings.BLANK_LINES_AROUND_FIELD);
myBuilder.between(CSharpStubElements.QUALIFIED_MEMBERS, CSharpStubElements.QUALIFIED_MEMBERS).blankLines(commonSettings.BLANK_LINES_AROUND_METHOD);
myBuilder.afterInside(CSharpTokens.LBRACE, CSharpStubElements.QUALIFIED_MEMBERS).spacing(0, 0, 1, commonSettings.KEEP_LINE_BREAKS, commonSettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
myBuilder.beforeInside(CSharpTokens.RBRACE, CSharpStubElements.QUALIFIED_MEMBERS).spacing(0, 0, 1, commonSettings.KEEP_LINE_BREAKS, commonSettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
myBuilder.afterInside(CSharpTokens.LBRACE, CSharpElements.BLOCK_STATEMENT).spacing(0, 0, 1, commonSettings.KEEP_LINE_BREAKS, commonSettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
myBuilder.beforeInside(CSharpTokens.RBRACE, CSharpElements.BLOCK_STATEMENT).spacing(0, 0, 1, commonSettings.KEEP_LINE_BREAKS, commonSettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
// call(arg
myBuilder.afterInside(CSharpTokens.LPAR, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES);
// call[arg
myBuilder.afterInside(CSharpTokens.LBRACKET, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS);
// arg)
myBuilder.beforeInside(CSharpTokens.RPAR, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES);
// arg]
myBuilder.beforeInside(CSharpTokens.RBRACKET, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS);
// arg, arg
myBuilder.afterInside(CSharpTokens.COMMA, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_AFTER_COMMA);
myBuilder.beforeInside(CSharpTokens.COMMA, CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_BEFORE_COMMA);
// call(
myBuilder.before(CSharpElements.CALL_ARGUMENT_LIST).spaceIf(commonSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
IElementType[] iElementTypes = {
CSharpElements.TYPE_OF_EXPRESSION,
CSharpElements.DEFAULT_EXPRESSION,
CSharpElements.NAMEOF_EXPRESSION,
CSharpElements.__MAKEREF_EXPRESSION,
CSharpElements.__REFTYPE_EXPRESSION,
CSharpElements.__REFVALUE_EXPRESSION,
CSharpElements.SIZE_OF_EXPRESSION
};
for(IElementType elementType : iElementTypes)
{
myBuilder.afterInside(CSharpTokens.LPAR, elementType).spaces(0);
myBuilder.beforeInside(CSharpTokens.RPAR, elementType).spaces(0);
}
myBuilder.before(CSharpElements.PARAMETER_LIST).none();
myBuilder.before(CSharpStubElements.PARAMETER_LIST).none();
// (Type
myBuilder.afterInside(CSharpTokens.LPAR, CSharpStubElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
myBuilder.afterInside(CSharpTokens.LPAR, CSharpElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
myBuilder.afterInside(CSharpTokens.LPAR, CSharpElements.LAMBDA_PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
// , type CSharpTokens.IDENTIFIER)
myBuilder.afterInside(CSharpTokens.COMMA, CSharpStubElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_AFTER_COMMA);
myBuilder.afterInside(CSharpTokens.COMMA, CSharpElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_AFTER_COMMA);
myBuilder.afterInside(CSharpTokens.COMMA, CSharpElements.LAMBDA_PARAMETER_LIST).spaceIf(commonSettings.SPACE_AFTER_COMMA);
myBuilder.beforeInside(CSharpTokens.COMMA, CSharpStubElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_COMMA);
myBuilder.beforeInside(CSharpTokens.COMMA, CSharpElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_COMMA);
myBuilder.beforeInside(CSharpTokens.COMMA, CSharpElements.LAMBDA_PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_COMMA);
// name)
myBuilder.beforeInside(CSharpTokens.RPAR, CSharpStubElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
myBuilder.beforeInside(CSharpTokens.RPAR, CSharpElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
myBuilder.beforeInside(CSharpTokens.RPAR, CSharpElements.LAMBDA_PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES);
// <Type
myBuilder.afterInside(CSharpTokens.LT, CSharpElements.TYPE_ARGUMENTS).none();
myBuilder.afterInside(CSharpTokens.LT, CSharpStubElements.TYPE_ARGUMENTS).none();
// <Type, Type
myBuilder.afterInside(CSharpTokens.COMMA, CSharpElements.TYPE_ARGUMENTS).spaceIf(commonSettings.SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS);
myBuilder.afterInside(CSharpTokens.COMMA, CSharpStubElements.TYPE_ARGUMENTS).spaceIf(commonSettings.SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS);
// Type>
myBuilder.beforeInside(CSharpTokens.GT, CSharpElements.TYPE_ARGUMENTS).none();
myBuilder.beforeInside(CSharpTokens.GT, CSharpStubElements.TYPE_ARGUMENTS).none();
// <modifier-list> <type>
myBuilder.between(CSharpStubElements.MODIFIER_LIST, CSharpStubElements.TYPE_SET).spaces(1);
// <modifier> <modifier>
myBuilder.between(CSharpTokenSets.MODIFIERS, CSharpTokenSets.MODIFIERS).spaces(1);
// [Att]
// [Att]
myBuilder.between(CSharpStubElements.ATTRIBUTE_LIST, CSharpStubElements.ATTRIBUTE_LIST).blankLines(0);
// [Att]
// <modifier>
myBuilder.between(CSharpStubElements.ATTRIBUTE_LIST, CSharpTokenSets.MODIFIERS).blankLines(0);
// name(parameterList)
myBuilder.between(CSharpTokens.IDENTIFIER, CSharpStubElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_METHOD_PARENTHESES);
// delegate(parameterList)
myBuilder.between(CSharpTokens.DELEGATE_KEYWORD, CSharpElements.PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_METHOD_PARENTHESES);
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, TYPE_DECLARATION).spaces(1);
myBuilder.beforeInside(CSharpTokens.IDENTIFIER, LOCAL_VARIABLE).spaces(1);
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, FIELD_DECLARATION).spaces(1);
myBuilder.betweenInside(CSharpTokens.DOT, CSharpTokens.IDENTIFIER, EVENT_DECLARATION).none();
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, EVENT_DECLARATION).spaces(1);
myBuilder.betweenInside(CSharpTokens.DOT, CSharpTokens.IDENTIFIER, PROPERTY_DECLARATION).none();
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, PROPERTY_DECLARATION).spaces(1);
myBuilder.betweenInside(CSharpTokens.DOT, CSharpTokens.IDENTIFIER, METHOD_DECLARATION).none();
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, METHOD_DECLARATION).spaces(1);
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, CONSTRUCTOR_DECLARATION).spaces(1);
myBuilder.betweenInside(CSharpTokens.DOT, CSharpTokens.THIS_KEYWORD, ARRAY_METHOD_DECLARATION).none();
myBuilder.beforeInside(CSharpTokens.THIS_KEYWORD, ARRAY_METHOD_DECLARATION).spaces(1);
myBuilder.beforeInside(CSharpTokens.IDENTIFIER, CSharpElements.PARAMETER).spaces(1);
myBuilder.beforeInside(CSharpTokens.IDENTIFIER, CSharpStubElements.PARAMETER).spaces(1);
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, CSharpElements.PARAMETER).spaces(1);
myBuilder.beforeInside(CSharpStubElements.IDENTIFIER, CSharpStubElements.PARAMETER).spaces(1);
spaceIfNoBlankLines(myBuilder.afterInside(COLON, CSharpStubElements.EXTENDS_LIST), true);
spaceIfNoBlankLines(myBuilder.before(CSharpStubElements.EXTENDS_LIST), true);
// constructor declaration
spaceIfNoBlankLines(myBuilder.afterInside(COLON, CSharpStubElements.CONSTRUCTOR_DECLARATION), true);
spaceIfNoBlankLines(myBuilder.beforeInside(COLON, CSharpStubElements.CONSTRUCTOR_DECLARATION), true);
myBuilder.around(COLONCOLON).none();
myBuilder.aroundInside(COLON, CSharpElements.GENERIC_CONSTRAINT).spaces(1);
myBuilder.around(DARROW).spaceIf(commonSettings.SPACE_AROUND_LAMBDA_ARROW);
myBuilder.around(ARROW).none();
myBuilder.before(CSharpTokens.ELSE_KEYWORD).spaceIf(commonSettings.SPACE_BEFORE_ELSE_KEYWORD);
myBuilder.betweenInside(CSharpTokens.ELSE_KEYWORD, CSharpElements.BLOCK_STATEMENT, CSharpElements.IF_STATEMENT).spaceIf(commonSettings.SPACE_BEFORE_ELSE_LBRACE);
// need be after else declaration
myBuilder.beforeInside(BLOCK_STATEMENT, IF_STATEMENT).spaceIf(commonSettings.SPACE_BEFORE_IF_LBRACE);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_EQUALITY_OPERATORS, CSharpTokens.EQEQ, CSharpTokens.NTEQ);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_LOGICAL_OPERATORS, CSharpTokens.ANDAND, CSharpTokens.OROR);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_RELATIONAL_OPERATORS, CSharpTokens.LT, CSharpTokens.GT, CSharpTokens.LTEQ, CSharpTokens.GTEQ);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS, CSharpTokens.EQ, CSharpTokens.PLUSEQ, CSharpTokens.MINUSEQ, CSharpTokens.MULEQ, CSharpTokens.DIVEQ,
CSharpTokens.PERCEQ);
// field, local var, etc initialization
myBuilder.around(CSharpTokens.EQ).spaceIf(commonSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_SHIFT_OPERATORS, CSharpTokens.GTGT, CSharpTokens.GTGTEQ, CSharpTokens.LTLT, CSharpTokens.LTLTEQ);
operatorReferenceSpacingWithParent(commonSettings.SPACE_AROUND_UNARY_OPERATOR, TokenSet.create(POSTFIX_EXPRESSION, PREFIX_EXPRESSION), CSharpTokens.PLUS, CSharpTokens.MINUS,
CSharpTokens.PLUSPLUS, CSharpTokens.MINUSMINUS, CSharpTokens.MUL, CSharpTokens.AND);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_ADDITIVE_OPERATORS, CSharpTokens.PLUS, CSharpTokens.MINUS);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS, CSharpTokens.MUL, CSharpTokens.DIV, CSharpTokens.PERC);
operatorReferenceSpacing(commonSettings.SPACE_AROUND_BITWISE_OPERATORS, CSharpTokens.XOR, CSharpTokens.AND, CSharpTokens.OR);
// doc
myBuilder.after(CSharpDocTokenType.DOC_LINE_START).spacing(1, 1, 0, true, 0);
// semicolons
// special hacks for 'for()'
myBuilder.betweenInside(CSharpTokens.LPAR, CSharpTokens.SEMICOLON, CSharpElements.FOR_STATEMENT).spaces(0);
myBuilder.betweenInside(CSharpTokens.SEMICOLON, CSharpTokens.RPAR, CSharpElements.FOR_STATEMENT).spaces(0);
myBuilder.betweenInside(CSharpTokens.SEMICOLON, CSharpTokens.SEMICOLON, CSharpElements.FOR_STATEMENT).spaces(0);
myBuilder.beforeInside(CSharpTokens.SEMICOLON, CSharpElements.FOR_STATEMENT).spaceIf(commonSettings.SPACE_BEFORE_SEMICOLON);
myBuilder.afterInside(CSharpTokens.SEMICOLON, CSharpElements.FOR_STATEMENT).spaceIf(commonSettings.SPACE_AFTER_SEMICOLON);
myBuilder.before(CSharpTokens.SEMICOLON).spaces(0);
}
private void spaceIfNoBlankLines(SpacingBuilder.RuleBuilder builder, boolean config)
{
int count = config ? 1 : 0;
builder.spacing(count, count, 0, false, 0);
}
public void operatorReferenceSpacing(boolean ifCondition, IElementType... types)
{
operatorReferenceSpacingWithParent(ifCondition, TokenSet.EMPTY, types);
}
public void operatorReferenceSpacingWithParent(boolean ifCondition, @NotNull TokenSet parents, IElementType... types)
{
myOperatorReferenceSpacingBuilders.add(new OperatorReferenceSpacingBuilder(myCommonSettings, parents, types, ifCondition));
}
@Nullable
public Spacing getSpacing(@Nullable ASTBlock child1, @NotNull ASTBlock child2)
{
for(OperatorReferenceSpacingBuilder operatorReferenceSpacingBuilder : myOperatorReferenceSpacingBuilders)
{
if(operatorReferenceSpacingBuilder.match(child1, child2))
{
return operatorReferenceSpacingBuilder.createSpacing();
}
}
IElementType elementType1 = PsiUtilCore.getElementType(child1 == null ? null : child1.getNode());
IElementType elementType2 = PsiUtilCore.getElementType(child2.getNode());
if(ourMultiDeclarationSet.contains(elementType1) && elementType1 == elementType2)
{
ASTNode commaNode = child1.getNode().findChildByType(CSharpTokens.COMMA);
if(commaNode != null)
{
return Spacing.createSpacing(1, 1, 0, false, 0);
}
}
return myBuilder.getSpacing(myParent, child1, child2);
}
}