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) {
+ }
+}