diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index 7691836e447..64cdbede1ba 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -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) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinKeywordInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinKeywordInsertHandler.kt index 4166099623f..eb66859ea0b 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinKeywordInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinKeywordInsertHandler.kt @@ -39,7 +39,9 @@ object KotlinKeywordInsertHandler : InsertHandler { 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 diff --git a/idea/idea-completion/testData/handlers/PropertiesSetter.kt b/idea/idea-completion/testData/handlers/PropertiesGetter.kt similarity index 68% rename from idea/idea-completion/testData/handlers/PropertiesSetter.kt rename to idea/idea-completion/testData/handlers/PropertiesGetter.kt index a6e2193410e..6369a9926b4 100644 --- a/idea/idea-completion/testData/handlers/PropertiesSetter.kt +++ b/idea/idea-completion/testData/handlers/PropertiesGetter.kt @@ -1,4 +1,4 @@ -package propertiesSetter +package propertiesGetter class TestClass { val a : Int diff --git a/idea/idea-completion/testData/handlers/PropertiesGetter.kt.after b/idea/idea-completion/testData/handlers/PropertiesGetter.kt.after new file mode 100644 index 00000000000..13cef211fb7 --- /dev/null +++ b/idea/idea-completion/testData/handlers/PropertiesGetter.kt.after @@ -0,0 +1,6 @@ +package propertiesGetter + +class TestClass { + val a : Int + get +} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/PropertiesSetter.kt.after b/idea/idea-completion/testData/handlers/PropertiesSetter.kt.after deleted file mode 100644 index 9fa5eb2f4a0..00000000000 --- a/idea/idea-completion/testData/handlers/PropertiesSetter.kt.after +++ /dev/null @@ -1,6 +0,0 @@ -package propertiesSetter - -class TestClass { - val a : Int - get() -} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Getter1.kt b/idea/idea-completion/testData/handlers/keywords/Getter1.kt new file mode 100644 index 00000000000..d70e04b475c --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Getter1.kt @@ -0,0 +1,4 @@ +val v: Int + g + +// ELEMENT: "get() = " \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Getter1.kt.after b/idea/idea-completion/testData/handlers/keywords/Getter1.kt.after new file mode 100644 index 00000000000..527cab5d1e2 --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Getter1.kt.after @@ -0,0 +1,4 @@ +val v: Int + get() = + +// ELEMENT: "get() = " \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Getter2.kt b/idea/idea-completion/testData/handlers/keywords/Getter2.kt new file mode 100644 index 00000000000..487bdbebe0c --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Getter2.kt @@ -0,0 +1,4 @@ +val v: Int + g + +// ELEMENT: "get() {}" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Getter2.kt.after b/idea/idea-completion/testData/handlers/keywords/Getter2.kt.after new file mode 100644 index 00000000000..bcd208c5b57 --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Getter2.kt.after @@ -0,0 +1,4 @@ +val v: Int + get() {} + +// ELEMENT: "get() {}" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Setter1.kt b/idea/idea-completion/testData/handlers/keywords/Setter1.kt new file mode 100644 index 00000000000..0e06288b218 --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Setter1.kt @@ -0,0 +1,5 @@ +var v: Int + get() = 0 + s + +// ELEMENT: "set(value) = " \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Setter1.kt.after b/idea/idea-completion/testData/handlers/keywords/Setter1.kt.after new file mode 100644 index 00000000000..e297fe18295 --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Setter1.kt.after @@ -0,0 +1,5 @@ +var v: Int + get() = 0 + set(value) = + +// ELEMENT: "set(value) = " \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Setter2.kt b/idea/idea-completion/testData/handlers/keywords/Setter2.kt new file mode 100644 index 00000000000..357285edbda --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Setter2.kt @@ -0,0 +1,5 @@ +var v: Int + get() = 0 + s + +// ELEMENT: "set(value) {}" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/keywords/Setter2.kt.after b/idea/idea-completion/testData/handlers/keywords/Setter2.kt.after new file mode 100644 index 00000000000..464c2e29eea --- /dev/null +++ b/idea/idea-completion/testData/handlers/keywords/Setter2.kt.after @@ -0,0 +1,5 @@ +var v: Int + get() = 0 + set(value) {} + +// ELEMENT: "set(value) {}" \ No newline at end of file diff --git a/idea/idea-completion/testData/keywords/AfterClassProperty.kt b/idea/idea-completion/testData/keywords/AfterClassProperty.kt index f8382ae5df9..3440f963fcb 100644 --- a/idea/idea-completion/testData/keywords/AfterClassProperty.kt +++ b/idea/idea-completion/testData/keywords/AfterClassProperty.kt @@ -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 diff --git a/idea/idea-completion/testData/keywords/GlobalPropertyAccessors.kt b/idea/idea-completion/testData/keywords/GlobalPropertyAccessors.kt index de82f7a849f..be2534f2035 100644 --- a/idea/idea-completion/testData/keywords/GlobalPropertyAccessors.kt +++ b/idea/idea-completion/testData/keywords/GlobalPropertyAccessors.kt @@ -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 diff --git a/idea/idea-completion/testData/keywords/PropertyAccessors.kt b/idea/idea-completion/testData/keywords/PropertyAccessors.kt index 7b652e36f67..d53e083eb44 100644 --- a/idea/idea-completion/testData/keywords/PropertyAccessors.kt +++ b/idea/idea-completion/testData/keywords/PropertyAccessors.kt @@ -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 diff --git a/idea/idea-completion/testData/keywords/PropertyAccessors2.kt b/idea/idea-completion/testData/keywords/PropertyAccessors2.kt index 97e524af8f1..b828edb7dd9 100644 --- a/idea/idea-completion/testData/keywords/PropertyAccessors2.kt +++ b/idea/idea-completion/testData/keywords/PropertyAccessors2.kt @@ -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 diff --git a/idea/idea-completion/testData/keywords/PropertySetter.kt b/idea/idea-completion/testData/keywords/PropertySetter.kt index a7263c028a4..5a6da8bf797 100644 --- a/idea/idea-completion/testData/keywords/PropertySetter.kt +++ b/idea/idea-completion/testData/keywords/PropertySetter.kt @@ -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 diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTest.kt index 3ecf0d53fed..184b3c62a00 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTest.kt @@ -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() diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java index 381b4abc040..53e6a232aa2 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java @@ -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");