From 1001b4ae65b29f1f1e7c65414217db2009387f10 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Jun 2011 20:43:03 +0200 Subject: [PATCH] initial, really basic implementation of formatter --- idea/src/META-INF/plugin.xml | 2 + .../jet/plugin/formatter/JetBlock.java | 146 ++++++++++++++++++ .../formatter/JetFormattingModelBuilder.java | 29 ++++ .../formatter/JetIndentOptionsProvider.java | 38 +++++ 4 files changed, 215 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java create mode 100644 idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java create mode 100644 idea/src/org/jetbrains/jet/plugin/formatter/JetIndentOptionsProvider.java diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 5a9f30decb1..066f18ef40d 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -28,6 +28,7 @@ + @@ -35,5 +36,6 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java new file mode 100644 index 00000000000..971ff4ab27e --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java @@ -0,0 +1,146 @@ +package org.jetbrains.jet.plugin.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.TokenType; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author yole + */ +public class JetBlock implements ASTBlock { + private ASTNode myNode; + private Alignment myAlignment; + private Indent myIndent; + private Wrap myWrap; + private CodeStyleSettings mySettings; + private List mySubBlocks; + + private static final TokenSet CODE_BLOCKS = TokenSet.create( + JetNodeTypes.BLOCK, + JetNodeTypes.CLASS_BODY, + JetNodeTypes.FUNCTION_LITERAL); + + private static final TokenSet STATEMENT_PARTS = TokenSet.create( + JetNodeTypes.THEN, + JetNodeTypes.ELSE); + + public JetBlock(ASTNode node, Alignment alignment, Indent indent, Wrap wrap, CodeStyleSettings settings) { + myNode = node; + myAlignment = alignment; + myIndent = indent; + myWrap = wrap; + mySettings = settings; + } + + @Override + public ASTNode getNode() { + return myNode; + } + + @NotNull + @Override + public TextRange getTextRange() { + return myNode.getTextRange(); + } + + @Override + public Wrap getWrap() { + return myWrap; + } + + @Override + public Indent getIndent() { + return myIndent; + } + + @Override + public Alignment getAlignment() { + return myAlignment; + } + + @NotNull + @Override + public List getSubBlocks() { + if (mySubBlocks == null) { + mySubBlocks = buildSubBlocks(); + } + return new ArrayList(mySubBlocks); + } + + private List buildSubBlocks() { + List blocks = new ArrayList(); + for (ASTNode child = myNode.getFirstChildNode(); child != null; child = child.getTreeNext()) { + + IElementType childType = child.getElementType(); + + if (child.getTextRange().getLength() == 0) continue; + + if (childType == TokenType.WHITE_SPACE) { + continue; + } + + blocks.add(buildSubBlock(child)); + } + return Collections.unmodifiableList(blocks); + } + + private Block buildSubBlock(ASTNode child) { + Wrap wrap = null; + Indent childIndent = Indent.getNoneIndent(); + Alignment childAlignment = null; + + if (CODE_BLOCKS.contains(myNode.getElementType())) { + childIndent = indentIfNotBrace(child); + } + else if (myNode.getElementType() == JetNodeTypes.WHEN) { + childIndent = indentIfNotBrace(child); + } + else if (STATEMENT_PARTS.contains(myNode.getElementType()) && child.getElementType() != JetNodeTypes.BLOCK) { + childIndent = Indent.getNormalIndent(); + } + + return new JetBlock(child, childAlignment, childIndent, wrap, mySettings); + } + + private static Indent indentIfNotBrace(ASTNode child) { + return child.getElementType() == JetTokens.RBRACE || child.getElementType() == JetTokens.LBRACE + ? Indent.getNoneIndent() + : Indent.getNormalIndent(); + } + + @Override + public Spacing getSpacing(Block block, Block block1) { + return null; + } + + @NotNull + @Override + public ChildAttributes getChildAttributes(int newChildIndex) { + Indent childIndent = Indent.getNoneIndent(); + if (CODE_BLOCKS.contains(myNode.getElementType()) || myNode.getElementType() == JetNodeTypes.WHEN) { + childIndent = Indent.getNormalIndent(); + } + return new ChildAttributes(childIndent, null); + } + + @Override + public boolean isIncomplete() { + return false; + } + + @Override + public boolean isLeaf() { + return myNode.getFirstChildNode() == null; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java new file mode 100644 index 00000000000..852e8a05a30 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java @@ -0,0 +1,29 @@ +package org.jetbrains.jet.plugin.formatter; + +import com.intellij.formatting.FormattingModel; +import com.intellij.formatting.FormattingModelBuilder; +import com.intellij.formatting.FormattingModelProvider; +import com.intellij.formatting.Indent; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import org.jetbrains.annotations.NotNull; + +/** + * @author yole + */ +public class JetFormattingModelBuilder implements FormattingModelBuilder { + @NotNull + @Override + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + final JetBlock block = new JetBlock(element.getNode(), null, Indent.getNoneIndent(), null, settings); + return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings); + } + + @Override + public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) { + return null; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetIndentOptionsProvider.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetIndentOptionsProvider.java new file mode 100644 index 00000000000..eed4b2bd647 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetIndentOptionsProvider.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.plugin.formatter; + +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.FileTypeIndentOptionsProvider; +import org.jetbrains.jet.plugin.JetFileType; + +/** + * @author yole + */ +public class JetIndentOptionsProvider implements FileTypeIndentOptionsProvider { + @Override + public CodeStyleSettings.IndentOptions createIndentOptions() { + return new CodeStyleSettings.IndentOptions(); + } + + @Override + public FileType getFileType() { + return JetFileType.INSTANCE; + } + + @Override + public IndentOptionsEditor createOptionsEditor() { + return new SmartIndentOptionsEditor(); + } + + @Override + public String getPreviewText() { + return ""; + } + + @Override + public void prepareForReformat(PsiFile psiFile) { + } +}