Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions gen/org/intellij/grammar/formatter/BnfFormattingModelBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package org.intellij.grammar.formatter;

import com.intellij.formatting.*;
import com.intellij.psi.formatter.common.AbstractBlock;
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.tree.IElementType;
import java.util.List;
import java.util.ArrayList;
import static org.intellij.grammar.psi.BnfTypes.*;

public class BnfFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
BnfFormattingBlock block = new BnfFormattingBlock(element.getNode(), null, null, settings);
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings);
}

@Override
public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) {
return null;
}

public static class BnfFormattingBlock extends AbstractBlock {
private final CodeStyleSettings mySettings;
public BnfFormattingBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, CodeStyleSettings settings) {
super(node, wrap, alignment);
mySettings = settings;
}

@Override
protected List<Block> buildChildren() {
if (isLeaf()) { return EMPTY; }
ArrayList<Block> children = new ArrayList<Block>();
Alignment baseAlignment = Alignment.createAlignment();
for (ASTNode childNode = getNode().getFirstChildNode(); childNode != null; childNode = childNode.getTreeNext()) {
if (FormatterUtil.containsWhiteSpacesOnly(childNode)) continue;
Block childBlock = new BnfFormattingBlock(childNode, createChildWrap(childNode), createChildAlignment(baseAlignment, childNode), mySettings);
children.add(childBlock);
}
return children;
}

public Wrap createChildWrap(ASTNode child) {
return null;
}

public Alignment createChildAlignment(Alignment baseAlignment, ASTNode child) {
IElementType elementType = child.getElementType();
ASTNode parent = child.getTreeParent();
IElementType parentType = parent != null ? parent.getElementType() : null;
if (parentType == BNF_ATTRS && elementType != BNF_LEFT_BRACE && elementType != BNF_RIGHT_BRACE) {
return baseAlignment;
}
if (parentType == BNF_CHOICE) {
return baseAlignment;
}
if (parentType == BNF_PAREN_EXPRESSION && elementType != BNF_LEFT_BRACE && elementType != BNF_RIGHT_BRACE) {
return baseAlignment;
}
return null;
}

@Override
public Indent getIndent() {
ASTNode node = getNode();
IElementType elementType = node.getElementType();
ASTNode parent = node.getTreeParent();
IElementType parentType = parent != null ? parent.getElementType() : null;
if (parentType == BNF_ATTRS && elementType == BNF_ATTR) {
return Indent.getNormalIndent();
}
if (parentType == BNF_CHOICE) {
return Indent.getContinuationIndent();
}
if (parentType == BNF_PAREN_EXPRESSION) {
return Indent.getContinuationIndent();
}
return Indent.getNoneIndent();
}

@Nullable
@Override
public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
SpacingBuilder spacingBuilder = new SpacingBuilder(mySettings)
.around(BNF_OP_EQ).none()
.around(BNF_OP_IS).spaces(1)
.around(BNF_OP_OR).spaces(1)
.before(BNF_OP_ONEMORE).none()
.before(BNF_OP_ZEROMORE).none()
.before(BNF_SEMICOLON).none()
.after(BNF_LEFT_BRACE).none()
.before(BNF_RIGHT_BRACE).none()
.after(BNF_LEFT_BRACKET).none()
.after(BNF_LEFT_PAREN).none()
.before(BNF_RIGHT_PAREN).none()
.after(BNF_EXTERNAL_START).none()
.before(BNF_EXTERNAL_END).none()
.around(BNF_RULE).none()
.after(BNF_MODIFIER).spaces(1)
.before(BNF_ATTRS).spaces(1)
.after(BNF_ATTR).spaces(1)
.around(BNF_EXPRESSION).spaces(1)
.after(BNF_QUANTIFIED).spaces(1)
.before(BNF_QUANTIFIER).none()
.after(BNF_PREDICATE_SIGN).none()
.around(BNF_EXTERNAL_EXPRESSION).spaces(1)
.around(BNF_REFERENCE_OR_TOKEN).spaces(1)
.around(BNF_LITERAL_EXPRESSION).spaces(1)
.around(BNF_STRING_LITERAL_EXPRESSION).spaces(1)
.around(BNF_PAREN_EXPRESSION).spaces(1)
.around(BNF_PAREN_OPT_EXPRESSION).spaces(1)
;
return spacingBuilder.getSpacing(this, child1, child2);
}

@Override
public boolean isLeaf() {
return false;
}
}
}
17 changes: 17 additions & 0 deletions grammars/Grammar.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@
line_comment="regexp://.*"
block_comment="regexp:/\*(.|\n)*\*/"
]

formattingBuilderClass="org.intellij.grammar.formatter.BnfFormattingModelBuilder"
around("::=|\|")="spaces(1)"
around("=|rule")="none()"
before("\*|\+|\)|\;|\}|>>")="none()"
after("\(|\[|\{|predicate_sign|<<")="none()"
after("quantified|attr|modifier")="spaces(1)"
before("quantifier")="none()"
before("attrs")="spaces(1)"
around(".*expression|reference_or_token")="spaces(1)"

normalIndent("attrs")="attr"
continuationIndent("paren_expression")=".*"
continuationIndent("choice")=".*"

alignment("choice")=".*"
alignment("attrs|paren_expression")="except:\{|\}"

implements("rule|attr")="org.intellij.grammar.psi.BnfNamedElement"
extends("rule|attr")="org.intellij.grammar.psi.impl.BnfNamedElementImpl"
Expand Down
2 changes: 2 additions & 0 deletions support/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@

<documentationProvider implementation="org.intellij.grammar.BnfDocumentationProvider"/>

<lang.formatter language="BNF" implementationClass="org.intellij.grammar.formatter.BnfFormattingModelBuilder"/>

<localInspection language="BNF" shortName="BnfSuspiciousTokenInspection" displayName="Suspicious token" groupName="Grammar Inspections"
enabledByDefault="true" level="WARNING" implementationClass="org.intellij.grammar.inspection.BnfSuspiciousTokenInspection"/>
<localInspection language="BNF" shortName="BnfLeftRecursionInspection" displayName="Left recursion" groupName="Grammar Inspections"
Expand Down
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/after.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Represents <strong>after</strong> rule in SpacingBuilder.
</body>
</html>
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/alignment.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Allows to control formatter <strong>alignment</strong> for children nodes.
</body>
</html>
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/around.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Represents <strong>around</strong> rule in SpacingBuilder.
</body>
</html>
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/before.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Represents <strong>before</strong> rule in SpacingBuilder.
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Allows to control formatter <strong>continuation indent</strong> for children nodes.
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
FormattingModelBuilder class qualified name.
</body>
</html>
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/noneIndent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Allows to control formatter <strong>none indent</strong> for children nodes.
</body>
</html>
5 changes: 5 additions & 0 deletions support/messages/attributeDescriptions/normalIndent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Allows to control formatter <strong>normal indent</strong> for children nodes.
</body>
</html>
12 changes: 12 additions & 0 deletions support/org/intellij/grammar/KnownAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ public class KnownAttribute<T> {
public static final KnownAttribute<String> RECOVER_WHILE = create(false, String.class, "recoverWhile", null);
public static final KnownAttribute<String> NAME = create(false, String.class, "name", null);

public static final KnownAttribute<String> FORMATTING_BUILDER_CLASS = create(true, String.class, "formattingBuilderClass", null);

public static final KnownAttribute<String> AROUND = create(false, String.class, "around", null);
public static final KnownAttribute<String> BEFORE = create(false, String.class, "before", null);
public static final KnownAttribute<String> AFTER = create(false, String.class, "after", null);

public static final KnownAttribute<String> CONTINUATION_INDENT = create(false, String.class, "continuationIndent", null);
public static final KnownAttribute<String> NONE_INDENT = create(false, String.class, "noneIndent", null);
public static final KnownAttribute<String> NORMAL_INDENT = create(false, String.class, "normalIndent", null);

public static final KnownAttribute<String> ALIGNMENT = create(false, String.class, "alignment", null);

public static final KnownAttribute<Boolean> RIGHT_ASSOCIATIVE = create(false, Boolean.class, "rightAssociative", false);
public static final KnownAttribute<String> CONSUME_TOKEN_METHOD = create(false, String.class, "consumeTokenMethod", "consumeToken");

Expand Down
Loading