From 32d35778943db44376f1342d9e85c7ea14a06acb Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Thu, 18 Nov 2021 01:46:02 +0100
Subject: [PATCH] initial version of auto formatter

---
 .../jastadd/tooling/aspect/AspectBlock.java   | 112 ++++++++++++++++++
 .../aspect/AspectFormattingModelBuilder.java  |  29 +++++
 src/main/resources/META-INF/plugin.xml        |   2 +
 3 files changed, 143 insertions(+)
 create mode 100644 src/main/java/org/jastadd/tooling/aspect/AspectBlock.java
 create mode 100644 src/main/java/org/jastadd/tooling/aspect/AspectFormattingModelBuilder.java

diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectBlock.java b/src/main/java/org/jastadd/tooling/aspect/AspectBlock.java
new file mode 100644
index 0000000..694bcc4
--- /dev/null
+++ b/src/main/java/org/jastadd/tooling/aspect/AspectBlock.java
@@ -0,0 +1,112 @@
+package org.jastadd.tooling.aspect;
+
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.formatter.common.InjectedLanguageBlockBuilder;
+import com.intellij.psi.formatter.java.LeafBlock;
+import org.jastadd.tooling.aspect.psi.JastAddAspectAspectBody;
+import org.jastadd.tooling.aspect.psi.JastAddAspectAspectBodyDeclaration;
+import org.jastadd.tooling.aspect.psi.JastAddAspectBlock;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AspectBlock extends AbstractBlock {
+
+  private final SpacingBuilder spacingBuilder;
+  private final InjectedLanguageBlockBuilder myInjectedBlockBuilder;
+
+  protected AspectBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment,
+                        SpacingBuilder spacingBuilder) {
+    super(node, wrap, alignment);
+    this.spacingBuilder = spacingBuilder;
+
+    myInjectedBlockBuilder = new JavaBlockInjectedBlockBuilder();
+  }
+
+  @Override
+  protected List<Block> buildChildren() {
+    List<Block> blocks = new ArrayList<>();
+    if (myNode.getPsi() instanceof JastAddAspectBlock) {
+      myInjectedBlockBuilder.addInjectedBlocks(blocks, myNode, Wrap.createWrap(WrapType.NONE, false), null, Indent.getIndent(Indent.Type.NONE, false, true));
+    } else {
+      ASTNode child = myNode.getFirstChildNode();
+      while (child != null) {
+        if (child.getElementType() != TokenType.WHITE_SPACE) {
+          Block block = new AspectBlock(child, Wrap.createWrap(WrapType.NORMAL, false), null, spacingBuilder);
+          blocks.add(block);
+        }
+        child = child.getTreeNext();
+      }
+    }
+    return blocks;
+  }
+
+  @Override
+  public Indent getIndent() {
+
+    if (myNode.getPsi() instanceof JastAddAspectAspectBodyDeclaration) {
+      return Indent.getNormalIndent();
+    } else if (myNode.getPsi() instanceof JastAddAspectAspectBody) {
+      return Indent.getAbsoluteNoneIndent();
+    } else {
+      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;
+  }
+
+  private static class AroundBlockBlock extends LeafBlock {
+    private final TextRange myRange;
+
+    AroundBlockBlock(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, TextRange range) {
+      super(node, wrap, alignment, indent);
+      myRange = range;
+    }
+
+    @NotNull
+    @Override
+    public TextRange getTextRange() {
+      return myRange;
+    }
+  }
+
+  private static class JavaBlockInjectedBlockBuilder extends InjectedLanguageBlockBuilder {
+    @Override
+    public CodeStyleSettings getSettings() {
+      return CodeStyleSettings.getDefaults();
+    }
+
+    @Override
+    public boolean canProcessFragment(String text, ASTNode injectionHost) {
+      return true;
+    }
+
+    @Override
+    public Block createBlockBeforeInjection(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, TextRange range) {
+      return new AroundBlockBlock(node, wrap, alignment, indent, range);
+    }
+
+    @Override
+    public Block createBlockAfterInjection(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, TextRange range) {
+      return new AroundBlockBlock(node, wrap, alignment, Indent.getNoneIndent(), range);
+    }
+  }
+
+}
diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectFormattingModelBuilder.java b/src/main/java/org/jastadd/tooling/aspect/AspectFormattingModelBuilder.java
new file mode 100644
index 0000000..fa469ff
--- /dev/null
+++ b/src/main/java/org/jastadd/tooling/aspect/AspectFormattingModelBuilder.java
@@ -0,0 +1,29 @@
+package org.jastadd.tooling.aspect;
+
+import com.intellij.formatting.*;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import org.jastadd.tooling.aspect.psi.AspectTypes;
+import org.jetbrains.annotations.NotNull;
+
+public class AspectFormattingModelBuilder implements FormattingModelBuilder {
+
+  private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) {
+    return new SpacingBuilder(settings, Aspect.INSTANCE)
+      .before(AspectTypes.ASPECT).none()
+      .after(AspectTypes.ASPECT).spaces(1)
+      .after(AspectTypes.LBRACE).none();
+  }
+
+  @Override
+  public @NotNull FormattingModel createModel(@NotNull FormattingContext formattingContext) {
+    final CodeStyleSettings codeStyleSettings = formattingContext.getCodeStyleSettings();
+    return FormattingModelProvider
+      .createFormattingModelForPsiFile(formattingContext.getContainingFile(),
+        new AspectBlock(formattingContext.getNode(),
+          Wrap.createWrap(WrapType.NONE, false),
+          Alignment.createAlignment(),
+          createSpaceBuilder(codeStyleSettings)),
+        codeStyleSettings);
+  }
+
+}
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 5b1ae81..2cb82c0 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -79,6 +79,8 @@
         <annotator language="JAVA" implementationClass="org.jastadd.tooling.java.JavaMethodHighlighter"/>
 
         <colorSettingsPage implementation="org.jastadd.tooling.java.JavaColorSettingsPage"/>
+
+        <lang.formatter language="JastAddAspect" implementationClass="org.jastadd.tooling.aspect.AspectFormattingModelBuilder"/>
     </extensions>
 
     <actions>
-- 
GitLab