Implement display of code construct start for Kotlin
#KT-20470 Fixed
This commit is contained in:
@@ -774,6 +774,12 @@
|
|||||||
|
|
||||||
<gotoRelatedProvider implementation="org.jetbrains.kotlin.idea.goto.KotlinExpectOrActualGotoRelatedProvider"/>
|
<gotoRelatedProvider implementation="org.jetbrains.kotlin.idea.goto.KotlinExpectOrActualGotoRelatedProvider"/>
|
||||||
|
|
||||||
|
<declarationRangeHandler key="org.jetbrains.kotlin.psi.KtClassOrObject"
|
||||||
|
implementationClass="org.jetbrains.kotlin.idea.codeInsight.KotlinClassDeclarationRangeHandler"/>
|
||||||
|
|
||||||
|
<declarationRangeHandler key="org.jetbrains.kotlin.psi.KtDeclarationWithBody"
|
||||||
|
implementationClass="org.jetbrains.kotlin.idea.codeInsight.KotlinFunDeclarationRangeHandler"/>
|
||||||
|
|
||||||
<intentionAction>
|
<intentionAction>
|
||||||
<className>org.jetbrains.kotlin.idea.intentions.FoldInitializerAndIfToElvisIntention</className>
|
<className>org.jetbrains.kotlin.idea.intentions.FoldInitializerAndIfToElvisIntention</className>
|
||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
|
|||||||
@@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea
|
package org.jetbrains.kotlin.idea
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.hint.DeclarationRangeUtil
|
||||||
import com.intellij.lang.BracePair
|
import com.intellij.lang.BracePair
|
||||||
import com.intellij.lang.PairedBraceMatcher
|
import com.intellij.lang.PairedBraceMatcher
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassBody
|
||||||
|
|
||||||
class KotlinPairMatcher : PairedBraceMatcher {
|
class KotlinPairMatcher : PairedBraceMatcher {
|
||||||
private val pairs = arrayOf(
|
private val pairs = arrayOf(
|
||||||
@@ -37,6 +40,12 @@ class KotlinPairMatcher : PairedBraceMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getCodeConstructStart(file: PsiFile, openingBraceOffset: Int): Int {
|
override fun getCodeConstructStart(file: PsiFile, openingBraceOffset: Int): Int {
|
||||||
return openingBraceOffset
|
val element = file.findElementAt(openingBraceOffset)
|
||||||
|
if (element == null || element is PsiFile) return openingBraceOffset
|
||||||
|
val parent = element.parent
|
||||||
|
return when (parent) {
|
||||||
|
is KtClassBody, is KtBlockExpression -> DeclarationRangeUtil.getDeclarationRange(parent.parent).startOffset
|
||||||
|
else -> openingBraceOffset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.hint.DeclarationRangeHandler
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiNameIdentifierOwner
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
|
||||||
|
class KotlinClassDeclarationRangeHandler : DeclarationRangeHandler<KtClassOrObject> {
|
||||||
|
override fun getDeclarationRange(container: KtClassOrObject): TextRange {
|
||||||
|
val body = container.getBody() ?: return container.textRange
|
||||||
|
val prevSibling = body.getPrevSiblingIgnoringWhitespaceAndComments()
|
||||||
|
return TextRange(
|
||||||
|
container.getDeclarationKeyword()?.startOffset ?: container.startOffset,
|
||||||
|
prevSibling?.endOffset ?: body.startOffset
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinFunDeclarationRangeHandler : DeclarationRangeHandler<KtDeclarationWithBody> {
|
||||||
|
override fun getDeclarationRange(container: KtDeclarationWithBody): TextRange {
|
||||||
|
val body = container.bodyExpression ?: return container.textRange
|
||||||
|
val prevSibling = body.getPrevSiblingIgnoringWhitespaceAndComments()
|
||||||
|
return TextRange(
|
||||||
|
(container as? KtNamedFunction)?.funKeyword?.startOffset
|
||||||
|
?: (container as? PsiNameIdentifierOwner)?.nameIdentifier?.startOffset
|
||||||
|
?: container.modifierList?.startOffset
|
||||||
|
?: container.startOffset,
|
||||||
|
prevSibling?.endOffset ?: body.startOffset
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinPairMatcher
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
|
class KotlinPairMatcherTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
override fun getProjectDescriptor(): KotlinLightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
|
private fun doTest(testData: String) {
|
||||||
|
var docText = testData
|
||||||
|
val startPos = docText.indexOf("<start>")
|
||||||
|
if (startPos == -1) {
|
||||||
|
throw IllegalArgumentException("<start> marker not found in testdata")
|
||||||
|
}
|
||||||
|
docText = docText.replace("<start>", "")
|
||||||
|
val bracePos = docText.indexOf("<brace>")
|
||||||
|
if (bracePos == -1) {
|
||||||
|
throw IllegalArgumentException("<brace> marker not found in testdata")
|
||||||
|
}
|
||||||
|
docText = docText.replace("<brace>", "")
|
||||||
|
myFixture.configureByText(KotlinFileType.INSTANCE, docText)
|
||||||
|
val pos = KotlinPairMatcher().getCodeConstructStart(myFixture.file, bracePos)
|
||||||
|
assertEquals(startPos, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testClass() {
|
||||||
|
doTest("/* Doc comment */ <start>class Foo : Bar, Baz <brace>{ fun xyzzy() { } }")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFun() {
|
||||||
|
doTest("/* Doc comment */ <start>fun xyzzy(x: Int, y: String): Any <brace>{ }")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user