From f3e68fdeaa86b0325ce1a9b4e1fcfe9af17b45e2 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Tue, 23 Feb 2016 16:35:33 +0100 Subject: [PATCH] Implement smart enter processors for property setter with tests Fixes #KT-9996 --- .../idea/editor/KotlinSmartEnterHandler.kt | 5 +- .../KotlinFunctionDeclarationBodyFixer.kt | 10 +- .../fixers/KotlinPropertySetterBodyFixer.kt | 59 ++++++ .../KotlinPropertySetterParametersFixer.kt | 63 +++++++ .../codeInsight/smartEnter/SmartEnterTest.kt | 169 ++++++++++++++++++ 5 files changed, 300 insertions(+), 6 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinPropertySetterBodyFixer.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinPropertySetterParametersFixer.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt index 6563551863f..17886598836 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt @@ -46,7 +46,10 @@ class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() { KotlinDoWhileFixer(), KotlinFunctionParametersFixer(), - KotlinFunctionDeclarationBodyFixer() + KotlinFunctionDeclarationBodyFixer(), + + KotlinPropertySetterParametersFixer(), + KotlinPropertySetterBodyFixer() ) addEnterProcessors(KotlinPlainEnterProcessor()) diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt index d83c85b6e6b..4b356e53a4e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt @@ -18,13 +18,13 @@ package org.jetbrains.kotlin.idea.editor.fixers import com.intellij.lang.SmartEnterProcessorWithFixers import com.intellij.openapi.editor.Editor -import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtPsiUtil +import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType @@ -43,7 +43,7 @@ class KotlinFunctionDeclarationBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtPropertyAccessor) return + + if (!psiElement.isSetter) return + + if (psiElement.bodyExpression != null || psiElement.equalsToken != null) return + + val parentDeclaration = psiElement.getStrictParentOfType() + if (parentDeclaration is KtClassOrObject) { + if (KtPsiUtil.isTrait(parentDeclaration) || psiElement.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { + return + } + } + + //setter without parameter and body is valid + if (psiElement.namePlaceholder.endOffset == psiElement.endOffset) return + + val doc = editor.document + var endOffset = psiElement.range.end + + if (psiElement.text?.last() == ';') { + doc.deleteString(endOffset - 1, endOffset) + endOffset-- + } + + doc.insertString(endOffset, "{}") + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinPropertySetterParametersFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinPropertySetterParametersFixer.kt new file mode 100644 index 00000000000..dff3c3fca17 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinPropertySetterParametersFixer.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2016 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.kotlin.idea.editor.fixers + +import com.intellij.lang.ASTNode +import com.intellij.lang.SmartEnterProcessorWithFixers +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtPropertyAccessor +import org.jetbrains.kotlin.psi.psiUtil.endOffset + + +class KotlinPropertySetterParametersFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtPropertyAccessor) return; + + if (!psiElement.isSetter) return + + val parameter = psiElement.parameter + + if (!parameter?.text.isNullOrBlank() && psiElement.rightParenthesis != null) return + + //setter without parameter and body is valid + if (psiElement.namePlaceholder.endOffset == psiElement.endOffset) return + + val doc = editor.document + + val parameterOffset = (psiElement.leftParenthesis?.startOffset ?: return) + 1 + + if (parameter?.text.isNullOrBlank()) { + if (psiElement.rightParenthesis == null) { + doc.insertString(parameterOffset, "value)") + } + else { + doc.insertString(parameterOffset, "value") + } + } + else if (psiElement.rightParenthesis == null) { + doc.insertString(parameterOffset + parameter!!.text.length, ")") + } + } + + private val KtPropertyAccessor.leftParenthesis : ASTNode? + get() = node.findChildByType(KtTokens.LPAR) + +} + diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt index 61efad1e269..0c5aa257035 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt @@ -1016,6 +1016,175 @@ class SmartEnterTest : KotlinLightCodeInsightFixtureTestCase() { """ ) + fun testSetter1() = doFileTest( + """ + var a : Int = 0 + set + """ + , + """ + var a : Int = 0 + set + + """ + ) + + fun testSetter2() = doFileTest( + """ + var a : Int = 0 + set( + """ + , + """ + var a : Int = 0 + set(value) { + + } + """ + ) + + fun testSetter3() = doFileTest( + """ + var a : Int = 0 + set() + """ + , + """ + var a : Int = 0 + set(value) { + + } + """ + ) + + fun testSetter4() = doFileTest( + """ + var a : Int = 0 + set(v) + """ + , + """ + var a : Int = 0 + set(v) { + + } + """ + ) + + fun testSetter5() = doFileTest( + """ + var a : Int = 0 + set() { + } + """ + , + """ + var a : Int = 0 + set(value) { + + } + """ + ) + fun testSetter6() = doFileTest( + """ + var a : Int = 0 + set(v) { + } + """ + , + """ + var a : Int = 0 + set(v) { + + } + """ + ) + + fun testSetterPrivate1() = doFileTest( + """ + var a : Int = 0 + private set + """ + , + """ + var a : Int = 0 + private set + + """ + ) + + fun testSetterPrivate2() = doFileTest( + """ + var a : Int = 0 + private set( + """ + , + """ + var a : Int = 0 + private set(value) { + + } + """ + ) + + fun testSetterPrivate3() = doFileTest( + """ + var a : Int = 0 + private set() + """ + , + """ + var a : Int = 0 + private set(value) { + + } + """ + ) + + fun testSetterPrivate4() = doFileTest( + """ + var a : Int = 0 + private set(v) + """ + , + """ + var a : Int = 0 + private set(v) { + + } + """ + ) + + fun testSetterPrivate5() = doFileTest( + """ + var a : Int = 0 + private set() { + } + """ + , + """ + var a : Int = 0 + private set(value) { + + } + """ + ) + + fun testSetterPrivate6() = doFileTest( + """ + var a : Int = 0 + private set(v) { + } + """ + , + """ + var a : Int = 0 + private set(v) { + + } + """ + ) + fun doFunTest(before: String, after: String) { fun String.withFunContext(): String { val bodyText = "//----\n${this.trimIndent()}\n//----"