KT-9661 Code completion of "get" and "set" in property accessors
#KT-9661 Fixed
This commit is contained in:
+28
-4
@@ -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.SmartCompletion
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
|
||||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
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.stubindex.PackageIndexUtil
|
||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
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.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||||
@@ -266,6 +265,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
KeywordValues.process(keywordValueConsumer, callTypeAndReceiver, bindingContext, resolutionFacade, moduleDescriptor, isJvmModule)
|
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 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 ->
|
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix, isJvmModule) { lookupElement ->
|
||||||
val keyword = lookupElement.lookupString
|
val keyword = lookupElement.lookupString
|
||||||
if (keyword in keywordsToSkip) return@complete
|
if (keyword in keywordsToSkip) return@complete
|
||||||
@@ -309,6 +309,20 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
|
|
||||||
"get" -> {
|
"get" -> {
|
||||||
collector.addElement(lookupElement)
|
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)
|
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() {
|
private fun completeNonImported() {
|
||||||
if (completionKind == CompletionKind.ALL) {
|
if (completionKind == CompletionKind.ALL) {
|
||||||
collector.addDescriptorElements(getTopLevelExtensions(), notImported = true)
|
collector.addDescriptorElements(getTopLevelExtensions(), notImported = true)
|
||||||
|
|||||||
+3
-1
@@ -39,7 +39,9 @@ object KotlinKeywordInsertHandler : InsertHandler<LookupElement> {
|
|||||||
FILE_KEYWORD,
|
FILE_KEYWORD,
|
||||||
CATCH_KEYWORD,
|
CATCH_KEYWORD,
|
||||||
FINALLY_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) {
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
val keyword = item.lookupString
|
val keyword = item.lookupString
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package propertiesSetter
|
package propertiesGetter
|
||||||
|
|
||||||
class TestClass {
|
class TestClass {
|
||||||
val a : Int
|
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: final
|
||||||
// EXIST: fun
|
// EXIST: fun
|
||||||
// EXIST: get
|
// EXIST: get
|
||||||
|
// EXIST: "get() = "
|
||||||
|
// EXIST: "get() {}"
|
||||||
// EXIST: inner
|
// EXIST: inner
|
||||||
// EXIST: internal
|
// EXIST: internal
|
||||||
// EXIST: object
|
// EXIST: object
|
||||||
@@ -20,6 +22,8 @@ class MouseMovedEventArgs
|
|||||||
// EXIST: protected
|
// EXIST: protected
|
||||||
// EXIST: public
|
// EXIST: public
|
||||||
// EXIST: set
|
// EXIST: set
|
||||||
|
// EXIST: "set(value) = "
|
||||||
|
// EXIST: "set(value) {}"
|
||||||
// EXIST: interface
|
// EXIST: interface
|
||||||
// EXIST: val
|
// EXIST: val
|
||||||
// EXIST: var
|
// EXIST: var
|
||||||
|
|||||||
@@ -16,12 +16,16 @@ var a : Int
|
|||||||
// EXIST: final
|
// EXIST: final
|
||||||
// EXIST: fun
|
// EXIST: fun
|
||||||
// EXIST: get
|
// EXIST: get
|
||||||
|
// EXIST: "get() = "
|
||||||
|
// EXIST: "get() {}"
|
||||||
// EXIST: internal
|
// EXIST: internal
|
||||||
// EXIST: object
|
// EXIST: object
|
||||||
// EXIST: open
|
// EXIST: open
|
||||||
// EXIST: private
|
// EXIST: private
|
||||||
// EXIST: public
|
// EXIST: public
|
||||||
// EXIST: set
|
// EXIST: set
|
||||||
|
// EXIST: "set(value) = "
|
||||||
|
// EXIST: "set(value) {}"
|
||||||
// EXIST: interface
|
// EXIST: interface
|
||||||
// EXIST: val
|
// EXIST: val
|
||||||
// EXIST: var
|
// EXIST: var
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class Some {
|
|||||||
// EXIST: final
|
// EXIST: final
|
||||||
// EXIST: fun
|
// EXIST: fun
|
||||||
// EXIST: get
|
// EXIST: get
|
||||||
|
// EXIST: "get() = "
|
||||||
|
// EXIST: "get() {}"
|
||||||
// EXIST: inner
|
// EXIST: inner
|
||||||
// EXIST: internal
|
// EXIST: internal
|
||||||
// EXIST: object
|
// EXIST: object
|
||||||
@@ -19,6 +21,8 @@ class Some {
|
|||||||
// EXIST: protected
|
// EXIST: protected
|
||||||
// EXIST: public
|
// EXIST: public
|
||||||
// EXIST: set
|
// EXIST: set
|
||||||
|
// EXIST: "set(value) = "
|
||||||
|
// EXIST: "set(value) {}"
|
||||||
// EXIST: interface
|
// EXIST: interface
|
||||||
// EXIST: val
|
// EXIST: val
|
||||||
// EXIST: var
|
// EXIST: var
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class Some {
|
|||||||
// EXIST: final
|
// EXIST: final
|
||||||
// EXIST: fun
|
// EXIST: fun
|
||||||
// EXIST: get
|
// EXIST: get
|
||||||
|
// EXIST: "get() = "
|
||||||
|
// EXIST: "get() {}"
|
||||||
// EXIST: inner
|
// EXIST: inner
|
||||||
// EXIST: internal
|
// EXIST: internal
|
||||||
// EXIST: object
|
// EXIST: object
|
||||||
@@ -19,6 +21,8 @@ class Some {
|
|||||||
// EXIST: protected
|
// EXIST: protected
|
||||||
// EXIST: public
|
// EXIST: public
|
||||||
// EXIST: set
|
// EXIST: set
|
||||||
|
// EXIST: "set(value) = "
|
||||||
|
// EXIST: "set(value) {}"
|
||||||
// EXIST: interface
|
// EXIST: interface
|
||||||
// EXIST: val
|
// EXIST: val
|
||||||
// EXIST: var
|
// EXIST: var
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ class Some {
|
|||||||
// EXIST: enum class
|
// EXIST: enum class
|
||||||
// EXIST: final
|
// EXIST: final
|
||||||
// EXIST: fun
|
// EXIST: fun
|
||||||
// EXIST: get
|
|
||||||
/*TODO*/
|
/*TODO*/
|
||||||
|
// EXIST: get
|
||||||
|
// EXIST: "get() = "
|
||||||
|
// EXIST: "get() {}"
|
||||||
|
|
||||||
// EXIST: inner
|
// EXIST: inner
|
||||||
// EXIST: internal
|
// EXIST: internal
|
||||||
// EXIST: object
|
// EXIST: object
|
||||||
@@ -21,6 +25,8 @@ class Some {
|
|||||||
// EXIST: protected
|
// EXIST: protected
|
||||||
// EXIST: public
|
// EXIST: public
|
||||||
// EXIST: set
|
// EXIST: set
|
||||||
|
// EXIST: "set(value) = "
|
||||||
|
// EXIST: "set(value) {}"
|
||||||
// EXIST: interface
|
// EXIST: interface
|
||||||
// EXIST: val
|
// EXIST: val
|
||||||
// EXIST: var
|
// EXIST: var
|
||||||
|
|||||||
+1
-4
@@ -17,11 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.completion.handlers
|
package org.jetbrains.kotlin.completion.handlers
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionType
|
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.COMPLETION_TEST_DATA_BASE_PATH
|
||||||
import org.jetbrains.kotlin.idea.completion.test.handlers.CompletionHandlerTestBase
|
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
|
import java.io.File
|
||||||
|
|
||||||
@Deprecated("All tests from here to be moved to the generated test")
|
@Deprecated("All tests from here to be moved to the generated test")
|
||||||
@@ -77,7 +74,7 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
|||||||
|
|
||||||
fun testInsertVoidJavaMethod() = doTest()
|
fun testInsertVoidJavaMethod() = doTest()
|
||||||
|
|
||||||
fun testPropertiesSetter() = doTest()
|
fun testPropertiesGetter() = doTest()
|
||||||
|
|
||||||
fun testExistingSingleBrackets() = doTest()
|
fun testExistingSingleBrackets() = doTest()
|
||||||
|
|
||||||
|
|||||||
+24
@@ -59,6 +59,18 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("NoSpaceAfterNull.kt")
|
||||||
public void testNoSpaceAfterNull() throws Exception {
|
public void testNoSpaceAfterNull() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/NoSpaceAfterNull.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/NoSpaceAfterNull.kt");
|
||||||
@@ -119,6 +131,18 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("SpaceAfterImport.kt")
|
||||||
public void testSpaceAfterImport() throws Exception {
|
public void testSpaceAfterImport() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/SpaceAfterImport.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/SpaceAfterImport.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user