diff --git a/.idea/dictionaries/Nikolay_Krasko.xml b/.idea/dictionaries/Nikolay_Krasko.xml
index 12359831dfd..6ccd21192dd 100644
--- a/.idea/dictionaries/Nikolay_Krasko.xml
+++ b/.idea/dictionaries/Nikolay_Krasko.xml
@@ -6,6 +6,7 @@
kdoc
memoized
multiline
+ preprocess
redeclarations
subclassed
subgraph
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index cc9d29f9d27..4df3f79c1b9 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -268,7 +268,10 @@
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java
index bf3d6ff478f..70c5ed11b2e 100644
--- a/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java
+++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java
@@ -134,7 +134,7 @@ public class CodeInsightUtils {
}
@Nullable
- private static PsiElement getElementAtOffsetIgnoreWhitespaceBefore(@NotNull PsiFile file, int offset) {
+ public static PsiElement getElementAtOffsetIgnoreWhitespaceBefore(@NotNull PsiFile file, int offset) {
PsiElement element = file.findElementAt(offset);
if (element instanceof PsiWhiteSpace) {
return file.findElementAt(element.getTextRange().getEndOffset());
@@ -143,7 +143,7 @@ public class CodeInsightUtils {
}
@Nullable
- private static PsiElement getElementAtOffsetIgnoreWhitespaceAfter(@NotNull PsiFile file, int offset) {
+ public static PsiElement getElementAtOffsetIgnoreWhitespaceAfter(@NotNull PsiFile file, int offset) {
PsiElement element = file.findElementAt(offset - 1);
if (element instanceof PsiWhiteSpace) {
return file.findElementAt(element.getTextRange().getStartOffset() - 1);
diff --git a/idea/src/org/jetbrains/jet/plugin/editor/KotlinEnterHandler.kt b/idea/src/org/jetbrains/jet/plugin/editor/KotlinEnterHandler.kt
new file mode 100644
index 00000000000..8e89d36d18c
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/editor/KotlinEnterHandler.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010-2014 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 org.jetbrains.jet.plugin.editor
+
+import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter
+import com.intellij.psi.PsiFile
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.util.Ref
+import com.intellij.openapi.actionSystem.DataContext
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler
+import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate
+import com.intellij.codeInsight.CodeInsightSettings
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.codeStyle.CodeStyleManager
+import org.jetbrains.jet.lang.psi.JetFile
+import com.intellij.util.IncorrectOperationException
+import org.jetbrains.jet.lexer.JetTokens
+import org.jetbrains.jet.lang.psi.JetFunctionLiteral
+import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils
+import com.intellij.openapi.diagnostic.Logger
+import com.intellij.psi.tree.TokenSet
+import com.intellij.psi.PsiWhiteSpace
+
+public class KotlinEnterHandler: EnterHandlerDelegateAdapter() {
+ class object {
+ private val LOG = Logger.getInstance(javaClass())
+ private val FORCE_INDENT_IN_LAMBDA_AFTER = TokenSet.create(JetTokens.ARROW, JetTokens.LBRACE)
+ }
+
+ override fun preprocessEnter(
+ file: PsiFile,
+ editor: Editor,
+ caretOffsetRef: Ref,
+ caretAdvance: Ref,
+ dataContext: DataContext,
+ originalHandler: EditorActionHandler?
+ ): EnterHandlerDelegate.Result? {
+ if (file !is JetFile) return EnterHandlerDelegate.Result.Continue
+ if (!CodeInsightSettings.getInstance()!!.SMART_INDENT_ON_ENTER) return EnterHandlerDelegate.Result.Continue
+
+ val document = editor.getDocument()
+ val text = document.getCharsSequence()
+ val caretOffset = caretOffsetRef.get()!!.toInt()
+
+ if (caretOffset !in 0..text.length()) return EnterHandlerDelegate.Result.Continue
+
+ val elementAt = file.findElementAt(caretOffset)
+ if (elementAt is PsiWhiteSpace && ("\n" in elementAt.getText()!!)) return EnterHandlerDelegate.Result.Continue
+
+ // Indent for LBRACE can be removed after fixing IDEA-124917
+ val elementBefore = CodeInsightUtils.getElementAtOffsetIgnoreWhitespaceAfter(file, caretOffset);
+ val elementAfter = CodeInsightUtils.getElementAtOffsetIgnoreWhitespaceBefore(file, caretOffset);
+
+ val isAfterLBraceOrArrow = elementBefore != null && elementBefore.getNode()!!.getElementType() in FORCE_INDENT_IN_LAMBDA_AFTER
+ val isBeforeRBrace = elementAfter == null || elementAfter.getNode()!!.getElementType() == JetTokens.RBRACE
+
+ if (isAfterLBraceOrArrow && isBeforeRBrace && (elementBefore!!.getParent() is JetFunctionLiteral)) {
+ originalHandler?.execute(editor, dataContext)
+ PsiDocumentManager.getInstance(file.getProject()).commitDocument(document)
+
+ try {
+ CodeStyleManager.getInstance(file.getProject())!!.adjustLineIndent(file, editor.getCaretModel().getOffset())
+ }
+ catch (e: IncorrectOperationException) {
+ LOG.error(e);
+ }
+
+ return EnterHandlerDelegate.Result.DefaultForceIndent
+ }
+
+ return EnterHandlerDelegate.Result.Continue
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLabmdaAfterArrow.after.kt b/idea/testData/indentationOnNewline/InLabmdaAfterArrow.after.kt
new file mode 100644
index 00000000000..6afa2cee7ce
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLabmdaAfterArrow.after.kt
@@ -0,0 +1,3 @@
+val a: (String) -> String = { some ->
+
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLabmdaAfterArrow.kt b/idea/testData/indentationOnNewline/InLabmdaAfterArrow.kt
new file mode 100644
index 00000000000..164542935f8
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLabmdaAfterArrow.kt
@@ -0,0 +1 @@
+val a: (String) -> String = { some ->}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.after.kt b/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.after.kt
new file mode 100644
index 00000000000..6afa2cee7ce
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.after.kt
@@ -0,0 +1,3 @@
+val a: (String) -> String = { some ->
+
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.kt b/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.kt
new file mode 100644
index 00000000000..5ef728c5c59
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.kt
@@ -0,0 +1 @@
+val a: (String) -> String = { some -> }
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaBeforeParams.after.kt b/idea/testData/indentationOnNewline/InLambdaBeforeParams.after.kt
new file mode 100644
index 00000000000..61f1cfec2d2
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaBeforeParams.after.kt
@@ -0,0 +1,3 @@
+val a: (String) -> String = {
+ some ->
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaBeforeParams.kt b/idea/testData/indentationOnNewline/InLambdaBeforeParams.kt
new file mode 100644
index 00000000000..8d3791b2b04
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaBeforeParams.kt
@@ -0,0 +1,2 @@
+val a: (String) -> String = { some ->
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.after.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.after.kt
new file mode 100644
index 00000000000..c960c0abe96
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.after.kt
@@ -0,0 +1,10 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test().foo()?.foo({ "str" }).foo {
+
+ }
+}
+
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.kt
new file mode 100644
index 00000000000..2a40ece4201
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.kt
@@ -0,0 +1,8 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test().foo()?.foo({ "str" }).foo {}
+}
+
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.after.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.after.kt
new file mode 100644
index 00000000000..5a815c87f78
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.after.kt
@@ -0,0 +1,9 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test().foo()?.foo({ "str" }).foo {
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.kt
new file mode 100644
index 00000000000..74260e2a4a7
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.kt
@@ -0,0 +1,8 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test().foo()?.foo({ "str" }).foo { }
+}
+
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.after.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.after.kt
new file mode 100644
index 00000000000..5906bf8206d
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.after.kt
@@ -0,0 +1,11 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test()
+ .foo { "Str" }
+ .foo {
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.kt
new file mode 100644
index 00000000000..60c5386e244
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.kt
@@ -0,0 +1,9 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test()
+ .foo { "Str" }
+ .foo {}
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.after.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.after.kt
new file mode 100644
index 00000000000..5906bf8206d
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.after.kt
@@ -0,0 +1,11 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test()
+ .foo { "Str" }
+ .foo {
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.kt b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.kt
new file mode 100644
index 00000000000..423bcbc9a93
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.kt
@@ -0,0 +1,9 @@
+class Test {
+ fun foo(f: (String) -> String): Test = this
+}
+
+fun test() {
+ val abc = Test()
+ .foo { "Str" }
+ .foo { }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt b/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt
new file mode 100644
index 00000000000..c1453e9eee1
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt
@@ -0,0 +1,4 @@
+val a: (String) -> String = {
+ some ->
+
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.kt b/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.kt
new file mode 100644
index 00000000000..ce92c7d239e
--- /dev/null
+++ b/idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.kt
@@ -0,0 +1,3 @@
+val a: (String) -> String = {
+ some ->
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java
index acf6999031e..a9e4d02403a 100644
--- a/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java
+++ b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java
@@ -164,6 +164,46 @@ public class JetTypingIndentationTestBaseGenerated extends AbstractJetTypingInde
doNewlineTest("idea/testData/indentationOnNewline/InExpressionsParenthesesBeforeOperand.after.kt");
}
+ @TestMetadata("InLabmdaAfterArrow.after.kt")
+ public void testInLabmdaAfterArrow() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLabmdaAfterArrow.after.kt");
+ }
+
+ @TestMetadata("InLambdaAfterArrowWithSpaces.after.kt")
+ public void testInLambdaAfterArrowWithSpaces() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.after.kt");
+ }
+
+ @TestMetadata("InLambdaBeforeParams.after.kt")
+ public void testInLambdaBeforeParams() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaBeforeParams.after.kt");
+ }
+
+ @TestMetadata("InLambdaInsideChainCallSameLine.after.kt")
+ public void testInLambdaInsideChainCallSameLine() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.after.kt");
+ }
+
+ @TestMetadata("InLambdaInsideChainCallSameLineWithSpaces.after.kt")
+ public void testInLambdaInsideChainCallSameLineWithSpaces() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.after.kt");
+ }
+
+ @TestMetadata("InLambdaInsideChainCallWithNewLine.after.kt")
+ public void testInLambdaInsideChainCallWithNewLine() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.after.kt");
+ }
+
+ @TestMetadata("InLambdaInsideChainCallWithNewLineWithSpaces.after.kt")
+ public void testInLambdaInsideChainCallWithNewLineWithSpaces() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.after.kt");
+ }
+
+ @TestMetadata("InMultilineLambdaAfterArrow.after.kt")
+ public void testInMultilineLambdaAfterArrow() throws Exception {
+ doNewlineTest("idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt");
+ }
+
@TestMetadata("NotFirstParameter.after.kt")
public void testNotFirstParameter() throws Exception {
doNewlineTest("idea/testData/indentationOnNewline/NotFirstParameter.after.kt");