diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarBlock.java b/src/main/java/org/jastadd/tooling/RelAstGrammarBlock.java new file mode 100644 index 0000000000000000000000000000000000000000..7aca9c69078cb3d4426a34cb79a3f0bb9294bd76 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarBlock.java @@ -0,0 +1,55 @@ +package org.jastadd.tooling; + + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.TokenType; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class RelAstGrammarBlock extends AbstractBlock { + + private final SpacingBuilder spacingBuilder; + + protected RelAstGrammarBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, + SpacingBuilder spacingBuilder) { + super(node, wrap, alignment); + this.spacingBuilder = spacingBuilder; + } + + @Override + protected List<Block> buildChildren() { + List<Block> blocks = new ArrayList<>(); + ASTNode child = myNode.getFirstChildNode(); + while (child != null) { + if (child.getElementType() != TokenType.WHITE_SPACE) { + Block block = new RelAstGrammarBlock(child, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(), + spacingBuilder); + blocks.add(block); + } + child = child.getTreeNext(); + } + return blocks; + } + + @Override + public Indent getIndent() { + return Indent.getNoneIndent(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return spacingBuilder.getSpacing(this, child1, child2); + } + + @Override + public boolean isLeaf() { + return myNode.getFirstChildNode() == null; + } + +} diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarFormattingModelBuilder.java b/src/main/java/org/jastadd/tooling/RelAstGrammarFormattingModelBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..fc3a2efafb363b222d9c6fb24f10e9853599d2e9 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarFormattingModelBuilder.java @@ -0,0 +1,59 @@ +package org.jastadd.tooling; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +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.jastadd.tooling.parser.RelAstGrammarTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class RelAstGrammarFormattingModelBuilder implements FormattingModelBuilder { + + private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) { + final CommonCodeStyleSettings commonSettings = settings.getCommonSettings(RelAstGrammar.INSTANCE.getID()); + + final TokenSet roleMultiplicityTokens = TokenSet.create(RelAstGrammarTypes.STAR, RelAstGrammarTypes.QUESTION_MARK); + final TokenSet relationDirectionTokens = TokenSet.create(RelAstGrammarTypes.LEFT, RelAstGrammarTypes.RIGHT, RelAstGrammarTypes.BIDIRECTIONAL); + final TokenSet declarationTokens = TokenSet.create(RelAstGrammarTypes.TYPE_DECL, RelAstGrammarTypes.RELATION); + + return new SpacingBuilder(settings, RelAstGrammar.INSTANCE) + .around(RelAstGrammarTypes.ASSIGN).spaceIf(commonSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS) + .before(declarationTokens).none() + .before(RelAstGrammarTypes.SCOL).spaceIf(commonSettings.SPACE_BEFORE_SEMICOLON) + .around(relationDirectionTokens).spaceIf(commonSettings.SPACE_AROUND_RELATIONAL_OPERATORS) + .between(RelAstGrammarTypes.COMPONENT, RelAstGrammarTypes.COMPONENT).spaces(1) + .around(RelAstGrammarTypes.DOT).none() + .before(roleMultiplicityTokens).spaceIf(commonSettings.SPACE_AROUND_UNARY_OPERATOR) + .beforeInside(RelAstGrammarTypes.COL, RelAstGrammarTypes.TYPE_DECL).spaceIf(commonSettings.SPACE_BEFORE_COLON) + .afterInside(RelAstGrammarTypes.COL, RelAstGrammarTypes.TYPE_DECL).spaceIf(commonSettings.SPACE_AFTER_COLON) + .aroundInside(RelAstGrammarTypes.COL, RelAstGrammarTypes.COMPONENT).none() + .withinPair(RelAstGrammarTypes.LT, RelAstGrammarTypes.GT).spaceIf(commonSettings.SPACE_WITHIN_CAST_PARENTHESES) + .withinPair(RelAstGrammarTypes.LBRACKET, RelAstGrammarTypes.RBRACKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) + .between(declarationTokens, RelAstGrammarTypes.COMMENT).spaces(1) + .afterInside(RelAstGrammarTypes.SLASH, RelAstGrammarTypes.NTA_COMPONENT).none() + .beforeInside(RelAstGrammarTypes.SLASH, RelAstGrammarTypes.NTA_COMPONENT).none(); + } + + @NotNull + @Override + public FormattingModel createModel(FormattingContext context) { + return FormattingModelProvider + .createFormattingModelForPsiFile(context.getPsiElement().getContainingFile(), + new RelAstGrammarBlock(context.getPsiElement().getNode(), + Wrap.createWrap(WrapType.NONE, false), + Alignment.createAlignment(), + createSpaceBuilder(context.getCodeStyleSettings())), + context.getCodeStyleSettings()); + } + + @Nullable + @Override + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { + return null; + } + +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 29eb7921f9f6a73367c02f9b3c68a98271a4911a..f591fa9116d3d4208895a73a5922b1ceff5ef111 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -45,6 +45,9 @@ <lang.psiStructureViewFactory language="JastAddGrammar" implementationClass="org.jastadd.tooling.RelAstGrammarStructureViewFactory"/> + + <lang.formatter language="JastAddGrammar" + implementationClass="org.jastadd.tooling.RelAstGrammarFormattingModelBuilder"/> </extensions> <actions>