From 9ac29e9ca9cf2a894891ce6163192de126965e8a Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 17 Apr 2016 21:11:11 +0300 Subject: [PATCH 01/14] Add formatter --- build.gradle | 12 +-- gradle.properties | 2 +- .../plugin/ProtoParserDefinition.java | 29 +++---- .../plugin/formatter/BlockFactory.java | 60 +++++++++++++++ .../plugin/formatter/CommentBlock.java | 42 +++++++++++ .../jetbrains/plugin/formatter/EnumBlock.java | 42 +++++++++++ .../plugin/formatter/ExtendBlock.java | 42 +++++++++++ .../plugin/formatter/GenericBlock.java | 42 +++++++++++ .../plugin/formatter/ImportBlock.java | 42 +++++++++++ .../plugin/formatter/LineCommentBlock.java | 42 +++++++++++ .../plugin/formatter/MessageBlock.java | 42 +++++++++++ .../plugin/formatter/OptionBlock.java | 42 +++++++++++ .../plugin/formatter/PackageBlock.java | 42 +++++++++++ .../plugin/formatter/ProtoFileBlock.java | 75 +++++++++++++++++++ .../formatter/ProtoFormatterModelBuilder.java | 35 +++++++++ .../plugin/formatter/ServiceBlock.java | 42 +++++++++++ .../plugin/formatter/SyntaxBlock.java | 42 +++++++++++ .../plugin/psi/ProtoRootStatementNode.java | 16 ---- .../view/structure/RootTreeElement.java | 28 +++---- src/main/resources/META-INF/plugin.xml | 3 + 20 files changed, 670 insertions(+), 52 deletions(-) create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoRootStatementNode.java diff --git a/build.gradle b/build.gradle index d7ded81..6a02883 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { plugins { id "org.jetbrains.intellij" version "0.0.43" - id "com.jfrog.bintray" version "1.6" +// id "com.jfrog.bintray" version "1.6" } group = 'org.antlr' @@ -26,8 +26,8 @@ apply plugin: 'antlr' dependencies { compile 'org.antlr:antlr4-runtime:4.5.1' compile 'org.antlr:antlr4-jetbrains-adapter:1.0.0' - antlr 'org.antlr:antlr4:4.5' - compile 'io.protostuff:protostuff-parser:2.0.0-alpha12' +// antlr 'org.antlr:antlr4:4.5' + compile 'io.protostuff:protostuff-parser:2.0.0-alpha13-SNAPSHOT' } apply plugin: 'idea' @@ -36,9 +36,9 @@ idea { jdkName = javaVersion languageLevel = javaVersion } - module { - generatedSourceDirs += file('gen') - } +// module { +// generatedSourceDirs += file('gen') +// } } apply plugin: 'org.jetbrains.intellij' diff --git a/gradle.properties b/gradle.properties index b138b3d..8b41ae5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Available idea versions: # https://www.jetbrains.com/intellij-repository/releases # https://www.jetbrains.com/intellij-repository/snapshots -version=0.2.0 +version=0.3.0-SNAPSHOT ideaVersion=145.258.11 # https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under # Java 8 is required to run IntelliJ IDEA starting from version 16 diff --git a/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java b/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java index e78c8b6..59ff18c 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java @@ -46,6 +46,7 @@ public class ProtoParserDefinition implements ParserDefinition { public static final TokenIElementType RSQUARE; public static final TokenIElementType LT; public static final TokenIElementType GT; + public static final TokenIElementType ASSIGN; // Rules public static final IElementType R_TYPE_REFERENCE; @@ -53,16 +54,17 @@ public class ProtoParserDefinition implements ParserDefinition { public static final IElementType R_FIELD_MODIFIER; private static final IFileElementType FILE; private static final TokenSet COMMENTS; - private static final TokenSet WHITESPACE; - private static final TokenSet STRING; + public static final TokenSet WHITESPACE; + private static final TokenSet STRING; + private static List tokenTypes; + private static List ruleTypes; static { PSIElementTypeFactory.defineLanguageIElementTypes(ProtoLanguage.INSTANCE, ProtoParser.tokenNames, ProtoParser.ruleNames); - List tokenTypes = - PSIElementTypeFactory.getTokenIElementTypes(ProtoLanguage.INSTANCE); + tokenTypes = PSIElementTypeFactory.getTokenIElementTypes(ProtoLanguage.INSTANCE); ID = tokenTypes.get(ProtoLexer.NAME); FILE = new IFileElementType(ProtoLanguage.INSTANCE); COMMENTS = PSIElementTypeFactory.createTokenSet(ProtoLanguage.INSTANCE, COMMENT, LINE_COMMENT); @@ -111,7 +113,7 @@ public class ProtoParserDefinition implements ParserDefinition { ProtoLexer.BYTES ); - List ruleTypes = PSIElementTypeFactory.getRuleIElementTypes(ProtoLanguage.INSTANCE); + ruleTypes = PSIElementTypeFactory.getRuleIElementTypes(ProtoLanguage.INSTANCE); R_TYPE_REFERENCE = ruleTypes.get(ProtoParser.RULE_typeReference); R_NAME = ruleTypes.get(ProtoParser.RULE_name); @@ -123,10 +125,19 @@ public class ProtoParserDefinition implements ParserDefinition { RPAREN = tokenTypes.get(ProtoLexer.RPAREN); LSQUARE = tokenTypes.get(ProtoLexer.LSQUARE); RSQUARE = tokenTypes.get(ProtoLexer.RSQUARE); + ASSIGN = tokenTypes.get(ProtoLexer.ASSIGN); LT = tokenTypes.get(ProtoLexer.LT); GT = tokenTypes.get(ProtoLexer.GT); } + public static TokenIElementType token(int token) { + return tokenTypes.get(token); + } + + public static RuleIElementType rule(int rule) { + return ruleTypes.get(rule); + } + @NotNull @Override public Lexer createLexer(Project project) { @@ -229,14 +240,6 @@ public PsiElement createElement(ASTNode node) { return new RpcMethodTypeNode(node); case ProtoParser.RULE_proto: return new ProtoRootNode(node); - case ProtoParser.RULE_statement: - return new ProtoRootStatementNode(node); - case ProtoParser.RULE_messageBlockEntry: - return new MessageBlockEntryNode(node); - case ProtoParser.RULE_enumBlockEntry: - return new EnumBlockEntryNode(node); - case ProtoParser.RULE_serviceBlockEntry: - return new ServiceBlockEntryNode(node); default: return new ANTLRPsiNode(node); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java new file mode 100644 index 0000000..13ce06c --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -0,0 +1,60 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Wrap; +import com.intellij.formatting.WrapType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +import static io.protostuff.compiler.parser.ProtoParser.*; +import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.rule; +import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.token; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class BlockFactory { + + private static final Map> blockFactory = new HashMap<>(); + + private static final Wrap NO_WRAP = Wrap.createWrap(WrapType.NONE, false); + + private static final Alignment ALIGNMENT = Alignment.createAlignment(); + + static { + register(rule(RULE_syntax), node -> new SyntaxBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_packageStatement), node -> new PackageBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_importStatement), node -> new ImportBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_optionEntry), node -> new OptionBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_messageBlock), node -> new MessageBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_enumBlock), node -> new EnumBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_serviceBlock), node -> new ServiceBlock(node, NO_WRAP, ALIGNMENT)); + register(token(LINE_COMMENT), node -> new LineCommentBlock(node, NO_WRAP, ALIGNMENT)); + register(token(COMMENT), node -> new CommentBlock(node, NO_WRAP, ALIGNMENT)); + } + + private static void register(IElementType elementType, Function factory) { + blockFactory.put(elementType, factory); + } + + + public static Block createBlock(ASTNode node) { + Function factory = blockFactory.get(node.getElementType()); + if (factory == null) { + return createGenericBlock(node); + } + return factory.apply(node); + } + + @NotNull + private static GenericBlock createGenericBlock(ASTNode node) { + return new GenericBlock(node, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment()); + } + +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java new file mode 100644 index 0000000..634d3b7 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class CommentBlock extends AbstractBlock { + + protected CommentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java new file mode 100644 index 0000000..5398e98 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class EnumBlock extends AbstractBlock { + + protected EnumBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java new file mode 100644 index 0000000..74cd261 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ExtendBlock extends AbstractBlock { + + protected ExtendBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java new file mode 100644 index 0000000..dd1104c --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class GenericBlock extends AbstractBlock { + + protected GenericBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java new file mode 100644 index 0000000..80f2a84 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ImportBlock extends AbstractBlock { + + protected ImportBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java new file mode 100644 index 0000000..e2021b8 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class LineCommentBlock extends AbstractBlock { + + protected LineCommentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java new file mode 100644 index 0000000..5281a74 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class MessageBlock extends AbstractBlock { + + protected MessageBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java new file mode 100644 index 0000000..ae1f3e4 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class OptionBlock extends AbstractBlock { + + protected OptionBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java new file mode 100644 index 0000000..40be503 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class PackageBlock extends AbstractBlock { + + protected PackageBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java new file mode 100644 index 0000000..5798e9f --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -0,0 +1,75 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +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; + +import static io.protostuff.compiler.parser.ProtoParser.RULE_proto; +import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.rule; +import static io.protostuff.jetbrains.plugin.formatter.BlockFactory.createBlock; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ProtoFileBlock extends AbstractBlock { + + private static final Spacing BLANK_LINE = Spacing.createSpacing(0, 0, 2, true, 2); + private static final Spacing LINE_BREAK = Spacing.createSpacing(0, 0, 1, true, 2); + private static final Spacing NONE = Spacing.createSpacing(0, 0, 0, true, 2); + + protected ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + + } + + private static boolean canBeCorrectBlock(com.intellij.lang.ASTNode node) { + return node.getText().trim().length() > 0; + } + + @Override + protected List buildChildren() { + List blocks = new ArrayList<>(); + ASTNode protoRootNode = myNode.findChildByType(rule(RULE_proto)); + ASTNode child = protoRootNode.getFirstChildNode(); + while (child != null) { + if (canBeCorrectBlock(child)) { + Block block = createBlock(child); + blocks.add(block); + } + child = child.getTreeNext(); + } + return blocks; + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + if (child1 == null) { + return NONE; + } + if (child1 instanceof ImportBlock + && child2 instanceof ImportBlock) { + return LINE_BREAK; + } + if (child1 instanceof CommentBlock + || child1 instanceof LineCommentBlock) { + return NONE; + } + return BLANK_LINE; + } + + @Override + public boolean isLeaf() { + return myNode.getFirstChildNode() == null; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java new file mode 100644 index 0000000..2b64f81 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java @@ -0,0 +1,35 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +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 io.protostuff.jetbrains.plugin.ProtoLanguage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ProtoFormatterModelBuilder implements FormattingModelBuilder { + + @NotNull + @Override + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + ASTNode node = element.getNode(); + PsiFile containingFile = element.getContainingFile().getViewProvider().getPsi(ProtoLanguage.INSTANCE); + ASTNode fileNode = containingFile.getNode(); + Wrap wrap = Wrap.createWrap(WrapType.NONE, false); + Alignment alignment = Alignment.createAlignment(); + ProtoFileBlock block = new ProtoFileBlock(fileNode, wrap, alignment); + return FormattingModelProvider.createFormattingModelForPsiFile(containingFile, block, settings); + } + + @Nullable + @Override + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { + return null; + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java new file mode 100644 index 0000000..e4c8913 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ServiceBlock extends AbstractBlock { + + protected ServiceBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java new file mode 100644 index 0000000..16f1290 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java @@ -0,0 +1,42 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.common.AbstractBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class SyntaxBlock extends AbstractBlock { + + protected SyntaxBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + super(node, wrap, alignment); + } + + + @Override + protected List buildChildren() { + return Collections.emptyList(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return Spacing.getReadOnlySpacing(); + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return Indent.getAbsoluteNoneIndent(); + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoRootStatementNode.java b/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoRootStatementNode.java deleted file mode 100644 index 93ed111..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoRootStatementNode.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.protostuff.jetbrains.plugin.psi; - -import com.intellij.lang.ASTNode; -import org.antlr.jetbrains.adapter.psi.ANTLRPsiNode; -import org.jetbrains.annotations.NotNull; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class ProtoRootStatementNode extends ANTLRPsiNode implements KeywordsContainer { - - public ProtoRootStatementNode(@NotNull ASTNode node) { - super(node); - } - -} \ No newline at end of file diff --git a/src/main/java/io/protostuff/jetbrains/plugin/view/structure/RootTreeElement.java b/src/main/java/io/protostuff/jetbrains/plugin/view/structure/RootTreeElement.java index e07f840..139dd51 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/view/structure/RootTreeElement.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/view/structure/RootTreeElement.java @@ -30,22 +30,18 @@ public ItemPresentation getPresentation() { @Override public TreeElement[] getChildren() { List treeElements = new ArrayList<>(); - for (PsiElement psiElement : element.getChildren()) { - if (psiElement instanceof ProtoRootStatementNode) { - // first and the only child - PsiElement node = psiElement.getFirstChild(); - if (node instanceof MessageNode) { - TreeElement element = new MessageTreeElement((MessageNode) node); - treeElements.add(element); - } - if (node instanceof EnumNode) { - TreeElement element = new EnumTreeElement((EnumNode) node); - treeElements.add(element); - } - if (node instanceof ServiceNode) { - TreeElement element = new ServiceTreeElement((ServiceNode) node); - treeElements.add(element); - } + for (PsiElement node : element.getChildren()) { + if (node instanceof MessageNode) { + TreeElement element = new MessageTreeElement((MessageNode) node); + treeElements.add(element); + } + if (node instanceof EnumNode) { + TreeElement element = new EnumTreeElement((EnumNode) node); + treeElements.add(element); + } + if (node instanceof ServiceNode) { + TreeElement element = new ServiceTreeElement((ServiceNode) node); + treeElements.add(element); } } return treeElements.toArray(new TreeElement[treeElements.size()]); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 020f30f..33693cb 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -89,6 +89,9 @@ + + From a9b696f3a3e1568e9e01a07b061a194bcb3438d5 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 17 Apr 2016 23:38:27 +0300 Subject: [PATCH 02/14] Refactoring --- build.gradle | 3 +- .../plugin/formatter/BlockFactory.java | 44 +++++++++---------- .../plugin/formatter/CommentBlock.java | 9 ++-- .../jetbrains/plugin/formatter/EnumBlock.java | 9 ++-- .../plugin/formatter/ExtendBlock.java | 9 ++-- .../plugin/formatter/Formatting.java | 20 +++++++++ .../plugin/formatter/GenericBlock.java | 9 ++-- .../plugin/formatter/ImportBlock.java | 9 ++-- .../plugin/formatter/LineCommentBlock.java | 9 ++-- .../plugin/formatter/MessageBlock.java | 9 ++-- .../plugin/formatter/OptionBlock.java | 9 ++-- .../plugin/formatter/PackageBlock.java | 9 ++-- .../plugin/formatter/ProtoFileBlock.java | 23 ++++------ .../plugin/formatter/ServiceBlock.java | 9 ++-- .../plugin/formatter/SyntaxBlock.java | 9 ++-- 15 files changed, 119 insertions(+), 70 deletions(-) create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java diff --git a/build.gradle b/build.gradle index 6a02883..7a483b4 100644 --- a/build.gradle +++ b/build.gradle @@ -26,8 +26,9 @@ apply plugin: 'antlr' dependencies { compile 'org.antlr:antlr4-runtime:4.5.1' compile 'org.antlr:antlr4-jetbrains-adapter:1.0.0' + compile 'com.google.guava:guava:19.0' // antlr 'org.antlr:antlr4:4.5' - compile 'io.protostuff:protostuff-parser:2.0.0-alpha13-SNAPSHOT' + compile 'io.protostuff:protostuff-parser:2.0.0-alpha13' } apply plugin: 'idea' diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index 13ce06c..b0d30e9 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.function.Function; import static io.protostuff.compiler.parser.ProtoParser.*; import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.rule; @@ -21,40 +20,41 @@ */ public class BlockFactory { - private static final Map> blockFactory = new HashMap<>(); - + private static final Map registry = new HashMap<>(); private static final Wrap NO_WRAP = Wrap.createWrap(WrapType.NONE, false); - private static final Alignment ALIGNMENT = Alignment.createAlignment(); static { - register(rule(RULE_syntax), node -> new SyntaxBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_packageStatement), node -> new PackageBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_importStatement), node -> new ImportBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_optionEntry), node -> new OptionBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_messageBlock), node -> new MessageBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_enumBlock), node -> new EnumBlock(node, NO_WRAP, ALIGNMENT)); - register(rule(RULE_serviceBlock), node -> new ServiceBlock(node, NO_WRAP, ALIGNMENT)); - register(token(LINE_COMMENT), node -> new LineCommentBlock(node, NO_WRAP, ALIGNMENT)); - register(token(COMMENT), node -> new CommentBlock(node, NO_WRAP, ALIGNMENT)); + register(rule(RULE_syntax), SyntaxBlock::new); + register(rule(RULE_packageStatement), PackageBlock::new); + register(rule(RULE_importStatement), ImportBlock::new); + register(rule(RULE_optionEntry), OptionBlock::new); + register(rule(RULE_messageBlock), MessageBlock::new); + register(rule(RULE_enumBlock), EnumBlock::new); + register(rule(RULE_serviceBlock), ServiceBlock::new); + register(token(LINE_COMMENT), LineCommentBlock::new); + register(token(COMMENT), CommentBlock::new); } - private static void register(IElementType elementType, Function factory) { - blockFactory.put(elementType, factory); + private static void register(IElementType elementType, Factory factory) { + registry.put(elementType, factory); } - - public static Block createBlock(ASTNode node) { - Function factory = blockFactory.get(node.getElementType()); + static Block createBlock(ASTNode node, Alignment alignment) { + Factory factory = registry.get(node.getElementType()); if (factory == null) { - return createGenericBlock(node); + return createGenericBlock(node, alignment); } - return factory.apply(node); + return factory.create(node, alignment); } @NotNull - private static GenericBlock createGenericBlock(ASTNode node) { - return new GenericBlock(node, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment()); + private static GenericBlock createGenericBlock(ASTNode node, Alignment alignment) { + return new GenericBlock(node, alignment); + } + + private interface Factory { + Block create(ASTNode node, Alignment alignment); } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java index 634d3b7..87f978d 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class CommentBlock extends AbstractBlock { - protected CommentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected CommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java index 5398e98..da5e911 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class EnumBlock extends AbstractBlock { - protected EnumBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected EnumBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java index 74cd261..5f81102 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class ExtendBlock extends AbstractBlock { - protected ExtendBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected ExtendBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java new file mode 100644 index 0000000..96b8581 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java @@ -0,0 +1,20 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.Spacing; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class Formatting { + + static final Spacing BLANK_LINE = Spacing.createSpacing(0, 0, 2, true, 2); + static final Spacing LINE_BREAK = Spacing.createSpacing(0, 0, 1, true, 2); + static final Spacing NONE = Spacing.createSpacing(0, 0, 0, true, 2); + + private Formatting() { + } + + static boolean isNotEmpty(com.intellij.lang.ASTNode node) { + return node.getText().trim().length() > 0; + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java index dd1104c..a0c4d54 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class GenericBlock extends AbstractBlock { - protected GenericBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected GenericBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java index 80f2a84..21e022c 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class ImportBlock extends AbstractBlock { - protected ImportBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected ImportBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java index e2021b8..5b579fb 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class LineCommentBlock extends AbstractBlock { - protected LineCommentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected LineCommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java index 5281a74..eb72b9f 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class MessageBlock extends AbstractBlock { - protected MessageBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected MessageBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java index ae1f3e4..e0302a1 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class OptionBlock extends AbstractBlock { - protected OptionBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected OptionBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java index 40be503..6118709 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class PackageBlock extends AbstractBlock { - protected PackageBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected PackageBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index 5798e9f..b21548d 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -1,5 +1,6 @@ package io.protostuff.jetbrains.plugin.formatter; +import com.google.common.base.Preconditions; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; @@ -18,27 +19,21 @@ */ public class ProtoFileBlock extends AbstractBlock { - private static final Spacing BLANK_LINE = Spacing.createSpacing(0, 0, 2, true, 2); - private static final Spacing LINE_BREAK = Spacing.createSpacing(0, 0, 1, true, 2); - private static final Spacing NONE = Spacing.createSpacing(0, 0, 0, true, 2); - protected ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { super(node, wrap, alignment); } - private static boolean canBeCorrectBlock(com.intellij.lang.ASTNode node) { - return node.getText().trim().length() > 0; - } - @Override protected List buildChildren() { List blocks = new ArrayList<>(); ASTNode protoRootNode = myNode.findChildByType(rule(RULE_proto)); + Preconditions.checkNotNull(protoRootNode, "Could not find root proto node"); ASTNode child = protoRootNode.getFirstChildNode(); + Alignment alignment = Alignment.createAlignment(); while (child != null) { - if (canBeCorrectBlock(child)) { - Block block = createBlock(child); + if (Formatting.isNotEmpty(child)) { + Block block = createBlock(child, alignment); blocks.add(block); } child = child.getTreeNext(); @@ -50,17 +45,17 @@ protected List buildChildren() { @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { if (child1 == null) { - return NONE; + return Formatting.NONE; } if (child1 instanceof ImportBlock && child2 instanceof ImportBlock) { - return LINE_BREAK; + return Formatting.LINE_BREAK; } if (child1 instanceof CommentBlock || child1 instanceof LineCommentBlock) { - return NONE; + return Formatting.NONE; } - return BLANK_LINE; + return Formatting.BLANK_LINE; } @Override diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java index e4c8913..e6bb69e 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class ServiceBlock extends AbstractBlock { - protected ServiceBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected ServiceBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java index 16f1290..06f7e79 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java @@ -1,6 +1,9 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,8 @@ */ public class SyntaxBlock extends AbstractBlock { - protected SyntaxBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { - super(node, wrap, alignment); + protected SyntaxBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); } From f9d6c3b3c3dbfd1974339b7b2fbe95df3130c0fa Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sat, 23 Apr 2016 15:26:28 +0300 Subject: [PATCH 03/14] Implement formatting inside of message block --- build.gradle | 4 +- .../plugin/formatter/AbstractParentBlock.java | 105 ++++++++++++++++++ .../plugin/formatter/BlockFactory.java | 11 +- .../plugin/formatter/CommentBlock.java | 7 +- .../jetbrains/plugin/formatter/EnumBlock.java | 7 +- .../plugin/formatter/ExtendBlock.java | 8 +- .../plugin/formatter/GenericBlock.java | 7 +- .../plugin/formatter/ImportBlock.java | 2 +- .../jetbrains/plugin/formatter/LeafBlock.java | 100 +++++++++++++++++ .../plugin/formatter/LineCommentBlock.java | 7 +- .../plugin/formatter/MessageBlock.java | 36 ++---- .../plugin/formatter/OptionBlock.java | 7 +- .../plugin/formatter/PackageBlock.java | 2 +- .../plugin/formatter/ServiceBlock.java | 2 +- .../plugin/formatter/SyntaxBlock.java | 3 +- .../formatter/SyntheticStatementBlock.java | 82 ++++++++++++++ 16 files changed, 338 insertions(+), 52 deletions(-) create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java diff --git a/build.gradle b/build.gradle index 7a483b4..531d07d 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,8 @@ plugins { // id "com.jfrog.bintray" version "1.6" } -group = 'org.antlr' -description = 'Support for using ANTLR-generated parsers/lexers in jetbrains IDE plug-ins.' +group = 'io.protostuff' +description = 'Protobuf Plugin for JetBrains IDEs' repositories { jcenter() diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java new file mode 100644 index 0000000..fc4045c --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java @@ -0,0 +1,105 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.formatter.common.AbstractBlock; +import io.protostuff.compiler.parser.ProtoParser; +import io.protostuff.jetbrains.plugin.ProtoParserDefinition; +import org.antlr.jetbrains.adapter.lexer.TokenIElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Abstract block for all constructs that have children in curly braces. + * + * @author Kostiantyn Shchepanovskyi + */ +public abstract class AbstractParentBlock extends AbstractBlock { + + public static final TokenIElementType LEFT_CURLY_BRACE = ProtoParserDefinition.token(ProtoParser.LCURLY); + public static final TokenIElementType RIGHT_CURLY_BRACE = ProtoParserDefinition.token(ProtoParser.RCURLY); + public static final Spacing NEW_LINE = Spacing.createSpacing(0, 0, 1, true, 2); + public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); + + private final Indent indent; + + protected AbstractParentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, Indent indent) { + super(node, wrap, alignment); + this.indent = indent; + } + + protected AbstractParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + super(node, null, alignment); + this.indent = Indent.getNoneIndent(); + } + + enum State { + BEFORE_LEFT_CURLY_BRACE, + AFTER_LEFT_CURLY_BRACE + } + + @Override + protected List buildChildren() { + ASTNode child = getNode().getFirstChildNode(); + State state = State.BEFORE_LEFT_CURLY_BRACE; + List result = new ArrayList<>(); + Block openBrace = null; + Block closeBrace = null; + Alignment childAlignment = Alignment.createAlignment(); + while (child != null) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { + + if (child.getElementType() == LEFT_CURLY_BRACE) { + state = State.AFTER_LEFT_CURLY_BRACE; + openBrace = new LeafBlock(child, null, myAlignment, Indent.getNoneIndent()); + result.add(openBrace); + } else if (child.getElementType() == RIGHT_CURLY_BRACE) { + closeBrace = new LeafBlock(child, null, myAlignment, Indent.getNoneIndent()); + result.add(closeBrace); + } else { + switch (state) { + case BEFORE_LEFT_CURLY_BRACE: + result.add(new LeafBlock(child, null, myAlignment, Indent.getNoneIndent())); + break; + case AFTER_LEFT_CURLY_BRACE: + result.add(createChildBlock(child, getWrap(), childAlignment, Indent.getNormalIndent(true))); + break; + } + } + } + child = child.getTreeNext(); + } + return result; + } + + abstract Block createChildBlock(ASTNode child, Wrap wrap, Alignment childAlignment, Indent noneIndent); + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + if (child1 instanceof LeafBlock) { + LeafBlock a = (LeafBlock) child1; + if (a.getNode().getElementType() == LEFT_CURLY_BRACE) { + return NEW_LINE; + } else { + return SPACE; + } + } else { + return NEW_LINE; + } + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + public Indent getIndent() { + return indent; + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index b0d30e9..c236f30 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -1,9 +1,6 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Wrap; -import com.intellij.formatting.WrapType; +import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; @@ -45,16 +42,16 @@ static Block createBlock(ASTNode node, Alignment alignment) { if (factory == null) { return createGenericBlock(node, alignment); } - return factory.create(node, alignment); + return factory.create(node, alignment, Indent.getNoneIndent()); } @NotNull private static GenericBlock createGenericBlock(ASTNode node, Alignment alignment) { - return new GenericBlock(node, alignment); + return new GenericBlock(node, alignment, Indent.getNoneIndent()); } private interface Factory { - Block create(ASTNode node, Alignment alignment); + Block create(ASTNode node, Alignment alignment, Indent indent); } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java index 87f978d..a45ba50 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java @@ -17,8 +17,11 @@ */ public class CommentBlock extends AbstractBlock { - protected CommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected CommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } @@ -40,6 +43,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java index da5e911..a2e4e65 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java @@ -17,8 +17,11 @@ */ public class EnumBlock extends AbstractBlock { - protected EnumBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected EnumBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } @@ -40,6 +43,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java index 5f81102..2968712 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java @@ -17,11 +17,13 @@ */ public class ExtendBlock extends AbstractBlock { - protected ExtendBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected ExtendBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } - @Override protected List buildChildren() { return Collections.emptyList(); @@ -40,6 +42,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java index a0c4d54..e357116 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java @@ -17,8 +17,11 @@ */ public class GenericBlock extends AbstractBlock { - protected GenericBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected GenericBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } @@ -40,6 +43,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java index 21e022c..49e651d 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java @@ -17,7 +17,7 @@ */ public class ImportBlock extends AbstractBlock { - protected ImportBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + protected ImportBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java new file mode 100644 index 0000000..133a5bf --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * 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 io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class LeafBlock implements ASTBlock { + private final ASTNode myNode; + private final Wrap myWrap; + private final Alignment myAlignment; + + private final Indent myIndent; + + public LeafBlock(final ASTNode node, + final Wrap wrap, + final Alignment alignment, + Indent indent) { + myNode = node; + myWrap = wrap; + myAlignment = alignment; + myIndent = indent; + } + + @Override + public ASTNode getNode() { + return myNode; + } + + @Override + @NotNull + public TextRange getTextRange() { + return myNode.getTextRange(); + } + + @Override + @NotNull + public List getSubBlocks() { + return Collections.emptyList(); + } + + @Override + public Wrap getWrap() { + return myWrap; + } + + @Override + public Indent getIndent() { + return myIndent; + } + + @Override + public Alignment getAlignment() { + return myAlignment; + } + + @Override + public Spacing getSpacing(Block child1, @NotNull Block child2) { + return null; + } + + public ASTNode getTreeNode() { + return myNode; + } + + @Override + @NotNull + public ChildAttributes getChildAttributes(final int newChildIndex) { + return new ChildAttributes(getIndent(), null); + } + + @Override + public boolean isIncomplete() { + return false; + } + + @Override + public boolean isLeaf() { + return true; + } + +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java index 5b579fb..68a94a5 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java @@ -17,8 +17,11 @@ */ public class LineCommentBlock extends AbstractBlock { - protected LineCommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected LineCommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } @@ -40,6 +43,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java index eb72b9f..d87f593 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java @@ -3,43 +3,29 @@ import com.intellij.formatting.Alignment; import com.intellij.formatting.Block; import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; +import com.intellij.formatting.Wrap; import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; +import io.protostuff.jetbrains.plugin.psi.MessageNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.List; - /** * @author Kostiantyn Shchepanovskyi */ -public class MessageBlock extends AbstractBlock { - - protected MessageBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { - super(node, null, alignment); - } +public class MessageBlock extends AbstractParentBlock { - @Override - protected List buildChildren() { - return Collections.emptyList(); + protected MessageBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { + super(node, null, alignment, indent); } - @Nullable @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); + Block createChildBlock(ASTNode child, Wrap wrap, Alignment childAlignment, Indent childrenIndent) { + if (child instanceof MessageNode) { + return new MessageBlock(child, childAlignment, childrenIndent); + } else { + return new GenericBlock(child, childAlignment, childrenIndent); + } } - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); - } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java index e0302a1..4b14dff 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java @@ -17,8 +17,11 @@ */ public class OptionBlock extends AbstractBlock { - protected OptionBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + private final Indent indent; + + protected OptionBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, null, alignment); + this.indent = indent; } @@ -40,6 +43,6 @@ public boolean isLeaf() { @Override public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); + return indent; } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java index 6118709..0ea0068 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java @@ -17,7 +17,7 @@ */ public class PackageBlock extends AbstractBlock { - protected PackageBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + protected PackageBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java index e6bb69e..2288eb6 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java @@ -17,7 +17,7 @@ */ public class ServiceBlock extends AbstractBlock { - protected ServiceBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + protected ServiceBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { super(node, null, alignment); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java index 06f7e79..69cd52a 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java @@ -17,11 +17,10 @@ */ public class SyntaxBlock extends AbstractBlock { - protected SyntaxBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { + protected SyntaxBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { super(node, null, alignment); } - @Override protected List buildChildren() { return Collections.emptyList(); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java new file mode 100644 index 0000000..3089f02 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java @@ -0,0 +1,82 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Single-line statement block, contains leaf blocks separated by spaces. + */ +public class SyntheticStatementBlock implements Block { + + public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); + private final Wrap myWrap; + private final Alignment myAlignment; + + private final Indent myIndent; + private final List children; + + public SyntheticStatementBlock(final Wrap wrap, + final Alignment alignment, + Indent indent, List children) { + myWrap = wrap; + myAlignment = alignment; + myIndent = indent; + this.children = children; + } + + @Override + @NotNull + public TextRange getTextRange() { + Block firstChild = children.get(0); + Block lastChild = children.get(children.size() - 1); + int startOffset = firstChild.getTextRange().getStartOffset(); + int endOffset = lastChild.getTextRange().getEndOffset(); + return TextRange.create(startOffset, endOffset); + } + + @Override + @NotNull + public List getSubBlocks() { + return children; + } + + @Override + public Wrap getWrap() { + return myWrap; + } + + @Override + public Indent getIndent() { + return myIndent; + } + + @Override + public Alignment getAlignment() { + return myAlignment; + } + + @Override + public Spacing getSpacing(Block child1, @NotNull Block child2) { + return SPACE; + } + + @Override + @NotNull + public ChildAttributes getChildAttributes(final int newChildIndex) { + return new ChildAttributes(getIndent(), null); + } + + @Override + public boolean isIncomplete() { + return false; + } + + @Override + public boolean isLeaf() { + return true; + } + +} From e06d779f492097f681aef52d45ae6c59f2f431f5 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sat, 23 Apr 2016 22:04:52 +0300 Subject: [PATCH 04/14] Implement formatting for all blocks --- build.gradle | 2 +- .../plugin/ProtoParserDefinition.java | 2 +- .../plugin/formatter/AbstractParentBlock.java | 105 ------------------ .../plugin/formatter/BlockFactory.java | 84 ++++++++++---- .../plugin/formatter/CommentBlock.java | 48 -------- .../jetbrains/plugin/formatter/EnumBlock.java | 48 -------- .../plugin/formatter/ExtendBlock.java | 47 -------- .../plugin/formatter/GenericBlock.java | 48 -------- .../plugin/formatter/ImportBlock.java | 45 -------- .../jetbrains/plugin/formatter/LeafBlock.java | 9 ++ .../plugin/formatter/LineCommentBlock.java | 48 -------- .../plugin/formatter/MessageBlock.java | 31 ------ .../plugin/formatter/OptionBlock.java | 48 -------- .../plugin/formatter/PackageBlock.java | 45 -------- .../plugin/formatter/ParentBlock.java | 83 ++++++++++++++ .../plugin/formatter/ProtoFileBlock.java | 52 ++++++--- .../formatter/ProtoFormatterModelBuilder.java | 1 - .../plugin/formatter/ServiceBlock.java | 45 -------- .../plugin/formatter/StatementBlock.java | 98 ++++++++++++++++ .../plugin/formatter/SyntaxBlock.java | 44 -------- .../formatter/SyntheticStatementBlock.java | 82 -------------- .../plugin/formatter/BlockFactoryTest.java | 36 ++++++ 22 files changed, 331 insertions(+), 720 deletions(-) delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java create mode 100644 src/test/java/io/protostuff/jetbrains/plugin/formatter/BlockFactoryTest.java diff --git a/build.gradle b/build.gradle index 531d07d..9b16c98 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ dependencies { compile 'org.antlr:antlr4-jetbrains-adapter:1.0.0' compile 'com.google.guava:guava:19.0' // antlr 'org.antlr:antlr4:4.5' - compile 'io.protostuff:protostuff-parser:2.0.0-alpha13' + compile 'io.protostuff:protostuff-parser:2.0.0-alpha17-SNAPSHOT' } apply plugin: 'idea' diff --git a/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java b/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java index 59ff18c..9b1d7b3 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/ProtoParserDefinition.java @@ -68,7 +68,7 @@ public class ProtoParserDefinition implements ParserDefinition { ID = tokenTypes.get(ProtoLexer.NAME); FILE = new IFileElementType(ProtoLanguage.INSTANCE); COMMENTS = PSIElementTypeFactory.createTokenSet(ProtoLanguage.INSTANCE, COMMENT, LINE_COMMENT); - WHITESPACE = PSIElementTypeFactory.createTokenSet(ProtoLanguage.INSTANCE, WS); + WHITESPACE = PSIElementTypeFactory.createTokenSet(ProtoLanguage.INSTANCE, WS, NL); STRING = PSIElementTypeFactory.createTokenSet(ProtoLanguage.INSTANCE, STRING_VALUE); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java deleted file mode 100644 index fc4045c..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/AbstractParentBlock.java +++ /dev/null @@ -1,105 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.FormatterUtil; -import com.intellij.psi.formatter.common.AbstractBlock; -import io.protostuff.compiler.parser.ProtoParser; -import io.protostuff.jetbrains.plugin.ProtoParserDefinition; -import org.antlr.jetbrains.adapter.lexer.TokenIElementType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Abstract block for all constructs that have children in curly braces. - * - * @author Kostiantyn Shchepanovskyi - */ -public abstract class AbstractParentBlock extends AbstractBlock { - - public static final TokenIElementType LEFT_CURLY_BRACE = ProtoParserDefinition.token(ProtoParser.LCURLY); - public static final TokenIElementType RIGHT_CURLY_BRACE = ProtoParserDefinition.token(ProtoParser.RCURLY); - public static final Spacing NEW_LINE = Spacing.createSpacing(0, 0, 1, true, 2); - public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); - - private final Indent indent; - - protected AbstractParentBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, Indent indent) { - super(node, wrap, alignment); - this.indent = indent; - } - - protected AbstractParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment) { - super(node, null, alignment); - this.indent = Indent.getNoneIndent(); - } - - enum State { - BEFORE_LEFT_CURLY_BRACE, - AFTER_LEFT_CURLY_BRACE - } - - @Override - protected List buildChildren() { - ASTNode child = getNode().getFirstChildNode(); - State state = State.BEFORE_LEFT_CURLY_BRACE; - List result = new ArrayList<>(); - Block openBrace = null; - Block closeBrace = null; - Alignment childAlignment = Alignment.createAlignment(); - while (child != null) { - if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - - if (child.getElementType() == LEFT_CURLY_BRACE) { - state = State.AFTER_LEFT_CURLY_BRACE; - openBrace = new LeafBlock(child, null, myAlignment, Indent.getNoneIndent()); - result.add(openBrace); - } else if (child.getElementType() == RIGHT_CURLY_BRACE) { - closeBrace = new LeafBlock(child, null, myAlignment, Indent.getNoneIndent()); - result.add(closeBrace); - } else { - switch (state) { - case BEFORE_LEFT_CURLY_BRACE: - result.add(new LeafBlock(child, null, myAlignment, Indent.getNoneIndent())); - break; - case AFTER_LEFT_CURLY_BRACE: - result.add(createChildBlock(child, getWrap(), childAlignment, Indent.getNormalIndent(true))); - break; - } - } - } - child = child.getTreeNext(); - } - return result; - } - - abstract Block createChildBlock(ASTNode child, Wrap wrap, Alignment childAlignment, Indent noneIndent); - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - if (child1 instanceof LeafBlock) { - LeafBlock a = (LeafBlock) child1; - if (a.getNode().getElementType() == LEFT_CURLY_BRACE) { - return NEW_LINE; - } else { - return SPACE; - } - } else { - return NEW_LINE; - } - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index c236f30..d8d1732 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -1,6 +1,8 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.*; +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; @@ -10,47 +12,91 @@ import static io.protostuff.compiler.parser.ProtoParser.*; import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.rule; -import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.token; /** * @author Kostiantyn Shchepanovskyi */ public class BlockFactory { - private static final Map registry = new HashMap<>(); - private static final Wrap NO_WRAP = Wrap.createWrap(WrapType.NONE, false); - private static final Alignment ALIGNMENT = Alignment.createAlignment(); + static final Map registry = new HashMap<>(); + + public static final Factory ILLEGAL = (node, alignment, indent) -> { + throw new IllegalStateException(); + }; static { - register(rule(RULE_syntax), SyntaxBlock::new); - register(rule(RULE_packageStatement), PackageBlock::new); - register(rule(RULE_importStatement), ImportBlock::new); - register(rule(RULE_optionEntry), OptionBlock::new); - register(rule(RULE_messageBlock), MessageBlock::new); - register(rule(RULE_enumBlock), EnumBlock::new); - register(rule(RULE_serviceBlock), ServiceBlock::new); - register(token(LINE_COMMENT), LineCommentBlock::new); - register(token(COMMENT), CommentBlock::new); + Factory FAIL_ROOT_NODE = (node, alignment, indent) -> { + throw new IllegalStateException("Root node cannot be handled here"); + }; + register(rule(RULE_proto), FAIL_ROOT_NODE); + register(rule(RULE_packageName), LeafBlock::new); + register(rule(RULE_rpcType), LeafBlock::new); + register(rule(RULE_name), LeafBlock::new); + register(rule(RULE_mapKey), LeafBlock::new); + register(rule(RULE_mapValue), LeafBlock::new); + register(rule(RULE_tag), LeafBlock::new); + register(rule(RULE_fieldName), LeafBlock::new); + register(rule(RULE_textFormatOptionName), LeafBlock::new); + register(rule(RULE_textFormatOptionValue), LeafBlock::new); + register(rule(RULE_optionName), LeafBlock::new); + register(rule(RULE_optionValue), LeafBlock::new); + register(rule(RULE_fieldModifier), LeafBlock::new); + register(rule(RULE_typeReference), LeafBlock::new); + register(rule(RULE_rpcMethodOptions), StatementBlock::new); + register(rule(RULE_ranges), StatementBlock::new); + register(rule(RULE_range), StatementBlock::new); + register(rule(RULE_reserved), StatementBlock::new); + register(rule(RULE_fieldNames), StatementBlock::new); + register(rule(RULE_fieldOptions), StatementBlock::new); + register(rule(RULE_map), StatementBlock::new); + register(rule(RULE_syntax), StatementBlock::new); + register(rule(RULE_packageStatement), StatementBlock::new); + register(rule(RULE_importStatement), StatementBlock::new); + register(rule(RULE_optionEntry), StatementBlock::new); + register(rule(RULE_option), StatementBlock::new); + register(rule(RULE_messageBlock), ParentBlock::new); + register(rule(RULE_textFormat), ParentBlock::new); + register(rule(RULE_textFormatEntry), ParentBlock::new); + register(rule(RULE_field), StatementBlock::new); + register(rule(RULE_enumBlock), ParentBlock::new); + register(rule(RULE_enumConstant), StatementBlock::new); + register(rule(RULE_serviceBlock), ParentBlock::new); + register(rule(RULE_rpcMethod), StatementBlock::new); + register(rule(RULE_extendBlock), ParentBlock::new); + register(rule(RULE_extendBlockEntry), StatementBlock::new); + register(rule(RULE_oneof), ParentBlock::new); + register(rule(RULE_oneofField), StatementBlock::new); + register(rule(RULE_oneofGroup), ParentBlock::new); + register(rule(RULE_groupBlock), ParentBlock::new); + register(rule(RULE_extensions), StatementBlock::new); } private static void register(IElementType elementType, Factory factory) { + if (registry.containsKey(elementType)) { + throw new IllegalStateException("Already registered: " + elementType); + } registry.put(elementType, factory); } static Block createBlock(ASTNode node, Alignment alignment) { + return createBlock(node, alignment, Indent.getNoneIndent()); + } + + static Block createBlock(ASTNode node, Alignment alignment, Indent indent) { Factory factory = registry.get(node.getElementType()); if (factory == null) { - return createGenericBlock(node, alignment); + // If element type is unknown it is best to keep existing formatting + return createLeaf(node, alignment, indent); } - return factory.create(node, alignment, Indent.getNoneIndent()); + return factory.create(node, alignment, indent); } @NotNull - private static GenericBlock createGenericBlock(ASTNode node, Alignment alignment) { - return new GenericBlock(node, alignment, Indent.getNoneIndent()); + private static LeafBlock createLeaf(ASTNode node, Alignment alignment, Indent indent) { + return new LeafBlock(node, alignment, indent); } - private interface Factory { + interface Factory { Block create(ASTNode node, Alignment alignment, Indent indent); } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java deleted file mode 100644 index a45ba50..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/CommentBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class CommentBlock extends AbstractBlock { - - private final Indent indent; - - protected CommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java deleted file mode 100644 index a2e4e65..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/EnumBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class EnumBlock extends AbstractBlock { - - private final Indent indent; - - protected EnumBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java deleted file mode 100644 index 2968712..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ExtendBlock.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class ExtendBlock extends AbstractBlock { - - private final Indent indent; - - protected ExtendBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java deleted file mode 100644 index e357116..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/GenericBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class GenericBlock extends AbstractBlock { - - private final Indent indent; - - protected GenericBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java deleted file mode 100644 index 49e651d..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ImportBlock.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class ImportBlock extends AbstractBlock { - - protected ImportBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { - super(node, null, alignment); - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java index 133a5bf..ad9c529 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java @@ -40,6 +40,15 @@ public LeafBlock(final ASTNode node, myIndent = indent; } + public LeafBlock(final ASTNode node, + final Alignment alignment, + Indent indent) { + myNode = node; + myWrap = null; + myAlignment = alignment; + myIndent = indent; + } + @Override public ASTNode getNode() { return myNode; diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java deleted file mode 100644 index 68a94a5..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LineCommentBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class LineCommentBlock extends AbstractBlock { - - private final Indent indent; - - protected LineCommentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java deleted file mode 100644 index d87f593..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/MessageBlock.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Wrap; -import com.intellij.lang.ASTNode; -import io.protostuff.jetbrains.plugin.psi.MessageNode; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class MessageBlock extends AbstractParentBlock { - - - protected MessageBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment, indent); - } - - @Override - Block createChildBlock(ASTNode child, Wrap wrap, Alignment childAlignment, Indent childrenIndent) { - if (child instanceof MessageNode) { - return new MessageBlock(child, childAlignment, childrenIndent); - } else { - return new GenericBlock(child, childAlignment, childrenIndent); - } - } - -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java deleted file mode 100644 index 4b14dff..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/OptionBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class OptionBlock extends AbstractBlock { - - private final Indent indent; - - protected OptionBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, null, alignment); - this.indent = indent; - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return indent; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java deleted file mode 100644 index 0ea0068..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/PackageBlock.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class PackageBlock extends AbstractBlock { - - protected PackageBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { - super(node, null, alignment); - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java new file mode 100644 index 0000000..e4e791b --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java @@ -0,0 +1,83 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Spacing; +import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Abstract block for all constructs that have children in curly braces. + * + * @author Kostiantyn Shchepanovskyi + */ +public class ParentBlock extends StatementBlock { + + private final Set headerBlocks = new HashSet<>(); + + protected ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { + super(node, alignment, indent); + } + + enum State { + BEFORE_LEFT_CURLY_BRACE, + AFTER_LEFT_CURLY_BRACE + } + + @Override + protected List buildChildren() { + ASTNode child = getNode().getFirstChildNode(); + State state = State.BEFORE_LEFT_CURLY_BRACE; + List result = new ArrayList<>(); + Alignment childAlignment = Alignment.createAlignment(); + while (child != null) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { + IElementType elementType = child.getElementType(); + if (LCURLY.equals(elementType)) { + state = State.AFTER_LEFT_CURLY_BRACE; + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + } else if (RCURLY.equals(elementType)) { + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + } else { + switch (state) { + case BEFORE_LEFT_CURLY_BRACE: + Block block = BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent()); + headerBlocks.add(block); + result.add(block); + break; + case AFTER_LEFT_CURLY_BRACE: + result.add(BlockFactory.createBlock(child, childAlignment, Indent.getNormalIndent(true))); + break; + default: + throw new IllegalStateException(state.toString()); + } + } + } + child = child.getTreeNext(); + } + return result; + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + if (headerBlocks.contains(child1)) { + return super.getSpacing(child1, child2); + } + return NEW_LINE; + } + + @Override + public boolean isLeaf() { + return false; + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index b21548d..45146cd 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -1,17 +1,21 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.google.common.base.Preconditions; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.common.AbstractBlock; +import com.intellij.psi.tree.IElementType; +import io.protostuff.compiler.parser.ProtoLexer; +import io.protostuff.compiler.parser.ProtoParser; +import io.protostuff.jetbrains.plugin.ProtoParserDefinition; +import org.antlr.jetbrains.adapter.lexer.RuleIElementType; +import org.antlr.jetbrains.adapter.lexer.TokenIElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -import static io.protostuff.compiler.parser.ProtoParser.RULE_proto; -import static io.protostuff.jetbrains.plugin.ProtoParserDefinition.rule; import static io.protostuff.jetbrains.plugin.formatter.BlockFactory.createBlock; /** @@ -19,6 +23,10 @@ */ public class ProtoFileBlock extends AbstractBlock { + public static final RuleIElementType IMPORT = ProtoParserDefinition.rule(ProtoParser.RULE_importStatement); + public static final TokenIElementType COMMENT = ProtoParserDefinition.token(ProtoLexer.COMMENT); + public static final TokenIElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); + protected ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { super(node, wrap, alignment); @@ -27,8 +35,23 @@ protected ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable A @Override protected List buildChildren() { List blocks = new ArrayList<>(); - ASTNode protoRootNode = myNode.findChildByType(rule(RULE_proto)); - Preconditions.checkNotNull(protoRootNode, "Could not find root proto node"); + ASTNode child = myNode.getFirstChildNode(); + while (child != null) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { + IElementType elementType = child.getElementType(); + if (ProtoParserDefinition.rule(ProtoParser.RULE_proto).equals(elementType)) { + appendProtoBlocks(child, blocks); + } else { + // Comments are not part of root rule, we have to append them separately + blocks.add(new LeafBlock(child, Alignment.createAlignment(), Indent.getNoneIndent())); + } + } + child = child.getTreeNext(); + } + return blocks; + } + + private void appendProtoBlocks(ASTNode protoRootNode, List blocks) { ASTNode child = protoRootNode.getFirstChildNode(); Alignment alignment = Alignment.createAlignment(); while (child != null) { @@ -38,7 +61,6 @@ protected List buildChildren() { } child = child.getTreeNext(); } - return blocks; } @Nullable @@ -47,20 +69,22 @@ public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { if (child1 == null) { return Formatting.NONE; } - if (child1 instanceof ImportBlock - && child2 instanceof ImportBlock) { - return Formatting.LINE_BREAK; - } - if (child1 instanceof CommentBlock - || child1 instanceof LineCommentBlock) { - return Formatting.NONE; + if (child1 instanceof ASTBlock && child2 instanceof ASTBlock) { + IElementType a = ((ASTBlock) child1).getNode().getElementType(); + IElementType b = ((ASTBlock) child2).getNode().getElementType(); + if (IMPORT.equals(a) && IMPORT.equals(b)) { + return Formatting.LINE_BREAK; + } + if (COMMENT.equals(a) || LINE_COMMENT.equals(a)) { + return Formatting.LINE_BREAK; + } } return Formatting.BLANK_LINE; } @Override public boolean isLeaf() { - return myNode.getFirstChildNode() == null; + return false; } @Override diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java index 2b64f81..87bfe45 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java @@ -18,7 +18,6 @@ public class ProtoFormatterModelBuilder implements FormattingModelBuilder { @NotNull @Override public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { - ASTNode node = element.getNode(); PsiFile containingFile = element.getContainingFile().getViewProvider().getPsi(ProtoLanguage.INSTANCE); ASTNode fileNode = containingFile.getNode(); Wrap wrap = Wrap.createWrap(WrapType.NONE, false); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java deleted file mode 100644 index 2288eb6..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ServiceBlock.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class ServiceBlock extends AbstractBlock { - - protected ServiceBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { - super(node, null, alignment); - } - - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java new file mode 100644 index 0000000..69513b1 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java @@ -0,0 +1,98 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.formatter.common.AbstractBlock; +import com.intellij.psi.tree.IElementType; +import io.protostuff.compiler.parser.ProtoLexer; +import io.protostuff.jetbrains.plugin.ProtoLanguage; +import io.protostuff.jetbrains.plugin.ProtoParserDefinition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Abstract block for all constructs that have children in curly braces. + * + * @author Kostiantyn Shchepanovskyi + */ +public class StatementBlock extends AbstractBlock { + + public static final Spacing NEW_LINE = Spacing.createSpacing(0, 0, 1, true, 2); + public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); + public static final Spacing NONE = Spacing.createSpacing(0, 0, 0, false, 0); + + public static final IElementType SEMICOLON = ProtoParserDefinition.token(ProtoLexer.SEMICOLON); + public static final IElementType LCURLY = ProtoParserDefinition.token(ProtoLexer.LCURLY); + public static final IElementType RCURLY = ProtoParserDefinition.token(ProtoLexer.RCURLY); + public static final IElementType LPAREN = ProtoParserDefinition.token(ProtoLexer.LPAREN); + public static final IElementType RPAREN = ProtoParserDefinition.token(ProtoLexer.RPAREN); + public static final IElementType LSQUARE = ProtoParserDefinition.token(ProtoLexer.LSQUARE); + public static final IElementType RSQUARE = ProtoParserDefinition.token(ProtoLexer.RSQUARE); + public static final IElementType LT = ProtoParserDefinition.token(ProtoLexer.LT); + public static final IElementType GT = ProtoParserDefinition.token(ProtoLexer.GT); + public static final IElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); + public static final IElementType COMMA = ProtoParserDefinition.token(ProtoLexer.COMMA); + private static final SpacingBuilder SB = new SpacingBuilder(new CodeStyleSettings(), ProtoLanguage.INSTANCE) + .after(LINE_COMMENT).spacing(0, 0, 1, true, 2) + .after(LCURLY).spacing(0, 0, 1, true, 2) + .before(RCURLY).spacing(0, 0, 1, true, 2) + .after(LPAREN).spacing(0, 0, 0, false, 0) + .before(RPAREN).spacing(0, 0, 0, false, 0) + .after(LSQUARE).spacing(0, 0, 0, false, 0) + .before(RSQUARE).spacing(0, 0, 0, false, 0) + .before(LT).spacing(0, 0, 0, false, 0) + .after(LT).spacing(0, 0, 0, false, 0) + .before(GT).spacing(0, 0, 0, false, 0) + .before(COMMA).spacing(0, 0, 0, false, 0) + .before(SEMICOLON).spacing(0, 0, 0, false, 0) + .after(COMMA).spacing(1, 1, 0, false, 0); + + private final Set headerBlocks = new HashSet<>(); + private final Indent indent; + + protected StatementBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { + super(node, null, alignment); + this.indent = indent; + } + + @Override + protected List buildChildren() { + ASTNode child = getNode().getFirstChildNode(); + List result = new ArrayList<>(); + while (child != null) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { + Block block = BlockFactory.createBlock(child, Alignment.createAlignment(), Indent.getNoneIndent()); + result.add(block); + } + child = child.getTreeNext(); + } + return result; + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + Spacing spacing = SB.getSpacing(this, child1, child2); + if (spacing == null) { + return SPACE; + } + return spacing; + } + + @Override + public boolean isLeaf() { + return false; + } + + @Override + public Indent getIndent() { + return indent; + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java deleted file mode 100644 index 69cd52a..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntaxBlock.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; -import com.intellij.lang.ASTNode; -import com.intellij.psi.formatter.common.AbstractBlock; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class SyntaxBlock extends AbstractBlock { - - protected SyntaxBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent ignore) { - super(node, null, alignment); - } - - @Override - protected List buildChildren() { - return Collections.emptyList(); - } - - @Nullable - @Override - public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - return Spacing.getReadOnlySpacing(); - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public Indent getIndent() { - return Indent.getAbsoluteNoneIndent(); - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java deleted file mode 100644 index 3089f02..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/SyntheticStatementBlock.java +++ /dev/null @@ -1,82 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.*; -import com.intellij.openapi.util.TextRange; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * Single-line statement block, contains leaf blocks separated by spaces. - */ -public class SyntheticStatementBlock implements Block { - - public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); - private final Wrap myWrap; - private final Alignment myAlignment; - - private final Indent myIndent; - private final List children; - - public SyntheticStatementBlock(final Wrap wrap, - final Alignment alignment, - Indent indent, List children) { - myWrap = wrap; - myAlignment = alignment; - myIndent = indent; - this.children = children; - } - - @Override - @NotNull - public TextRange getTextRange() { - Block firstChild = children.get(0); - Block lastChild = children.get(children.size() - 1); - int startOffset = firstChild.getTextRange().getStartOffset(); - int endOffset = lastChild.getTextRange().getEndOffset(); - return TextRange.create(startOffset, endOffset); - } - - @Override - @NotNull - public List getSubBlocks() { - return children; - } - - @Override - public Wrap getWrap() { - return myWrap; - } - - @Override - public Indent getIndent() { - return myIndent; - } - - @Override - public Alignment getAlignment() { - return myAlignment; - } - - @Override - public Spacing getSpacing(Block child1, @NotNull Block child2) { - return SPACE; - } - - @Override - @NotNull - public ChildAttributes getChildAttributes(final int newChildIndex) { - return new ChildAttributes(getIndent(), null); - } - - @Override - public boolean isIncomplete() { - return false; - } - - @Override - public boolean isLeaf() { - return true; - } - -} diff --git a/src/test/java/io/protostuff/jetbrains/plugin/formatter/BlockFactoryTest.java b/src/test/java/io/protostuff/jetbrains/plugin/formatter/BlockFactoryTest.java new file mode 100644 index 0000000..626054c --- /dev/null +++ b/src/test/java/io/protostuff/jetbrains/plugin/formatter/BlockFactoryTest.java @@ -0,0 +1,36 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.intellij.psi.tree.IElementType; +import io.protostuff.compiler.parser.ProtoParser; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class BlockFactoryTest { + + @Test + public void allParserRulesAreRegistered() throws Exception { + Map registry = BlockFactory.registry; + + Set allRules = ImmutableSet.copyOf(ProtoParser.ruleNames); + + Set registeredRules = new HashSet<>(); + for (IElementType type : registry.keySet()) { + registeredRules.add(type.toString()); + } + + Sets.SetView diff = Sets.difference(allRules, registeredRules); + if (!diff.isEmpty()) { + Assert.fail("Following rules are not registered: " + diff); + } + + } +} \ No newline at end of file From 05adff4dcc76bebefa40f4d008b46de1b7df1ce8 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sat, 23 Apr 2016 23:22:48 +0300 Subject: [PATCH 05/14] Improve formatter --- .../plugin/formatter/BlockFactory.java | 3 +- .../jetbrains/plugin/formatter/LeafBlock.java | 10 ----- .../plugin/formatter/ParentBlock.java | 44 ++++++++++++++++--- .../plugin/formatter/ProtoFileBlock.java | 13 +----- .../plugin/formatter/StatementBlock.java | 5 +-- 5 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index d8d1732..3219a75 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -42,7 +42,6 @@ public class BlockFactory { register(rule(RULE_optionValue), LeafBlock::new); register(rule(RULE_fieldModifier), LeafBlock::new); register(rule(RULE_typeReference), LeafBlock::new); - register(rule(RULE_rpcMethodOptions), StatementBlock::new); register(rule(RULE_ranges), StatementBlock::new); register(rule(RULE_range), StatementBlock::new); register(rule(RULE_reserved), StatementBlock::new); @@ -61,7 +60,7 @@ public class BlockFactory { register(rule(RULE_enumBlock), ParentBlock::new); register(rule(RULE_enumConstant), StatementBlock::new); register(rule(RULE_serviceBlock), ParentBlock::new); - register(rule(RULE_rpcMethod), StatementBlock::new); + register(rule(RULE_rpcMethod), ParentBlock::new); register(rule(RULE_extendBlock), ParentBlock::new); register(rule(RULE_extendBlockEntry), StatementBlock::new); register(rule(RULE_oneof), ParentBlock::new); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java index ad9c529..73c1b28 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java @@ -30,16 +30,6 @@ public class LeafBlock implements ASTBlock { private final Indent myIndent; - public LeafBlock(final ASTNode node, - final Wrap wrap, - final Alignment alignment, - Indent indent) { - myNode = node; - myWrap = wrap; - myAlignment = alignment; - myIndent = indent; - } - public LeafBlock(final ASTNode node, final Alignment alignment, Indent indent) { diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java index e4e791b..7aa88d8 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java @@ -1,9 +1,6 @@ package io.protostuff.jetbrains.plugin.formatter; -import com.intellij.formatting.Alignment; -import com.intellij.formatting.Block; -import com.intellij.formatting.Indent; -import com.intellij.formatting.Spacing; +import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.tree.IElementType; @@ -23,14 +20,19 @@ public class ParentBlock extends StatementBlock { private final Set headerBlocks = new HashSet<>(); + private Alignment childAlignment; + private int openBraceIndex; + private int closeBraceIndex; protected ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, alignment, indent); + childAlignment = Alignment.createAlignment(); } enum State { BEFORE_LEFT_CURLY_BRACE, - AFTER_LEFT_CURLY_BRACE + AFTER_LEFT_CURLY_BRACE, + AFTER_RIGHT_CURLY_BRACE } @Override @@ -38,15 +40,17 @@ protected List buildChildren() { ASTNode child = getNode().getFirstChildNode(); State state = State.BEFORE_LEFT_CURLY_BRACE; List result = new ArrayList<>(); - Alignment childAlignment = Alignment.createAlignment(); while (child != null) { if (!FormatterUtil.containsWhiteSpacesOnly(child)) { IElementType elementType = child.getElementType(); if (LCURLY.equals(elementType)) { state = State.AFTER_LEFT_CURLY_BRACE; + openBraceIndex = result.size(); result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); } else if (RCURLY.equals(elementType)) { + closeBraceIndex = result.size(); result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + state = State.AFTER_RIGHT_CURLY_BRACE; } else { switch (state) { case BEFORE_LEFT_CURLY_BRACE: @@ -57,6 +61,9 @@ protected List buildChildren() { case AFTER_LEFT_CURLY_BRACE: result.add(BlockFactory.createBlock(child, childAlignment, Indent.getNormalIndent(true))); break; + case AFTER_RIGHT_CURLY_BRACE: + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + break; default: throw new IllegalStateException(state.toString()); } @@ -70,12 +77,37 @@ protected List buildChildren() { @Nullable @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + if (child2 instanceof ASTBlock) { + ASTBlock block = (ASTBlock) child2; + // Do not move semicolon after '}' to new line. + IElementType elementType = block.getNode().getElementType(); + if (SEMICOLON.equals(elementType)) { + return NONE; + } + // Do not move trailing comments to new line. + if (LINE_COMMENT.equals(elementType) + || COMMENT.equals(elementType)) { + return SPACE_OR_NEW_LINE; + } + } if (headerBlocks.contains(child1)) { return super.getSpacing(child1, child2); } return NEW_LINE; } + @NotNull + @Override + public ChildAttributes getChildAttributes(int newChildIndex) { + return new ChildAttributes(getChildIndent(), childAlignment); + } + + @Nullable + @Override + protected Indent getChildIndent() { + return Indent.getNormalIndent(); + } + @Override public boolean isLeaf() { return false; diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index 45146cd..070d254 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -24,6 +24,7 @@ public class ProtoFileBlock extends AbstractBlock { public static final RuleIElementType IMPORT = ProtoParserDefinition.rule(ProtoParser.RULE_importStatement); + public static final RuleIElementType OPTION = ProtoParserDefinition.rule(ProtoParser.RULE_option); public static final TokenIElementType COMMENT = ProtoParserDefinition.token(ProtoLexer.COMMENT); public static final TokenIElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); @@ -69,17 +70,7 @@ public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { if (child1 == null) { return Formatting.NONE; } - if (child1 instanceof ASTBlock && child2 instanceof ASTBlock) { - IElementType a = ((ASTBlock) child1).getNode().getElementType(); - IElementType b = ((ASTBlock) child2).getNode().getElementType(); - if (IMPORT.equals(a) && IMPORT.equals(b)) { - return Formatting.LINE_BREAK; - } - if (COMMENT.equals(a) || LINE_COMMENT.equals(a)) { - return Formatting.LINE_BREAK; - } - } - return Formatting.BLANK_LINE; + return Formatting.LINE_BREAK; } @Override diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java index 69513b1..6115744 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java @@ -13,9 +13,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; /** * Abstract block for all constructs that have children in curly braces. @@ -26,6 +24,7 @@ public class StatementBlock extends AbstractBlock { public static final Spacing NEW_LINE = Spacing.createSpacing(0, 0, 1, true, 2); public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); + public static final Spacing SPACE_OR_NEW_LINE = Spacing.createSpacing(1, 1, 0, true, 1); public static final Spacing NONE = Spacing.createSpacing(0, 0, 0, false, 0); public static final IElementType SEMICOLON = ProtoParserDefinition.token(ProtoLexer.SEMICOLON); @@ -38,6 +37,7 @@ public class StatementBlock extends AbstractBlock { public static final IElementType LT = ProtoParserDefinition.token(ProtoLexer.LT); public static final IElementType GT = ProtoParserDefinition.token(ProtoLexer.GT); public static final IElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); + public static final IElementType COMMENT = ProtoParserDefinition.token(ProtoLexer.COMMENT); public static final IElementType COMMA = ProtoParserDefinition.token(ProtoLexer.COMMA); private static final SpacingBuilder SB = new SpacingBuilder(new CodeStyleSettings(), ProtoLanguage.INSTANCE) .after(LINE_COMMENT).spacing(0, 0, 1, true, 2) @@ -54,7 +54,6 @@ public class StatementBlock extends AbstractBlock { .before(SEMICOLON).spacing(0, 0, 0, false, 0) .after(COMMA).spacing(1, 1, 0, false, 0); - private final Set headerBlocks = new HashSet<>(); private final Indent indent; protected StatementBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { From 35c937329fe9d0e9475e87497c0ab19e665920c4 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sat, 23 Apr 2016 23:29:42 +0300 Subject: [PATCH 06/14] Refactoring --- .../plugin/formatter/BlockFactory.java | 6 +-- .../plugin/formatter/Formatting.java | 20 --------- .../jetbrains/plugin/formatter/LeafBlock.java | 44 +++++-------------- .../plugin/formatter/ParentBlock.java | 20 ++++----- .../plugin/formatter/ProtoFileBlock.java | 18 +++----- .../plugin/formatter/StatementBlock.java | 3 +- 6 files changed, 26 insertions(+), 85 deletions(-) delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index 3219a75..4572110 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -16,14 +16,10 @@ /** * @author Kostiantyn Shchepanovskyi */ -public class BlockFactory { +class BlockFactory { static final Map registry = new HashMap<>(); - public static final Factory ILLEGAL = (node, alignment, indent) -> { - throw new IllegalStateException(); - }; - static { Factory FAIL_ROOT_NODE = (node, alignment, indent) -> { throw new IllegalStateException("Root node cannot be handled here"); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java deleted file mode 100644 index 96b8581..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/Formatting.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.intellij.formatting.Spacing; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class Formatting { - - static final Spacing BLANK_LINE = Spacing.createSpacing(0, 0, 2, true, 2); - static final Spacing LINE_BREAK = Spacing.createSpacing(0, 0, 1, true, 2); - static final Spacing NONE = Spacing.createSpacing(0, 0, 0, true, 2); - - private Formatting() { - } - - static boolean isNotEmpty(com.intellij.lang.ASTNode node) { - return node.getText().trim().length() > 0; - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java index 73c1b28..4de1f53 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java @@ -1,18 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * 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 io.protostuff.jetbrains.plugin.formatter; import com.intellij.formatting.*; @@ -23,31 +8,26 @@ import java.util.Collections; import java.util.List; -public class LeafBlock implements ASTBlock { - private final ASTNode myNode; - private final Wrap myWrap; - private final Alignment myAlignment; - +class LeafBlock implements ASTBlock { + private final ASTNode node; + private final Alignment alignment; private final Indent myIndent; - public LeafBlock(final ASTNode node, - final Alignment alignment, - Indent indent) { - myNode = node; - myWrap = null; - myAlignment = alignment; + LeafBlock(ASTNode node, Alignment alignment, Indent indent) { + this.node = node; + this.alignment = alignment; myIndent = indent; } @Override public ASTNode getNode() { - return myNode; + return node; } @Override @NotNull public TextRange getTextRange() { - return myNode.getTextRange(); + return node.getTextRange(); } @Override @@ -58,7 +38,7 @@ public List getSubBlocks() { @Override public Wrap getWrap() { - return myWrap; + return null; } @Override @@ -68,7 +48,7 @@ public Indent getIndent() { @Override public Alignment getAlignment() { - return myAlignment; + return alignment; } @Override @@ -76,10 +56,6 @@ public Spacing getSpacing(Block child1, @NotNull Block child2) { return null; } - public ASTNode getTreeNode() { - return myNode; - } - @Override @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java index 7aa88d8..11cc562 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java @@ -17,24 +17,16 @@ * * @author Kostiantyn Shchepanovskyi */ -public class ParentBlock extends StatementBlock { +class ParentBlock extends StatementBlock { private final Set headerBlocks = new HashSet<>(); private Alignment childAlignment; - private int openBraceIndex; - private int closeBraceIndex; - protected ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { + ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { super(node, alignment, indent); childAlignment = Alignment.createAlignment(); } - enum State { - BEFORE_LEFT_CURLY_BRACE, - AFTER_LEFT_CURLY_BRACE, - AFTER_RIGHT_CURLY_BRACE - } - @Override protected List buildChildren() { ASTNode child = getNode().getFirstChildNode(); @@ -45,10 +37,8 @@ protected List buildChildren() { IElementType elementType = child.getElementType(); if (LCURLY.equals(elementType)) { state = State.AFTER_LEFT_CURLY_BRACE; - openBraceIndex = result.size(); result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); } else if (RCURLY.equals(elementType)) { - closeBraceIndex = result.size(); result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); state = State.AFTER_RIGHT_CURLY_BRACE; } else { @@ -112,4 +102,10 @@ protected Indent getChildIndent() { public boolean isLeaf() { return false; } + + private enum State { + BEFORE_LEFT_CURLY_BRACE, + AFTER_LEFT_CURLY_BRACE, + AFTER_RIGHT_CURLY_BRACE + } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index 070d254..43c78d6 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -5,11 +5,8 @@ import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.tree.IElementType; -import io.protostuff.compiler.parser.ProtoLexer; import io.protostuff.compiler.parser.ProtoParser; import io.protostuff.jetbrains.plugin.ProtoParserDefinition; -import org.antlr.jetbrains.adapter.lexer.RuleIElementType; -import org.antlr.jetbrains.adapter.lexer.TokenIElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,14 +18,9 @@ /** * @author Kostiantyn Shchepanovskyi */ -public class ProtoFileBlock extends AbstractBlock { +class ProtoFileBlock extends AbstractBlock { - public static final RuleIElementType IMPORT = ProtoParserDefinition.rule(ProtoParser.RULE_importStatement); - public static final RuleIElementType OPTION = ProtoParserDefinition.rule(ProtoParser.RULE_option); - public static final TokenIElementType COMMENT = ProtoParserDefinition.token(ProtoLexer.COMMENT); - public static final TokenIElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); - - protected ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { super(node, wrap, alignment); } @@ -56,7 +48,7 @@ private void appendProtoBlocks(ASTNode protoRootNode, List blocks) { ASTNode child = protoRootNode.getFirstChildNode(); Alignment alignment = Alignment.createAlignment(); while (child != null) { - if (Formatting.isNotEmpty(child)) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { Block block = createBlock(child, alignment); blocks.add(block); } @@ -68,9 +60,9 @@ private void appendProtoBlocks(ASTNode protoRootNode, List blocks) { @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { if (child1 == null) { - return Formatting.NONE; + return StatementBlock.NONE; } - return Formatting.LINE_BREAK; + return StatementBlock.NEW_LINE; } @Override diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java index 6115744..42867e5 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java @@ -20,7 +20,8 @@ * * @author Kostiantyn Shchepanovskyi */ -public class StatementBlock extends AbstractBlock { +@SuppressWarnings("WeakerAccess") +class StatementBlock extends AbstractBlock { public static final Spacing NEW_LINE = Spacing.createSpacing(0, 0, 1, true, 2); public static final Spacing SPACE = Spacing.createSpacing(1, 1, 0, false, 0); From 8c987732e2474dd817326d3dec15e78b1f80eb7b Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 00:43:45 +0300 Subject: [PATCH 07/14] Add code style settings (start) --- .../plugin/formatter/BlockFactory.java | 4 -- ...ilder.java => FormattingModelBuilder.java} | 2 +- .../formatter/ProtoCodeStyleSettings.java | 12 ++++ .../ProtoCodeStyleSettingsProvider.java | 61 +++++++++++++++++++ .../plugin/formatter/ProtoFileBlock.java | 2 +- .../formatter/ProtoIndentOptionsProvider.java | 49 +++++++++++++++ ...rotoLanguageCodeStyleSettingsProvider.java | 49 +++++++++++++++ src/main/resources/META-INF/plugin.xml | 8 ++- 8 files changed, 180 insertions(+), 7 deletions(-) rename src/main/java/io/protostuff/jetbrains/plugin/formatter/{ProtoFormatterModelBuilder.java => FormattingModelBuilder.java} (92%) create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettings.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java create mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index 4572110..b163cd4 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -73,10 +73,6 @@ private static void register(IElementType elementType, Factory factory) { registry.put(elementType, factory); } - static Block createBlock(ASTNode node, Alignment alignment) { - return createBlock(node, alignment, Indent.getNoneIndent()); - } - static Block createBlock(ASTNode node, Alignment alignment, Indent indent) { Factory factory = registry.get(node.getElementType()); if (factory == null) { diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java similarity index 92% rename from src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java rename to src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java index 87bfe45..487a145 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFormatterModelBuilder.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java @@ -13,7 +13,7 @@ /** * @author Kostiantyn Shchepanovskyi */ -public class ProtoFormatterModelBuilder implements FormattingModelBuilder { +public class FormattingModelBuilder implements com.intellij.formatting.FormattingModelBuilder { @NotNull @Override diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettings.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettings.java new file mode 100644 index 0000000..dfa9f27 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettings.java @@ -0,0 +1,12 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; + +public class ProtoCodeStyleSettings extends CustomCodeStyleSettings { + public ProtoCodeStyleSettings(CodeStyleSettings settings) { + super("ProtoCodeStyleSettings", settings); + } + + +} \ No newline at end of file diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java new file mode 100644 index 0000000..d4bf64a --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java @@ -0,0 +1,61 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.application.options.CodeStyleAbstractConfigurable; +import com.intellij.application.options.CodeStyleAbstractPanel; +import com.intellij.application.options.TabbedLanguageCodeStylePanel; +import com.intellij.openapi.options.Configurable; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import io.protostuff.jetbrains.plugin.ProtoLanguage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ProtoCodeStyleSettingsProvider extends CodeStyleSettingsProvider { + + @Override + public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) { + return new ProtoCodeStyleSettings(settings); + } + + @Nullable + @Override + public String getConfigurableDisplayName() { + return "Protobuf"; + } + + @NotNull + @Override + public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { + return new CodeStyleAbstractConfigurable(settings, originalSettings, "Protobuf") { + @Override + protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { + return new ProtoCodeStyleMainPanel(getCurrentSettings(), settings); + } + + @Nullable + @Override + public String getHelpTopic() { + return null; + } + }; + } + + private static class ProtoCodeStyleMainPanel extends TabbedLanguageCodeStylePanel { + public ProtoCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) { + super(ProtoLanguage.INSTANCE, currentSettings, settings); + } + + @Override + protected void initTabs(CodeStyleSettings settings) { + addIndentOptionsTab(settings); + addSpacesTab(settings); + addBlankLinesTab(settings); + addWrappingAndBracesTab(settings); +// addTab(new JsonCodeStylePanel(settings)); + } + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index 43c78d6..d86a8d8 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -49,7 +49,7 @@ private void appendProtoBlocks(ASTNode protoRootNode, List blocks) { Alignment alignment = Alignment.createAlignment(); while (child != null) { if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - Block block = createBlock(child, alignment); + Block block = createBlock(child, alignment, Indent.getNoneIndent()); blocks.add(block); } child = child.getTreeNext(); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java new file mode 100644 index 0000000..e6d4bd8 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java @@ -0,0 +1,49 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.google.common.base.Joiner; +import com.intellij.application.options.IndentOptionsEditor; +import com.intellij.application.options.SmartIndentOptionsEditor; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.codeStyle.FileTypeIndentOptionsProvider; +import io.protostuff.jetbrains.plugin.ProtoFileType; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ProtoIndentOptionsProvider implements FileTypeIndentOptionsProvider { + + @Override + public CommonCodeStyleSettings.IndentOptions createIndentOptions() { + CommonCodeStyleSettings.IndentOptions indentOptions = new CodeStyleSettings.IndentOptions(); + indentOptions.INDENT_SIZE = 2; + return indentOptions; + } + + @Override + public FileType getFileType() { + return ProtoFileType.INSTANCE; + } + + @Override + public IndentOptionsEditor createOptionsEditor() { + return new SmartIndentOptionsEditor(); + } + + @Override + public String getPreviewText() { + return Joiner.on('\n').join( + "message Test {", + " optional int32 foo = 1;", + " optional string bar = 2;", + "}" + ); + } + + @Override + public void prepareForReformat(PsiFile psiFile) { + + } +} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java new file mode 100644 index 0000000..25ef8d1 --- /dev/null +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java @@ -0,0 +1,49 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.google.common.base.Joiner; +import com.intellij.lang.Language; +import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; +import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; +import io.protostuff.jetbrains.plugin.ProtoLanguage; +import org.jetbrains.annotations.NotNull; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ProtoLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider { + + @NotNull + @Override + public Language getLanguage() { + return ProtoLanguage.INSTANCE; + } + + + @Override + public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { + switch (settingsType) { + case INDENT_SETTINGS: + consumer.showStandardOptions("INDENT_SIZE", "TAB_SIZE"); + case SPACING_SETTINGS: + consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS"); + break; + case BLANK_LINES_SETTINGS: + consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); + break; + default: + break; + } +// consumer.showAllStandardOptions(); + } + + @Override + public String getCodeSample(@NotNull SettingsType settingsType) { + return Joiner.on('\n').join( + "message Test {", + " optional int32 foo = 1;", + " optional string bar = 2;", + "}" + ); + } + +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 33693cb..6c4b1a2 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -91,7 +91,13 @@ implementationClass="io.protostuff.jetbrains.plugin.view.structure.ProtoStructureViewFactory"/> + implementationClass="io.protostuff.jetbrains.plugin.formatter.FormattingModelBuilder"/> + + + + From 9d2c354576f1d238fdb5478047859a14024eac71 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 01:34:44 +0300 Subject: [PATCH 08/14] Formatter indentation settings --- .../ProtoCodeStyleSettingsProvider.java | 1 + .../formatter/ProtoIndentOptionsProvider.java | 49 ------------------- ...rotoLanguageCodeStyleSettingsProvider.java | 19 +++++++ src/main/resources/META-INF/plugin.xml | 2 +- 4 files changed, 21 insertions(+), 50 deletions(-) delete mode 100644 src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java index d4bf64a..2645b9c 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java @@ -44,6 +44,7 @@ public String getHelpTopic() { }; } + private static class ProtoCodeStyleMainPanel extends TabbedLanguageCodeStylePanel { public ProtoCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) { super(ProtoLanguage.INSTANCE, currentSettings, settings); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java deleted file mode 100644 index e6d4bd8..0000000 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoIndentOptionsProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.protostuff.jetbrains.plugin.formatter; - -import com.google.common.base.Joiner; -import com.intellij.application.options.IndentOptionsEditor; -import com.intellij.application.options.SmartIndentOptionsEditor; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.psi.codeStyle.FileTypeIndentOptionsProvider; -import io.protostuff.jetbrains.plugin.ProtoFileType; - -/** - * @author Kostiantyn Shchepanovskyi - */ -public class ProtoIndentOptionsProvider implements FileTypeIndentOptionsProvider { - - @Override - public CommonCodeStyleSettings.IndentOptions createIndentOptions() { - CommonCodeStyleSettings.IndentOptions indentOptions = new CodeStyleSettings.IndentOptions(); - indentOptions.INDENT_SIZE = 2; - return indentOptions; - } - - @Override - public FileType getFileType() { - return ProtoFileType.INSTANCE; - } - - @Override - public IndentOptionsEditor createOptionsEditor() { - return new SmartIndentOptionsEditor(); - } - - @Override - public String getPreviewText() { - return Joiner.on('\n').join( - "message Test {", - " optional int32 foo = 1;", - " optional string bar = 2;", - "}" - ); - } - - @Override - public void prepareForReformat(PsiFile psiFile) { - - } -} diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java index 25ef8d1..489c9a1 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java @@ -1,11 +1,15 @@ package io.protostuff.jetbrains.plugin.formatter; import com.google.common.base.Joiner; +import com.intellij.application.options.IndentOptionsEditor; +import com.intellij.application.options.SmartIndentOptionsEditor; import com.intellij.lang.Language; import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import io.protostuff.jetbrains.plugin.ProtoLanguage; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Kostiantyn Shchepanovskyi @@ -36,6 +40,21 @@ public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @ // consumer.showAllStandardOptions(); } + @Nullable + @Override + public IndentOptionsEditor getIndentOptionsEditor() { + return new SmartIndentOptionsEditor(); + } + + @Nullable + @Override + public CommonCodeStyleSettings getDefaultCommonSettings() { + CommonCodeStyleSettings settings = new CommonCodeStyleSettings(ProtoLanguage.INSTANCE); + CommonCodeStyleSettings.IndentOptions indentOptions = settings.initIndentOptions(); + indentOptions.INDENT_SIZE = 2; + return settings; + } + @Override public String getCodeSample(@NotNull SettingsType settingsType) { return Joiner.on('\n').join( diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 6c4b1a2..6396303 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -92,7 +92,7 @@ - + From 364d00dc376591a3769a23da4c8140e13936b990 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 01:44:58 +0300 Subject: [PATCH 09/14] Update plugin name and file description --- README.md | 2 +- .../protostuff/jetbrains/plugin/psi/ProtoPsiFileRoot.java | 4 +++- .../messages/ProtostuffBundle.properties | 6 +----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 41e32fa..5adc12e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Google Protocol Buffers support for JetBrains IDEs +## Protobuf Support for JetBrains IDEs [Protobuf Support Plugin](https://plugins.jetbrains.com/plugin/8277) for IntelliJ IDEA & other JetBrains products. diff --git a/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoPsiFileRoot.java b/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoPsiFileRoot.java index 69c9ec7..caac3ec 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoPsiFileRoot.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/psi/ProtoPsiFileRoot.java @@ -2,6 +2,7 @@ import com.intellij.extapi.psi.PsiFileBase; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; @@ -30,7 +31,8 @@ public FileType getFileType() { @Override public String toString() { - return "Google Protocol Buffers File"; + final VirtualFile virtualFile = getVirtualFile(); + return "ProtobufFile: " + (virtualFile != null ? virtualFile.getName() : ""); } @Override diff --git a/src/main/resources/io/protostuff/protostuff-jetbrains-plugin/messages/ProtostuffBundle.properties b/src/main/resources/io/protostuff/protostuff-jetbrains-plugin/messages/ProtostuffBundle.properties index 22522b9..8e81ac5 100644 --- a/src/main/resources/io/protostuff/protostuff-jetbrains-plugin/messages/ProtostuffBundle.properties +++ b/src/main/resources/io/protostuff/protostuff-jetbrains-plugin/messages/ProtostuffBundle.properties @@ -1,9 +1,5 @@ #actions -filetype.description.proto=Google Protocol Buffers file -action.newfile.text=Proto File -action.newfile.description=Create a new Protocol Buffers File -action.newfile.dialog.title=Create a new Protocol Buffers File -action.newfile.dialog.promt=Enter a new Protocol Buffers file name +filetype.description.proto=Protobuf file action.structureview.show.fields=Show Fields file.structure.toggle.show.fields=Show Fields From 13d31a48e96090282a9aa0e7382a7eb1acf89aef Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 14:01:01 +0300 Subject: [PATCH 10/14] Refactoring --- .../plugin/formatter/ProtoCodeStyleSettingsProvider.java | 1 - .../formatter/ProtoLanguageCodeStyleSettingsProvider.java | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java index 2645b9c..99d3917 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java @@ -56,7 +56,6 @@ protected void initTabs(CodeStyleSettings settings) { addSpacesTab(settings); addBlankLinesTab(settings); addWrappingAndBracesTab(settings); -// addTab(new JsonCodeStylePanel(settings)); } } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java index 489c9a1..3c1401b 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java @@ -26,10 +26,9 @@ public Language getLanguage() { @Override public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { switch (settingsType) { - case INDENT_SETTINGS: - consumer.showStandardOptions("INDENT_SIZE", "TAB_SIZE"); case SPACING_SETTINGS: consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS"); + consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Space around assignment operator"); break; case BLANK_LINES_SETTINGS: consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); @@ -37,7 +36,6 @@ public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @ default: break; } -// consumer.showAllStandardOptions(); } @Nullable @@ -46,12 +44,12 @@ public IndentOptionsEditor getIndentOptionsEditor() { return new SmartIndentOptionsEditor(); } + @Nullable @Override public CommonCodeStyleSettings getDefaultCommonSettings() { CommonCodeStyleSettings settings = new CommonCodeStyleSettings(ProtoLanguage.INSTANCE); - CommonCodeStyleSettings.IndentOptions indentOptions = settings.initIndentOptions(); - indentOptions.INDENT_SIZE = 2; + settings.initIndentOptions(); return settings; } From 2a57c4435b96d531666beabc4177ac5e11e0e29d Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 14:34:57 +0300 Subject: [PATCH 11/14] Add tests for parsing and PSI structure --- build.gradle | 7 --- .../jetbrains/plugin/parsing/ParsingTest.java | 46 +++++++++++++++++++ src/test/resources/parsing/Enum.proto | 5 ++ src/test/resources/parsing/Enum.txt | 41 +++++++++++++++++ .../parsing/HeaderAndFooterComments.proto | 3 ++ .../parsing/HeaderAndFooterComments.txt | 14 ++++++ src/test/resources/parsing/Message.proto | 4 ++ src/test/resources/parsing/Message.txt | 43 +++++++++++++++++ src/test/resources/parsing/Service.proto | 3 ++ src/test/resources/parsing/Service.txt | 35 ++++++++++++++ 10 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 src/test/java/io/protostuff/jetbrains/plugin/parsing/ParsingTest.java create mode 100644 src/test/resources/parsing/Enum.proto create mode 100644 src/test/resources/parsing/Enum.txt create mode 100644 src/test/resources/parsing/HeaderAndFooterComments.proto create mode 100644 src/test/resources/parsing/HeaderAndFooterComments.txt create mode 100644 src/test/resources/parsing/Message.proto create mode 100644 src/test/resources/parsing/Message.txt create mode 100644 src/test/resources/parsing/Service.proto create mode 100644 src/test/resources/parsing/Service.txt diff --git a/build.gradle b/build.gradle index 9b16c98..f25fac9 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,6 @@ buildscript { plugins { id "org.jetbrains.intellij" version "0.0.43" -// id "com.jfrog.bintray" version "1.6" } group = 'io.protostuff' @@ -21,13 +20,10 @@ repositories { } } -apply plugin: 'antlr' - dependencies { compile 'org.antlr:antlr4-runtime:4.5.1' compile 'org.antlr:antlr4-jetbrains-adapter:1.0.0' compile 'com.google.guava:guava:19.0' -// antlr 'org.antlr:antlr4:4.5' compile 'io.protostuff:protostuff-parser:2.0.0-alpha17-SNAPSHOT' } @@ -37,9 +33,6 @@ idea { jdkName = javaVersion languageLevel = javaVersion } -// module { -// generatedSourceDirs += file('gen') -// } } apply plugin: 'org.jetbrains.intellij' diff --git a/src/test/java/io/protostuff/jetbrains/plugin/parsing/ParsingTest.java b/src/test/java/io/protostuff/jetbrains/plugin/parsing/ParsingTest.java new file mode 100644 index 0000000..d6fb1ca --- /dev/null +++ b/src/test/java/io/protostuff/jetbrains/plugin/parsing/ParsingTest.java @@ -0,0 +1,46 @@ +package io.protostuff.jetbrains.plugin.parsing; + +import com.intellij.testFramework.ParsingTestCase; +import io.protostuff.jetbrains.plugin.ProtoParserDefinition; +import org.junit.Test; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class ParsingTest extends ParsingTestCase { + + public ParsingTest() { + super("parsing", "proto", new ProtoParserDefinition()); + } + + public void testMessage() { + doTest(true); + } + + public void testEnum() { + doTest(true); + } + + public void testService() { + doTest(true); + } + + public void testHeaderAndFooterComments() { + doTest(true); + } + + @Override + protected String getTestDataPath() { + return "src/test/resources"; + } + + @Override + protected boolean skipSpaces() { + return false; + } + + @Override + protected boolean includeRanges() { + return true; + } +} diff --git a/src/test/resources/parsing/Enum.proto b/src/test/resources/parsing/Enum.proto new file mode 100644 index 0000000..58a14af --- /dev/null +++ b/src/test/resources/parsing/Enum.proto @@ -0,0 +1,5 @@ +enum TestEnum { + ZERO = 0; + FIRST = 1; + FIFTH = 5; +} diff --git a/src/test/resources/parsing/Enum.txt b/src/test/resources/parsing/Enum.txt new file mode 100644 index 0000000..3f436d2 --- /dev/null +++ b/src/test/resources/parsing/Enum.txt @@ -0,0 +1,41 @@ +ProtobufFile: Enum.proto(0,61) + ProtoRootNode(proto)(0,61) + EnumNode(enumBlock)(0,61) + PsiElement('enum')('enum')(0,4) + PsiWhiteSpace(' ')(4,5) + ANTLRPsiNode(name)(5,13) + PsiElement(NAME)('TestEnum')(5,13) + PsiWhiteSpace(' ')(13,14) + PsiElement('{')('{')(14,15) + PsiWhiteSpace('\n')(15,16) + PsiWhiteSpace(' ')(16,20) + EnumConstantNode(enumConstant)(20,29) + ANTLRPsiNode(name)(20,24) + PsiElement(NAME)('ZERO')(20,24) + PsiWhiteSpace(' ')(24,25) + PsiElement('=')('=')(25,26) + PsiWhiteSpace(' ')(26,27) + PsiElement(INTEGER_VALUE)('0')(27,28) + PsiElement(';')(';')(28,29) + PsiWhiteSpace('\n')(29,30) + PsiWhiteSpace(' ')(30,34) + EnumConstantNode(enumConstant)(34,44) + ANTLRPsiNode(name)(34,39) + PsiElement(NAME)('FIRST')(34,39) + PsiWhiteSpace(' ')(39,40) + PsiElement('=')('=')(40,41) + PsiWhiteSpace(' ')(41,42) + PsiElement(INTEGER_VALUE)('1')(42,43) + PsiElement(';')(';')(43,44) + PsiWhiteSpace('\n')(44,45) + PsiWhiteSpace(' ')(45,49) + EnumConstantNode(enumConstant)(49,59) + ANTLRPsiNode(name)(49,54) + PsiElement(NAME)('FIFTH')(49,54) + PsiWhiteSpace(' ')(54,55) + PsiElement('=')('=')(55,56) + PsiWhiteSpace(' ')(56,57) + PsiElement(INTEGER_VALUE)('5')(57,58) + PsiElement(';')(';')(58,59) + PsiWhiteSpace('\n')(59,60) + PsiElement('}')('}')(60,61) diff --git a/src/test/resources/parsing/HeaderAndFooterComments.proto b/src/test/resources/parsing/HeaderAndFooterComments.proto new file mode 100644 index 0000000..3f92f7d --- /dev/null +++ b/src/test/resources/parsing/HeaderAndFooterComments.proto @@ -0,0 +1,3 @@ +// Header comment does not belong to 'proto' rule +syntax = "proto2"; +// Footer comment does not belong to 'proto' rule diff --git a/src/test/resources/parsing/HeaderAndFooterComments.txt b/src/test/resources/parsing/HeaderAndFooterComments.txt new file mode 100644 index 0000000..52bea16 --- /dev/null +++ b/src/test/resources/parsing/HeaderAndFooterComments.txt @@ -0,0 +1,14 @@ +ProtobufFile: HeaderAndFooterComments.proto(0,118) + PsiComment(LINE_COMMENT)('// Header comment does not belong to 'proto' rule')(0,49) + PsiWhiteSpace('\n')(49,50) + ProtoRootNode(proto)(50,68) + SyntaxNode(syntax)(50,68) + PsiElement('syntax')('syntax')(50,56) + PsiWhiteSpace(' ')(56,57) + PsiElement('=')('=')(57,58) + PsiWhiteSpace(' ')(58,59) + PsiElement(STRING_VALUE)('"proto2"')(59,67) + PsiElement(';')(';')(67,68) + PsiWhiteSpace('\n')(68,69) + PsiComment(LINE_COMMENT)('// Footer comment does not belong to 'proto' rule')(69,118) + diff --git a/src/test/resources/parsing/Message.proto b/src/test/resources/parsing/Message.proto new file mode 100644 index 0000000..743d880 --- /dev/null +++ b/src/test/resources/parsing/Message.proto @@ -0,0 +1,4 @@ +message TestMessage { + optional int32 x = 1; + optional int32 y = 2; +} diff --git a/src/test/resources/parsing/Message.txt b/src/test/resources/parsing/Message.txt new file mode 100644 index 0000000..dfafbd5 --- /dev/null +++ b/src/test/resources/parsing/Message.txt @@ -0,0 +1,43 @@ +ProtobufFile: Message.proto(0,75) + ProtoRootNode(proto)(0,75) + MessageNode(messageBlock)(0,75) + PsiElement('message')('message')(0,7) + PsiWhiteSpace(' ')(7,8) + ANTLRPsiNode(name)(8,19) + PsiElement(NAME)('TestMessage')(8,19) + PsiWhiteSpace(' ')(19,20) + PsiElement('{')('{')(20,21) + PsiWhiteSpace('\n')(21,22) + PsiWhiteSpace(' ')(22,26) + FieldNode(field)(26,47) + ANTLRPsiNode(fieldModifier)(26,34) + PsiElement('optional')('optional')(26,34) + PsiWhiteSpace(' ')(34,35) + TypeReferenceNode(typeReference)(35,40) + PsiElement('int32')('int32')(35,40) + PsiWhiteSpace(' ')(40,41) + ANTLRPsiNode(name)(41,42) + PsiElement(NAME)('x')(41,42) + PsiWhiteSpace(' ')(42,43) + PsiElement('=')('=')(43,44) + PsiWhiteSpace(' ')(44,45) + PsiElement(INTEGER_VALUE)('1')(45,46) + PsiElement(';')(';')(46,47) + PsiWhiteSpace('\n')(47,48) + PsiWhiteSpace(' ')(48,52) + FieldNode(field)(52,73) + ANTLRPsiNode(fieldModifier)(52,60) + PsiElement('optional')('optional')(52,60) + PsiWhiteSpace(' ')(60,61) + TypeReferenceNode(typeReference)(61,66) + PsiElement('int32')('int32')(61,66) + PsiWhiteSpace(' ')(66,67) + ANTLRPsiNode(name)(67,68) + PsiElement(NAME)('y')(67,68) + PsiWhiteSpace(' ')(68,69) + PsiElement('=')('=')(69,70) + PsiWhiteSpace(' ')(70,71) + PsiElement(INTEGER_VALUE)('2')(71,72) + PsiElement(';')(';')(72,73) + PsiWhiteSpace('\n')(73,74) + PsiElement('}')('}')(74,75) diff --git a/src/test/resources/parsing/Service.proto b/src/test/resources/parsing/Service.proto new file mode 100644 index 0000000..814d237 --- /dev/null +++ b/src/test/resources/parsing/Service.proto @@ -0,0 +1,3 @@ +service TestService { + rpc Hello (HelloRequest) returns (HelloResponse); +} diff --git a/src/test/resources/parsing/Service.txt b/src/test/resources/parsing/Service.txt new file mode 100644 index 0000000..5f6fc1e --- /dev/null +++ b/src/test/resources/parsing/Service.txt @@ -0,0 +1,35 @@ +ProtobufFile: Service.proto(0,77) + ProtoRootNode(proto)(0,77) + ServiceNode(serviceBlock)(0,77) + PsiElement('service')('service')(0,7) + PsiWhiteSpace(' ')(7,8) + ANTLRPsiNode(name)(8,19) + PsiElement(NAME)('TestService')(8,19) + PsiWhiteSpace(' ')(19,20) + PsiElement('{')('{')(20,21) + PsiWhiteSpace('\n')(21,22) + PsiWhiteSpace(' ')(22,26) + RpcMethodNode(rpcMethod)(26,75) + PsiElement('rpc')('rpc')(26,29) + PsiWhiteSpace(' ')(29,30) + ANTLRPsiNode(name)(30,35) + PsiElement(NAME)('Hello')(30,35) + PsiWhiteSpace(' ')(35,36) + PsiElement('(')('(')(36,37) + RpcMethodTypeNode(rpcType)(37,49) + TypeReferenceNode(typeReference)(37,49) + ANTLRPsiNode(name)(37,49) + PsiElement(NAME)('HelloRequest')(37,49) + PsiElement(')')(')')(49,50) + PsiWhiteSpace(' ')(50,51) + PsiElement('returns')('returns')(51,58) + PsiWhiteSpace(' ')(58,59) + PsiElement('(')('(')(59,60) + RpcMethodTypeNode(rpcType)(60,73) + TypeReferenceNode(typeReference)(60,73) + ANTLRPsiNode(name)(60,73) + PsiElement(NAME)('HelloResponse')(60,73) + PsiElement(')')(')')(73,74) + PsiElement(';')(';')(74,75) + PsiWhiteSpace('\n')(75,76) + PsiElement('}')('}')(76,77) From 545170488cdff37dd151f3a5885aea8e24f3b361 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 21:51:48 +0300 Subject: [PATCH 12/14] Custom spacing settings for assignment operator + Add tests for formatter. --- build.gradle | 6 +- .../plugin/formatter/BlockFactory.java | 15 ++--- .../formatter/FormattingModelBuilder.java | 25 +++++++- .../jetbrains/plugin/formatter/LeafBlock.java | 3 +- .../plugin/formatter/ParentBlock.java | 16 ++--- .../plugin/formatter/ProtoFileBlock.java | 9 ++- ...rotoLanguageCodeStyleSettingsProvider.java | 1 + .../plugin/formatter/StatementBlock.java | 26 +++----- .../plugin/formatter/FormatterTest.java | 62 +++++++++++++++++++ .../formatting/custom_indent/Expected.proto | 5 ++ .../formatting/custom_indent/Source.proto | 5 ++ .../formatting/default/Expected.proto | 14 +++++ .../resources/formatting/default/Source.proto | 7 +++ .../Expected.proto | 5 ++ .../Source.proto | 5 ++ .../formatting/use_tab/Expected.proto | 5 ++ .../resources/formatting/use_tab/Source.proto | 5 ++ 17 files changed, 175 insertions(+), 39 deletions(-) create mode 100644 src/test/java/io/protostuff/jetbrains/plugin/formatter/FormatterTest.java create mode 100644 src/test/resources/formatting/custom_indent/Expected.proto create mode 100644 src/test/resources/formatting/custom_indent/Source.proto create mode 100644 src/test/resources/formatting/default/Expected.proto create mode 100644 src/test/resources/formatting/default/Source.proto create mode 100644 src/test/resources/formatting/disable_space_around_assignment_operator/Expected.proto create mode 100644 src/test/resources/formatting/disable_space_around_assignment_operator/Source.proto create mode 100644 src/test/resources/formatting/use_tab/Expected.proto create mode 100644 src/test/resources/formatting/use_tab/Source.proto diff --git a/build.gradle b/build.gradle index f25fac9..88ad590 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,11 @@ apply plugin: 'org.jetbrains.intellij' intellij { version = ideaVersion updateSinceUntilBuild = false - + // TODO: we do not need dependency on this plugin in runtime + // TODO: should be removed, but then tests are failing with + // TODO: ERROR: java.lang.ClassNotFoundException: com.intellij.lang.properties.PropertiesFileTypeFactory + plugins 'properties' +// downloadSources = false publish { username = project.hasProperty('jetbrainsUser') \ ? project.property('jetbrainsUser') \ diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java index b163cd4..5256d2e 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/BlockFactory.java @@ -4,6 +4,7 @@ import com.intellij.formatting.Block; import com.intellij.formatting.Indent; import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; @@ -21,7 +22,7 @@ class BlockFactory { static final Map registry = new HashMap<>(); static { - Factory FAIL_ROOT_NODE = (node, alignment, indent) -> { + Factory FAIL_ROOT_NODE = (node, alignment, indent, settings) -> { throw new IllegalStateException("Root node cannot be handled here"); }; register(rule(RULE_proto), FAIL_ROOT_NODE); @@ -73,22 +74,22 @@ private static void register(IElementType elementType, Factory factory) { registry.put(elementType, factory); } - static Block createBlock(ASTNode node, Alignment alignment, Indent indent) { + static Block createBlock(ASTNode node, Alignment alignment, Indent indent, CodeStyleSettings settings) { Factory factory = registry.get(node.getElementType()); if (factory == null) { // If element type is unknown it is best to keep existing formatting - return createLeaf(node, alignment, indent); + return createLeaf(node, alignment, indent, settings); } - return factory.create(node, alignment, indent); + return factory.create(node, alignment, indent, settings); } @NotNull - private static LeafBlock createLeaf(ASTNode node, Alignment alignment, Indent indent) { - return new LeafBlock(node, alignment, indent); + private static LeafBlock createLeaf(ASTNode node, Alignment alignment, Indent indent, CodeStyleSettings settings) { + return new LeafBlock(node, alignment, indent, settings); } interface Factory { - Block create(ASTNode node, Alignment alignment, Indent indent); + Block create(ASTNode node, Alignment alignment, Indent indent, CodeStyleSettings settings); } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java index 487a145..3b7213c 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java @@ -6,10 +6,11 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import io.protostuff.jetbrains.plugin.ProtoLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - +import static io.protostuff.jetbrains.plugin.formatter.StatementBlock.*; /** * @author Kostiantyn Shchepanovskyi */ @@ -22,7 +23,7 @@ public FormattingModel createModel(PsiElement element, CodeStyleSettings setting ASTNode fileNode = containingFile.getNode(); Wrap wrap = Wrap.createWrap(WrapType.NONE, false); Alignment alignment = Alignment.createAlignment(); - ProtoFileBlock block = new ProtoFileBlock(fileNode, wrap, alignment); + ProtoFileBlock block = new ProtoFileBlock(fileNode, wrap, alignment, settings); return FormattingModelProvider.createFormattingModelForPsiFile(containingFile, block, settings); } @@ -31,4 +32,24 @@ public FormattingModel createModel(PsiElement element, CodeStyleSettings setting public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { return null; } + + public static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) { + CommonCodeStyleSettings protoSettings = settings.getCommonSettings(ProtoLanguage.INSTANCE); + return new SpacingBuilder(settings, ProtoLanguage.INSTANCE) + .around(ASSIGN).spaceIf(protoSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS) + .after(LINE_COMMENT).spacing(0, 0, 1, true, 2) + .after(LCURLY).spacing(0, 0, 1, true, 2) + .before(RCURLY).spacing(0, 0, 1, true, 2) + .after(LPAREN).spacing(0, 0, 0, false, 0) + .before(RPAREN).spacing(0, 0, 0, false, 0) + .after(LSQUARE).spacing(0, 0, 0, false, 0) + .before(RSQUARE).spacing(0, 0, 0, false, 0) + .before(LT).spacing(0, 0, 0, false, 0) + .after(LT).spacing(0, 0, 0, false, 0) + .before(GT).spacing(0, 0, 0, false, 0) + .before(COMMA).spacing(0, 0, 0, false, 0) + .before(SEMICOLON).spacing(0, 0, 0, false, 0) + .after(COMMA).spacing(1, 1, 0, false, 0); + + } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java index 4de1f53..25bb38c 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/LeafBlock.java @@ -3,6 +3,7 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -13,7 +14,7 @@ class LeafBlock implements ASTBlock { private final Alignment alignment; private final Indent myIndent; - LeafBlock(ASTNode node, Alignment alignment, Indent indent) { + LeafBlock(ASTNode node, Alignment alignment, Indent indent, CodeStyleSettings settings) { this.node = node; this.alignment = alignment; myIndent = indent; diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java index 11cc562..e05f3ee 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ParentBlock.java @@ -2,6 +2,7 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; @@ -22,8 +23,9 @@ class ParentBlock extends StatementBlock { private final Set headerBlocks = new HashSet<>(); private Alignment childAlignment; - ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { - super(node, alignment, indent); + ParentBlock(@NotNull ASTNode node, @Nullable Alignment alignment, + Indent indent, CodeStyleSettings settings) { + super(node, alignment, indent, settings); childAlignment = Alignment.createAlignment(); } @@ -37,22 +39,22 @@ protected List buildChildren() { IElementType elementType = child.getElementType(); if (LCURLY.equals(elementType)) { state = State.AFTER_LEFT_CURLY_BRACE; - result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent(), settings)); } else if (RCURLY.equals(elementType)) { - result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent(), settings)); state = State.AFTER_RIGHT_CURLY_BRACE; } else { switch (state) { case BEFORE_LEFT_CURLY_BRACE: - Block block = BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent()); + Block block = BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent(), settings); headerBlocks.add(block); result.add(block); break; case AFTER_LEFT_CURLY_BRACE: - result.add(BlockFactory.createBlock(child, childAlignment, Indent.getNormalIndent(true))); + result.add(BlockFactory.createBlock(child, childAlignment, Indent.getNormalIndent(true), settings)); break; case AFTER_RIGHT_CURLY_BRACE: - result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent())); + result.add(BlockFactory.createBlock(child, myAlignment, Indent.getNoneIndent(), settings)); break; default: throw new IllegalStateException(state.toString()); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java index d86a8d8..79e97f3 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoFileBlock.java @@ -2,6 +2,7 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.tree.IElementType; @@ -20,8 +21,10 @@ */ class ProtoFileBlock extends AbstractBlock { - ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment) { + private final CodeStyleSettings settings; + ProtoFileBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, CodeStyleSettings settings) { super(node, wrap, alignment); + this.settings = settings; } @@ -36,7 +39,7 @@ protected List buildChildren() { appendProtoBlocks(child, blocks); } else { // Comments are not part of root rule, we have to append them separately - blocks.add(new LeafBlock(child, Alignment.createAlignment(), Indent.getNoneIndent())); + blocks.add(new LeafBlock(child, Alignment.createAlignment(), Indent.getNoneIndent(), settings)); } } child = child.getTreeNext(); @@ -49,7 +52,7 @@ private void appendProtoBlocks(ASTNode protoRootNode, List blocks) { Alignment alignment = Alignment.createAlignment(); while (child != null) { if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - Block block = createBlock(child, alignment, Indent.getNoneIndent()); + Block block = createBlock(child, alignment, Indent.getNoneIndent(), settings); blocks.add(block); } child = child.getTreeNext(); diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java index 3c1401b..8b925fd 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java @@ -50,6 +50,7 @@ public IndentOptionsEditor getIndentOptionsEditor() { public CommonCodeStyleSettings getDefaultCommonSettings() { CommonCodeStyleSettings settings = new CommonCodeStyleSettings(ProtoLanguage.INSTANCE); settings.initIndentOptions(); + settings.SPACE_AROUND_ASSIGNMENT_OPERATORS = true; return settings; } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java index 42867e5..4985427 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/StatementBlock.java @@ -40,26 +40,16 @@ class StatementBlock extends AbstractBlock { public static final IElementType LINE_COMMENT = ProtoParserDefinition.token(ProtoLexer.LINE_COMMENT); public static final IElementType COMMENT = ProtoParserDefinition.token(ProtoLexer.COMMENT); public static final IElementType COMMA = ProtoParserDefinition.token(ProtoLexer.COMMA); - private static final SpacingBuilder SB = new SpacingBuilder(new CodeStyleSettings(), ProtoLanguage.INSTANCE) - .after(LINE_COMMENT).spacing(0, 0, 1, true, 2) - .after(LCURLY).spacing(0, 0, 1, true, 2) - .before(RCURLY).spacing(0, 0, 1, true, 2) - .after(LPAREN).spacing(0, 0, 0, false, 0) - .before(RPAREN).spacing(0, 0, 0, false, 0) - .after(LSQUARE).spacing(0, 0, 0, false, 0) - .before(RSQUARE).spacing(0, 0, 0, false, 0) - .before(LT).spacing(0, 0, 0, false, 0) - .after(LT).spacing(0, 0, 0, false, 0) - .before(GT).spacing(0, 0, 0, false, 0) - .before(COMMA).spacing(0, 0, 0, false, 0) - .before(SEMICOLON).spacing(0, 0, 0, false, 0) - .after(COMMA).spacing(1, 1, 0, false, 0); + public static final IElementType ASSIGN = ProtoParserDefinition.token(ProtoLexer.ASSIGN); private final Indent indent; - - protected StatementBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent) { + protected final CodeStyleSettings settings; + private final SpacingBuilder spacingBuilder; + protected StatementBlock(@NotNull ASTNode node, @Nullable Alignment alignment, Indent indent, CodeStyleSettings settings) { super(node, null, alignment); this.indent = indent; + this.settings = settings; + spacingBuilder = FormattingModelBuilder.createSpacingBuilder(settings); } @Override @@ -68,7 +58,7 @@ protected List buildChildren() { List result = new ArrayList<>(); while (child != null) { if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - Block block = BlockFactory.createBlock(child, Alignment.createAlignment(), Indent.getNoneIndent()); + Block block = BlockFactory.createBlock(child, Alignment.createAlignment(), Indent.getNoneIndent(), settings); result.add(block); } child = child.getTreeNext(); @@ -79,7 +69,7 @@ protected List buildChildren() { @Nullable @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { - Spacing spacing = SB.getSpacing(this, child1, child2); + Spacing spacing = spacingBuilder.getSpacing(this, child1, child2); if (spacing == null) { return SPACE; } diff --git a/src/test/java/io/protostuff/jetbrains/plugin/formatter/FormatterTest.java b/src/test/java/io/protostuff/jetbrains/plugin/formatter/FormatterTest.java new file mode 100644 index 0000000..4ce1102 --- /dev/null +++ b/src/test/java/io/protostuff/jetbrains/plugin/formatter/FormatterTest.java @@ -0,0 +1,62 @@ +package io.protostuff.jetbrains.plugin.formatter; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import io.protostuff.jetbrains.plugin.ProtoLanguage; + +import java.util.function.Consumer; + +/** + * @author Kostiantyn Shchepanovskyi + */ +public class FormatterTest extends LightCodeInsightFixtureTestCase { + + @Override + protected String getTestDataPath() { + return "src/test/resources/formatting"; + } + + private void run(String test, Consumer settings) { + myFixture.configureByFiles(test + "/Source.proto"); + CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings protoSettings = codeStyleSettings.getCommonSettings(ProtoLanguage.INSTANCE); + settings.accept(protoSettings); + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + CodeStyleManager.getInstance(getProject()).reformat(myFixture.getFile()); + } + }.execute(); + myFixture.checkResultByFile(test + "/Expected.proto"); + } + + public void testDefaultFormatter() { + run("default", settings -> {}); + } + + public void testTab() { + run("use_tab", settings -> { + CommonCodeStyleSettings.IndentOptions indentOptions = settings.initIndentOptions(); + indentOptions.USE_TAB_CHARACTER = true; + }); + } + + public void testCustomIndent() { + run("custom_indent", settings -> { + CommonCodeStyleSettings.IndentOptions indentOptions = settings.initIndentOptions(); + indentOptions.INDENT_SIZE = 2; + }); + } + + public void testDisableSpaceAroundAssignmentOperator() { + run("disable_space_around_assignment_operator", settings -> { + settings.SPACE_AROUND_ASSIGNMENT_OPERATORS = false; + }); + } + +} diff --git a/src/test/resources/formatting/custom_indent/Expected.proto b/src/test/resources/formatting/custom_indent/Expected.proto new file mode 100644 index 0000000..2ae1fae --- /dev/null +++ b/src/test/resources/formatting/custom_indent/Expected.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message TestMessage { + optional int32 x = 1; +} diff --git a/src/test/resources/formatting/custom_indent/Source.proto b/src/test/resources/formatting/custom_indent/Source.proto new file mode 100644 index 0000000..eda0c3e --- /dev/null +++ b/src/test/resources/formatting/custom_indent/Source.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message TestMessage{ + optional int32 x = 1; +} diff --git a/src/test/resources/formatting/default/Expected.proto b/src/test/resources/formatting/default/Expected.proto new file mode 100644 index 0000000..8f2ee54 --- /dev/null +++ b/src/test/resources/formatting/default/Expected.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +message TestMessage { + optional int32 x = 1; +} + +enum TestEnum { + A = 1 [deprecated = true]; + B = 2; +} + +service TestService { + rpc Hello (HelloRequest) returns (HelloResponse); +} diff --git a/src/test/resources/formatting/default/Source.proto b/src/test/resources/formatting/default/Source.proto new file mode 100644 index 0000000..33a8cb8 --- /dev/null +++ b/src/test/resources/formatting/default/Source.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; + +message TestMessage{optional int32 x = 1;} + +enum TestEnum{A=1[deprecated=true];B=2;} + +service TestService{rpc Hello(HelloRequest)returns(HelloResponse);} diff --git a/src/test/resources/formatting/disable_space_around_assignment_operator/Expected.proto b/src/test/resources/formatting/disable_space_around_assignment_operator/Expected.proto new file mode 100644 index 0000000..4e6502f --- /dev/null +++ b/src/test/resources/formatting/disable_space_around_assignment_operator/Expected.proto @@ -0,0 +1,5 @@ +syntax="proto2"; + +message TestMessage { + optional int32 x=1; +} diff --git a/src/test/resources/formatting/disable_space_around_assignment_operator/Source.proto b/src/test/resources/formatting/disable_space_around_assignment_operator/Source.proto new file mode 100644 index 0000000..eda0c3e --- /dev/null +++ b/src/test/resources/formatting/disable_space_around_assignment_operator/Source.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message TestMessage{ + optional int32 x = 1; +} diff --git a/src/test/resources/formatting/use_tab/Expected.proto b/src/test/resources/formatting/use_tab/Expected.proto new file mode 100644 index 0000000..a2283ce --- /dev/null +++ b/src/test/resources/formatting/use_tab/Expected.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message TestMessage { + optional int32 x = 1; +} diff --git a/src/test/resources/formatting/use_tab/Source.proto b/src/test/resources/formatting/use_tab/Source.proto new file mode 100644 index 0000000..eda0c3e --- /dev/null +++ b/src/test/resources/formatting/use_tab/Source.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message TestMessage{ + optional int32 x = 1; +} From f462b70359b87742f662e117be712a29d72e7ffa Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 22:12:51 +0300 Subject: [PATCH 13/14] Disable formatter configuration parameters that are not fully supported --- .../formatter/FormattingModelBuilder.java | 1 + .../ProtoCodeStyleSettingsProvider.java | 6 ++--- ...rotoLanguageCodeStyleSettingsProvider.java | 23 +++++++++++++------ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java index 3b7213c..3e5300e 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/FormattingModelBuilder.java @@ -37,6 +37,7 @@ public static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) { CommonCodeStyleSettings protoSettings = settings.getCommonSettings(ProtoLanguage.INSTANCE); return new SpacingBuilder(settings, ProtoLanguage.INSTANCE) .around(ASSIGN).spaceIf(protoSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS) + .before(SEMICOLON).spaceIf(protoSettings.SPACE_BEFORE_SEMICOLON) .after(LINE_COMMENT).spacing(0, 0, 1, true, 2) .after(LCURLY).spacing(0, 0, 1, true, 2) .before(RCURLY).spacing(0, 0, 1, true, 2) diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java index 99d3917..a00ee84 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoCodeStyleSettingsProvider.java @@ -53,9 +53,9 @@ public ProtoCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSetti @Override protected void initTabs(CodeStyleSettings settings) { addIndentOptionsTab(settings); - addSpacesTab(settings); - addBlankLinesTab(settings); - addWrappingAndBracesTab(settings); +// addSpacesTab(settings); +// addBlankLinesTab(settings); +// addWrappingAndBracesTab(settings); } } } diff --git a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java index 8b925fd..69cf887 100644 --- a/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java +++ b/src/main/java/io/protostuff/jetbrains/plugin/formatter/ProtoLanguageCodeStyleSettingsProvider.java @@ -11,6 +11,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.intellij.psi.codeStyle.CommonCodeStyleSettings.END_OF_LINE; + /** * @author Kostiantyn Shchepanovskyi */ @@ -26,13 +28,17 @@ public Language getLanguage() { @Override public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { switch (settingsType) { - case SPACING_SETTINGS: - consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS"); - consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Space around assignment operator"); - break; - case BLANK_LINES_SETTINGS: - consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); - break; +// case SPACING_SETTINGS: +// consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS"); +// consumer.showStandardOptions("SPACE_SPACE_BEFORE_SEMICOLON"); +// consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Space around assignment operator"); +// break; +// case WRAPPING_AND_BRACES_SETTINGS: +// consumer.showStandardOptions("BRACE_STYLE"); +// break; +// case BLANK_LINES_SETTINGS: +// consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); +// break; default: break; } @@ -50,7 +56,10 @@ public IndentOptionsEditor getIndentOptionsEditor() { public CommonCodeStyleSettings getDefaultCommonSettings() { CommonCodeStyleSettings settings = new CommonCodeStyleSettings(ProtoLanguage.INSTANCE); settings.initIndentOptions(); + // TODO: we should define our own settings settings.SPACE_AROUND_ASSIGNMENT_OPERATORS = true; + settings.SPACE_BEFORE_SEMICOLON = false; + settings.BRACE_STYLE = END_OF_LINE; return settings; } From 5f5366ad332106efa292c979d6f54e8756e4af49 Mon Sep 17 00:00:00 2001 From: Konstantin Shchepanovskyi Date: Sun, 24 Apr 2016 22:18:36 +0300 Subject: [PATCH 14/14] Prepare for release 0.3.0 --- src/main/resources/META-INF/plugin.xml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 6396303..995c04f 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,7 +1,7 @@ io.protostuff.protostuff-jetbrains-plugin Protobuf Support - 0.1.0 + 0.3.0 Kostiantyn Shchepanovskyi Features:
    -
  • Syntax highlighting and validation (full proto3 support).
  • -
  • Fonts & Colors configuration (Editor → Colors & Fonts → Protobuf).
  • -
  • Structure View. Activation keys: Alt+7 and Ctrl+F12 (popup).
  • +
  • Full Proto3 support.
  • +
  • Syntax highlighting and validation.
  • +
  • Fonts & Colors configuration.
  • +
  • Structure View.
  • Brace matching.
  • -
  • Line and block commenting using Ctrl+/ and Ctrl+Shift+/.
  • +
  • Line and block commenting.
  • +
  • Code formatting.

]]>
+ v0.3.0 + (2016-04-24) +
    +
  • Add code formatting.
  • +
+ v0.2.0 (2016-04-16)