KT-9661 Code completion of "get" and "set" in property accessors

#KT-9661 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-10-21 19:15:28 +03:00
parent 798223b0e4
commit 6eba45febd
20 changed files with 122 additions and 17 deletions
@@ -35,15 +35,14 @@ import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.quickfix.moveCaret
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
@@ -266,6 +265,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
KeywordValues.process(keywordValueConsumer, callTypeAndReceiver, bindingContext, resolutionFacade, moduleDescriptor, isJvmModule)
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
val isUseSiteAnnotationTarget = position.prevLeaf()?.node?.elementType == KtTokens.AT
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix, isJvmModule) { lookupElement ->
val keyword = lookupElement.lookupString
if (keyword in keywordsToSkip) return@complete
@@ -309,6 +309,20 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
"get" -> {
collector.addElement(lookupElement)
if (!isUseSiteAnnotationTarget) { //TODO: use code style settings
collector.addElement(createKeywordWithSuffixLookupElement(keyword, "() = ", ""))
collector.addElement(createKeywordWithSuffixLookupElement(keyword, "() {", "}"))
}
}
"set" -> {
collector.addElement(lookupElement)
if (!isUseSiteAnnotationTarget) { //TODO: use code style settings
collector.addElement(createKeywordWithSuffixLookupElement(keyword, "(value) {", "}"))
collector.addElement(createKeywordWithSuffixLookupElement(keyword, "(value) = ", ""))
}
}
else -> collector.addElement(lookupElement)
@@ -316,6 +330,16 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
}
}
private fun createKeywordWithSuffixLookupElement(keyword: String, textBeforeCaret: String, textAfterCaret: String): LookupElementBuilder {
return LookupElementBuilder.create(KeywordLookupObject(), keyword + textBeforeCaret + textAfterCaret)
.withPresentableText(keyword)
.bold()
.withTailText(textBeforeCaret + textAfterCaret)
.withInsertHandler { insertionContext, lookupElement ->
insertionContext.editor.moveCaret(insertionContext.editor.caretModel.offset - textAfterCaret.length)
}
}
private fun completeNonImported() {
if (completionKind == CompletionKind.ALL) {
collector.addDescriptorElements(getTopLevelExtensions(), notImported = true)
@@ -39,7 +39,9 @@ object KotlinKeywordInsertHandler : InsertHandler<LookupElement> {
FILE_KEYWORD,
CATCH_KEYWORD,
FINALLY_KEYWORD,
DYNAMIC_KEYWORD).map { it.getValue() } + "companion object"
DYNAMIC_KEYWORD,
GET_KEYWORD,
SET_KEYWORD).map { it.value } + "companion object"
override fun handleInsert(context: InsertionContext, item: LookupElement) {
val keyword = item.lookupString
@@ -1,4 +1,4 @@
package propertiesSetter
package propertiesGetter
class TestClass {
val a : Int
@@ -0,0 +1,6 @@
package propertiesGetter
class TestClass {
val a : Int
get<caret>
}
@@ -1,6 +0,0 @@
package propertiesSetter
class TestClass {
val a : Int
get()<caret>
}
@@ -0,0 +1,4 @@
val v: Int
g<caret>
// ELEMENT: "get() = "
@@ -0,0 +1,4 @@
val v: Int
get() = <caret>
// ELEMENT: "get() = "
@@ -0,0 +1,4 @@
val v: Int
g<caret>
// ELEMENT: "get() {}"
@@ -0,0 +1,4 @@
val v: Int
get() {<caret>}
// ELEMENT: "get() {}"
@@ -0,0 +1,5 @@
var v: Int
get() = 0
s<caret>
// ELEMENT: "set(value) = "
@@ -0,0 +1,5 @@
var v: Int
get() = 0
set(value) = <caret>
// ELEMENT: "set(value) = "
@@ -0,0 +1,5 @@
var v: Int
get() = 0
s<caret>
// ELEMENT: "set(value) {}"
@@ -0,0 +1,5 @@
var v: Int
get() = 0
set(value) {<caret>}
// ELEMENT: "set(value) {}"
@@ -11,6 +11,8 @@ class MouseMovedEventArgs
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner
// EXIST: internal
// EXIST: object
@@ -20,6 +22,8 @@ class MouseMovedEventArgs
// EXIST: protected
// EXIST: public
// EXIST: set
// EXIST: "set(value) = "
// EXIST: "set(value) {}"
// EXIST: interface
// EXIST: val
// EXIST: var
@@ -16,12 +16,16 @@ var a : Int
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: private
// EXIST: public
// EXIST: set
// EXIST: "set(value) = "
// EXIST: "set(value) {}"
// EXIST: interface
// EXIST: val
// EXIST: var
@@ -10,6 +10,8 @@ class Some {
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner
// EXIST: internal
// EXIST: object
@@ -19,6 +21,8 @@ class Some {
// EXIST: protected
// EXIST: public
// EXIST: set
// EXIST: "set(value) = "
// EXIST: "set(value) {}"
// EXIST: interface
// EXIST: val
// EXIST: var
@@ -10,6 +10,8 @@ class Some {
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner
// EXIST: internal
// EXIST: object
@@ -19,6 +21,8 @@ class Some {
// EXIST: protected
// EXIST: public
// EXIST: set
// EXIST: "set(value) = "
// EXIST: "set(value) {}"
// EXIST: interface
// EXIST: val
// EXIST: var
+7 -1
View File
@@ -10,8 +10,12 @@ class Some {
// EXIST: enum class
// EXIST: final
// EXIST: fun
// EXIST: get
/*TODO*/
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner
// EXIST: internal
// EXIST: object
@@ -21,6 +25,8 @@ class Some {
// EXIST: protected
// EXIST: public
// EXIST: set
// EXIST: "set(value) = "
// EXIST: "set(value) {}"
// EXIST: interface
// EXIST: val
// EXIST: var
@@ -17,11 +17,8 @@
package org.jetbrains.kotlin.completion.handlers
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.kotlin.idea.completion.test.COMPLETION_TEST_DATA_BASE_PATH
import org.jetbrains.kotlin.idea.completion.test.handlers.CompletionHandlerTestBase
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import java.io.File
@Deprecated("All tests from here to be moved to the generated test")
@@ -77,7 +74,7 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
fun testInsertVoidJavaMethod() = doTest()
fun testPropertiesSetter() = doTest()
fun testPropertiesGetter() = doTest()
fun testExistingSingleBrackets() = doTest()
@@ -59,6 +59,18 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
doTest(fileName);
}
@TestMetadata("Getter1.kt")
public void testGetter1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Getter1.kt");
doTest(fileName);
}
@TestMetadata("Getter2.kt")
public void testGetter2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Getter2.kt");
doTest(fileName);
}
@TestMetadata("NoSpaceAfterNull.kt")
public void testNoSpaceAfterNull() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/NoSpaceAfterNull.kt");
@@ -119,6 +131,18 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
doTest(fileName);
}
@TestMetadata("Setter1.kt")
public void testSetter1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Setter1.kt");
doTest(fileName);
}
@TestMetadata("Setter2.kt")
public void testSetter2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Setter2.kt");
doTest(fileName);
}
@TestMetadata("SpaceAfterImport.kt")
public void testSpaceAfterImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/SpaceAfterImport.kt");