Smart enter for fun declaration
#KT-3600 In Progress
This commit is contained in:
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
||||
import org.jetbrains.jet.lang.psi.JetIfExpression
|
||||
import org.jetbrains.jet.lang.psi.JetForExpression
|
||||
import org.jetbrains.jet.lang.psi.JetParameter
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.jet.JetNodeTypes
|
||||
import org.jetbrains.jet.lang.psi.JetLoopExpression
|
||||
@@ -48,7 +49,10 @@ public class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() {
|
||||
KotlinWhenSubjectCaretFixer(),
|
||||
KotlinMissingWhenBodyFixer(),
|
||||
|
||||
KotlinDoWhileFixer()
|
||||
KotlinDoWhileFixer(),
|
||||
|
||||
KotlinFunctionParametersFixer(),
|
||||
KotlinFunctionDeclarationBodyFixer()
|
||||
)
|
||||
|
||||
addEnterProcessors(KotlinPlainEnterProcessor())
|
||||
@@ -62,7 +66,9 @@ public class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() {
|
||||
while (atCaret != null) {
|
||||
if (atCaret?.isJetStatement() == true) return atCaret
|
||||
|
||||
if (atCaret is JetDeclaration && (atCaret?.getParent() !is JetForExpression)) {
|
||||
if (atCaret is JetDeclaration &&
|
||||
atCaret !is JetParameter &&
|
||||
(atCaret?.getParent() !is JetForExpression)) {
|
||||
return atCaret
|
||||
}
|
||||
|
||||
@@ -94,7 +100,9 @@ public class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() {
|
||||
val old = settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE
|
||||
settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false
|
||||
val elt = PsiTreeUtil.getParentOfType(file.findElementAt(caretOffset - 1), javaClass<JetBlockExpression>())
|
||||
reformat(elt)
|
||||
if (elt != null) {
|
||||
reformat(elt)
|
||||
}
|
||||
settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = old
|
||||
editor.getCaretModel().moveToOffset(caretOffset - 1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.fixers
|
||||
|
||||
import com.intellij.lang.SmartEnterProcessorWithFixers
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import org.jetbrains.jet.lang.psi.JetFunction
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
|
||||
|
||||
public class KotlinFunctionDeclarationBodyFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
|
||||
override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) {
|
||||
if (psiElement !is JetNamedFunction) return
|
||||
if (psiElement.getBodyExpression() != null|| psiElement.getEqualsToken() != null) return
|
||||
|
||||
val parentDeclaration = PsiTreeUtil.getParentOfType(psiElement, javaClass<JetDeclaration>())
|
||||
if (parentDeclaration is JetClassOrObject) {
|
||||
if (JetPsiUtil.isTrait(parentDeclaration) || psiElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val doc = editor.getDocument()
|
||||
var endOffset = psiElement.range.end
|
||||
|
||||
if (psiElement.getText()?.last() == ';') {
|
||||
doc.deleteString(endOffset - 1, endOffset)
|
||||
endOffset--
|
||||
}
|
||||
|
||||
doc.insertString(endOffset, "{}")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.fixers
|
||||
|
||||
import com.intellij.lang.SmartEnterProcessorWithFixers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
|
||||
|
||||
public class KotlinFunctionParametersFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
|
||||
override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) {
|
||||
if (psiElement !is JetNamedFunction) return;
|
||||
|
||||
val parameterList = psiElement.getValueParameterList()
|
||||
if (parameterList == null) {
|
||||
val identifier = psiElement.getNameIdentifier()
|
||||
if (identifier == null) return
|
||||
|
||||
// Insert () after name or after type parameters list when it placed after name
|
||||
val offset = Math.max(identifier.range.end, psiElement.getTypeParameterList()?.range?.end ?: psiElement.range.start)
|
||||
editor.getDocument().insertString(offset, "()")
|
||||
processor.registerUnresolvedError(offset + 1)
|
||||
}
|
||||
else {
|
||||
val rParen = parameterList.getLastChild()
|
||||
if (rParen == null) return
|
||||
|
||||
if (")" != rParen.getText()) {
|
||||
val params = parameterList.getParameters()
|
||||
val offset = if (params.isEmpty()) parameterList.range.start + 1 else params.last().range.end
|
||||
editor.getDocument().insertString(offset, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -723,6 +723,124 @@ class SmartEnterTest : JetLightCodeInsightFixtureTestCase() {
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody() = doFileTest(
|
||||
"""
|
||||
fun test<caret>()
|
||||
"""
|
||||
,
|
||||
"""
|
||||
fun test() {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody1() = doFileTest(
|
||||
"""
|
||||
fun test<caret>
|
||||
"""
|
||||
,
|
||||
"""
|
||||
fun test() {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody2() = doFileTest(
|
||||
"""
|
||||
fun (p: Int, s: String<caret>
|
||||
"""
|
||||
,
|
||||
"""
|
||||
fun (p: Int, s: String) {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody3() = doFileTest(
|
||||
"""
|
||||
trait Some {
|
||||
fun (<caret>p: Int)
|
||||
}
|
||||
"""
|
||||
,
|
||||
"""
|
||||
trait Some {
|
||||
fun (p: Int)
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody4() = doFileTest(
|
||||
"""
|
||||
class Some {
|
||||
abstract fun (<caret>p: Int)
|
||||
}
|
||||
"""
|
||||
,
|
||||
"""
|
||||
class Some {
|
||||
abstract fun (p: Int)
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody5() = doFileTest(
|
||||
"""
|
||||
class Some {
|
||||
fun test(<caret>p: Int) = 1
|
||||
}
|
||||
"""
|
||||
,
|
||||
"""
|
||||
class Some {
|
||||
fun test(p: Int) = 1
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody6() = doFileTest(
|
||||
"""
|
||||
fun test(<caret>p: Int) {
|
||||
}
|
||||
"""
|
||||
,
|
||||
"""
|
||||
fun test(p: Int) {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody7() = doFileTest(
|
||||
"""
|
||||
trait T
|
||||
fun <U> other() where U: T<caret>
|
||||
""",
|
||||
"""
|
||||
trait T
|
||||
fun <U> other() where U : T {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun testFunBody8() = doFileTest(
|
||||
"""
|
||||
fun Int.other<caret>
|
||||
""",
|
||||
"""
|
||||
fun Int.other() {
|
||||
<caret>
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
fun doFunTest(before: String, after: String) {
|
||||
fun String.withFunContext(): String {
|
||||
val bodyText = "//----${this.trimIndent()}//----"
|
||||
@@ -734,6 +852,10 @@ class SmartEnterTest : JetLightCodeInsightFixtureTestCase() {
|
||||
doTest(before.withFunContext(), after.withFunContext())
|
||||
}
|
||||
|
||||
fun doFileTest(before: String, after: String) {
|
||||
doTest(before.trimIndent().removeFirstEmptyLines(), after.trimIndent().removeFirstEmptyLines())
|
||||
}
|
||||
|
||||
fun doTest(before: String, after: String) {
|
||||
myFixture.configureByText(JetFileType.INSTANCE, before)
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT)
|
||||
@@ -741,4 +863,6 @@ class SmartEnterTest : JetLightCodeInsightFixtureTestCase() {
|
||||
}
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor = LightCodeInsightFixtureTestCase.JAVA_LATEST
|
||||
|
||||
private fun String.removeFirstEmptyLines() = this.split("\n").dropWhile { it.isEmpty() }.joinToString(separator = "\n")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user