From ed152bccfaaa50df85622df0eb3b73e71f9c700e Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Fri, 26 Feb 2016 19:02:14 +0100 Subject: [PATCH] Implement smart enter processors for try, catch (parameters and body) and finally with tests Fixes #KT-10013 --- .../idea/editor/KotlinSmartEnterHandler.kt | 7 +- .../editor/fixers/KotlinCatchBodyFixer.kt | 34 +++++++ .../fixers/KotlinCatchParameterFixer.kt | 45 +++++++++ .../editor/fixers/KotlinFinallyBodyFixer.kt | 34 +++++++ .../idea/editor/fixers/KotlinTryBodyFixer.kt | 35 +++++++ .../codeInsight/smartEnter/SmartEnterTest.kt | 96 ++++++++++++++++++- 6 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchBodyFixer.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchParameterFixer.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFinallyBodyFixer.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinTryBodyFixer.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt index 17886598836..2b9f39b06a7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinSmartEnterHandler.kt @@ -49,7 +49,12 @@ class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() { KotlinFunctionDeclarationBodyFixer(), KotlinPropertySetterParametersFixer(), - KotlinPropertySetterBodyFixer() + KotlinPropertySetterBodyFixer(), + + KotlinTryBodyFixer(), + KotlinCatchParameterFixer(), + KotlinCatchBodyFixer(), + KotlinFinallyBodyFixer() ) addEnterProcessors(KotlinPlainEnterProcessor()) diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchBodyFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchBodyFixer.kt new file mode 100644 index 00000000000..8895c6ee424 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchBodyFixer.kt @@ -0,0 +1,34 @@ +/* + * 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.SmartEnterProcessorWithFixers +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler +import org.jetbrains.kotlin.psi.KtCatchClause +import org.jetbrains.kotlin.psi.psiUtil.endOffset + +class KotlinCatchBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtCatchClause) return + + if (psiElement.catchBody == null) { + editor.document.insertString(psiElement.endOffset, "{}") + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchParameterFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchParameterFixer.kt new file mode 100644 index 00000000000..f2f50d840ba --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinCatchParameterFixer.kt @@ -0,0 +1,45 @@ +/* + * 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.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.KtCatchClause +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset + +class KotlinCatchParameterFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtCatchClause) return + + val catchEnd = psiElement.node.findChildByType(KtTokens.CATCH_KEYWORD)!!.textRange!!.endOffset + + val parameterList = psiElement.parameterList + if (parameterList == null || parameterList.node.findChildByType(KtTokens.RPAR) == null) { + val endOffset = Math.min(psiElement.endOffset, psiElement.catchBody?.startOffset ?: Int.MAX_VALUE) + val parameter = parameterList?.parameters?.firstOrNull()?.text ?: "" + editor.document.replaceString(catchEnd, endOffset, "($parameter)") + processor.registerUnresolvedError(endOffset - 1) + } + else if (parameterList.parameters.firstOrNull()?.text.isNullOrBlank()) { + processor.registerUnresolvedError(parameterList.startOffset + 1) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFinallyBodyFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFinallyBodyFixer.kt new file mode 100644 index 00000000000..38b4e3674dc --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinFinallyBodyFixer.kt @@ -0,0 +1,34 @@ +/* + * 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.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.KtFinallySection + +class KotlinFinallyBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtFinallySection) return + + if (!psiElement.finalExpression.text.startsWith('{')) { + editor.document.insertString(psiElement.node.findChildByType(KtTokens.FINALLY_KEYWORD)!!.textRange.end, "{}") + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinTryBodyFixer.kt b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinTryBodyFixer.kt new file mode 100644 index 00000000000..69b251330e9 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/fixers/KotlinTryBodyFixer.kt @@ -0,0 +1,35 @@ +/* + * 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.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.KtTryExpression + +class KotlinTryBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is KtTryExpression) return + + if (psiElement.tryBlock.lBrace == null) { + val offset = psiElement.node.findChildByType(KtTokens.TRY_KEYWORD)?.textRange?.endOffset ?: return + editor.document.insertString(offset, "{}") + } + } +} \ No newline at end of file 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 0c5aa257035..761f5193d04 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/smartEnter/SmartEnterTest.kt @@ -1185,12 +1185,106 @@ class SmartEnterTest : KotlinLightCodeInsightFixtureTestCase() { """ ) + fun testTryBody() = doFunTest( + """ + try + """ + , + """ + try { + + } + """ + ) + + fun testCatchBody() = doFunTest( + """ + try { + } catch(e: Exception) + """ + , + """ + try { + } catch(e: Exception) { + + }${" "} + """ + ) + + fun testCatchParameter1() = doFunTest( + """ + try { + } catch + """ + , + """ + try { + } catch() { + } + """ + ) + + fun testCatchParameter2() = doFunTest( + """ + try { + } catch( + """ + , + """ + try { + } catch() { + } + """ + ) + + fun testCatchParameter3() = doFunTest( + """ + try { + } catch( {} + """ + , + """ + try { + } catch() { + } + """ + ) + + fun testCatchParameter4() = doFunTest( + """ + try { + } catch(e: Exception + """ + , + """ + try { + } catch(e: Exception) { + + } + """ + ) + fun testFinallyBody() = doFunTest( + """ + try { + } catch(e: Exception) { + } finally + """ + , + """ + try { + } catch(e: Exception) { + } finally { + + } + """ + ) + fun doFunTest(before: String, after: String) { fun String.withFunContext(): String { val bodyText = "//----\n${this.trimIndent()}\n//----" val withIndent = bodyText.prependIndent(" ") - return "fun method() {\n${withIndent}\n}" + return "fun method() {\n$withIndent\n}" } doTest(before.withFunContext(), after.withFunContext())