From 3f96b4775f16108c43a6a1ab7f199ebbe1d40050 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 8 May 2014 19:52:35 +0400 Subject: [PATCH] Better indententation on enter in lambdas --- .idea/dictionaries/Nikolay_Krasko.xml | 1 + idea/src/META-INF/plugin.xml | 3 + .../plugin/codeInsight/CodeInsightUtils.java | 4 +- .../jet/plugin/editor/KotlinEnterHandler.kt | 87 +++++++++++++++++++ .../InLabmdaAfterArrow.after.kt | 3 + .../InLabmdaAfterArrow.kt | 1 + .../InLambdaAfterArrowWithSpaces.after.kt | 3 + .../InLambdaAfterArrowWithSpaces.kt | 1 + .../InLambdaBeforeParams.after.kt | 3 + .../InLambdaBeforeParams.kt | 2 + .../InLambdaInsideChainCallSameLine.after.kt | 10 +++ .../InLambdaInsideChainCallSameLine.kt | 8 ++ ...InsideChainCallSameLineWithSpaces.after.kt | 9 ++ ...LambdaInsideChainCallSameLineWithSpaces.kt | 8 ++ ...nLambdaInsideChainCallWithNewLine.after.kt | 11 +++ .../InLambdaInsideChainCallWithNewLine.kt | 9 ++ ...ideChainCallWithNewLineWithSpaces.after.kt | 11 +++ ...bdaInsideChainCallWithNewLineWithSpaces.kt | 9 ++ .../InMultilineLambdaAfterArrow.after.kt | 4 + .../InMultilineLambdaAfterArrow.kt | 3 + ...JetTypingIndentationTestBaseGenerated.java | 40 +++++++++ 21 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/editor/KotlinEnterHandler.kt create mode 100644 idea/testData/indentationOnNewline/InLabmdaAfterArrow.after.kt create mode 100644 idea/testData/indentationOnNewline/InLabmdaAfterArrow.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaAfterArrowWithSpaces.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaBeforeParams.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaBeforeParams.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLine.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallSameLineWithSpaces.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLine.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.after.kt create mode 100644 idea/testData/indentationOnNewline/InLambdaInsideChainCallWithNewLineWithSpaces.kt create mode 100644 idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt create mode 100644 idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.kt 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");