Initial implementation of KT-5955 Completion for override methods
#KT-5955 Fixed
This commit is contained in:
@@ -17,16 +17,27 @@
|
|||||||
package org.jetbrains.kotlin.idea.quickfix
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
|
|
||||||
import org.jetbrains.kotlin.psi.JetBlockExpression
|
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
|
||||||
import com.intellij.openapi.editor.ScrollType
|
import com.intellij.openapi.editor.ScrollType
|
||||||
import org.jetbrains.kotlin.psi.JetWithExpressionInitializer
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
|
import com.intellij.psi.SmartPointerManager
|
||||||
|
import org.jetbrains.kotlin.psi.JetBlockExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
import org.jetbrains.kotlin.psi.JetWithExpressionInitializer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||||
|
|
||||||
public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement): Boolean {
|
public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
||||||
|
val project = element.project
|
||||||
|
val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(element)
|
||||||
|
|
||||||
|
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
|
||||||
|
|
||||||
|
pointer.element?.let { moveCaretIntoGeneratedElementDocumentUnblocked(editor, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun moveCaretIntoGeneratedElementDocumentUnblocked(editor: Editor, element: PsiElement): Boolean {
|
||||||
// Inspired by GenerateMembersUtils.positionCaret()
|
// Inspired by GenerateMembersUtils.positionCaret()
|
||||||
|
|
||||||
if (element is JetDeclarationWithBody && element.hasBody()) {
|
if (element is JetDeclarationWithBody && element.hasBody()) {
|
||||||
@@ -72,7 +83,7 @@ public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement): B
|
|||||||
|
|
||||||
if (element is JetProperty) {
|
if (element is JetProperty) {
|
||||||
for (accessor in element.getAccessors()) {
|
for (accessor in element.getAccessors()) {
|
||||||
if (moveCaretIntoGeneratedElement(editor, accessor)) {
|
if (moveCaretIntoGeneratedElementDocumentUnblocked(editor, accessor)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -257,6 +257,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"override" -> {
|
||||||
|
collector.addElement(lookupElement)
|
||||||
|
|
||||||
|
OverridesCompletion(collector, lookupElementFactory).complete(position)
|
||||||
|
}
|
||||||
|
|
||||||
else -> collector.addElement(lookupElement)
|
else -> collector.addElement(lookupElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -395,7 +395,7 @@ public class KotlinCompletionContributor : CompletionContributor() {
|
|||||||
if (parent is JetParameterList) {
|
if (parent is JetParameterList) {
|
||||||
val balance = countParenthesisBalance(tokenBefore, parent)
|
val balance = countParenthesisBalance(tokenBefore, parent)
|
||||||
val count = if (balance > 1) balance - 1 else 0
|
val count = if (balance > 1) balance - 1 else 0
|
||||||
return CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + ")".repeat(count) + " a: B$"
|
return CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + ")".repeat(count) + " a: B"
|
||||||
}
|
}
|
||||||
if (parent is JetTypeElement) return null
|
if (parent is JetTypeElement) return null
|
||||||
if (parent is JetAnnotationEntry) return null
|
if (parent is JetAnnotationEntry) return null
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.completion
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.InsertionContext
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||||
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.ui.RowIcon
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
|
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||||
|
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMembersHandler
|
||||||
|
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||||
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.moveCaret
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.moveCaretIntoGeneratedElement
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||||
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
|
||||||
|
class OverridesCompletion(
|
||||||
|
private val collector: LookupElementsCollector,
|
||||||
|
private val lookupElementFactory: LookupElementFactory
|
||||||
|
) {
|
||||||
|
private val PRESENTATION_RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.withOptions {
|
||||||
|
modifiers = emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun complete(position: PsiElement) {
|
||||||
|
val isConstructorParameter = position.getNonStrictParentOfType<JetPrimaryConstructor>() != null
|
||||||
|
|
||||||
|
val classOrObject = position.getNonStrictParentOfType<JetClassOrObject>() ?: return
|
||||||
|
|
||||||
|
val members = OverrideMembersHandler().collectMembersToGenerate(classOrObject)
|
||||||
|
|
||||||
|
for (memberObject in members) {
|
||||||
|
if (isConstructorParameter && memberObject.descriptor !is PropertyDescriptor) continue
|
||||||
|
|
||||||
|
val descriptor = memberObject.descriptor
|
||||||
|
var lookupElement = lookupElementFactory.createLookupElement(descriptor, useReceiverTypes = false)
|
||||||
|
|
||||||
|
var text = "override " + PRESENTATION_RENDERER.render(descriptor)
|
||||||
|
if (descriptor is FunctionDescriptor) {
|
||||||
|
text += " {...}"
|
||||||
|
}
|
||||||
|
|
||||||
|
val baseClass = descriptor.containingDeclaration as ClassDescriptor
|
||||||
|
val baseClassName = baseClass.name.asString()
|
||||||
|
|
||||||
|
val baseIcon = (lookupElement.`object` as DeclarationLookupObject).getIcon(0)
|
||||||
|
val additionalIcon = if (descriptor.modality == Modality.ABSTRACT)
|
||||||
|
AllIcons.Gutter.ImplementingMethod
|
||||||
|
else
|
||||||
|
AllIcons.Gutter.OverridingMethod
|
||||||
|
val icon = RowIcon(baseIcon, additionalIcon)
|
||||||
|
|
||||||
|
val baseClassDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(position.project, baseClass)
|
||||||
|
val baseClassIcon = JetDescriptorIconProvider.getIcon(baseClass, baseClassDeclaration, 0)
|
||||||
|
|
||||||
|
lookupElement = object : LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
|
override fun getLookupString() = "override"
|
||||||
|
override fun getAllLookupStrings() = setOf(lookupString)
|
||||||
|
|
||||||
|
override fun renderElement(presentation: LookupElementPresentation) {
|
||||||
|
super.renderElement(presentation)
|
||||||
|
|
||||||
|
presentation.itemText = text
|
||||||
|
presentation.icon = icon
|
||||||
|
presentation.clearTail()
|
||||||
|
presentation.setTypeText(baseClassName, baseClassIcon)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleInsert(context: InsertionContext) {
|
||||||
|
val dummyMemberText = if (isConstructorParameter) "override val dummy" else "override fun dummy() {}"
|
||||||
|
context.document.replaceString(context.startOffset, context.tailOffset, dummyMemberText)
|
||||||
|
|
||||||
|
PsiDocumentManager.getInstance(context.project).commitAllDocuments()
|
||||||
|
|
||||||
|
val dummyMember = context.file.findElementAt(context.startOffset)!!.getStrictParentOfType<JetNamedDeclaration>()!!
|
||||||
|
|
||||||
|
// keep original modifiers
|
||||||
|
val modifierList = JetPsiFactory(context.project).createModifierList(dummyMember.modifierList!!.text)
|
||||||
|
|
||||||
|
val prototype = memberObject.generateMember(context.project, isConstructorParameter)
|
||||||
|
prototype.modifierList!!.replace(modifierList)
|
||||||
|
val insertedMember = dummyMember.replaced(prototype)
|
||||||
|
|
||||||
|
ShortenReferences.DEFAULT.process(insertedMember)
|
||||||
|
|
||||||
|
if (isConstructorParameter) {
|
||||||
|
context.editor.moveCaret(insertedMember.endOffset)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
moveCaretIntoGeneratedElement(context.editor, insertedMember)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collector.addElement(lookupElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
interface I<T> {
|
||||||
|
fun foo(t: T): T
|
||||||
|
}
|
||||||
|
|
||||||
|
class A<T> : List<String>, I<T> {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "override", itemText: "override" }
|
||||||
|
// EXIST: { itemText: "override fun hashCode(): Int {...}", tailText: null, typeText: "Any" }
|
||||||
|
// EXIST: { itemText: "override fun foo(t: T): T {...}", tailText: null, typeText: "I" }
|
||||||
|
// EXIST: { itemText: "override fun get(index: Int): String {...}", tailText: null, typeText: "List" }
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo()
|
||||||
|
val someVal: Int
|
||||||
|
var someVar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Base1 {
|
||||||
|
protected open fun bar(){}
|
||||||
|
open val fromBase: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Base2 : Base1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(overr<caret>) : Base2(), I
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "override", itemText: "override" }
|
||||||
|
// EXIST: { itemText: "override val someVal: Int", tailText: null, typeText: "I" }
|
||||||
|
// EXIST: { itemText: "override var someVar: Int", tailText: null, typeText: "I" }
|
||||||
|
// EXIST: { itemText: "override val fromBase: String", tailText: null, typeText: "Base1" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString: "override", itemText: "override: Override" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo()
|
||||||
|
val someVal: Int
|
||||||
|
var someVar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Base1 {
|
||||||
|
protected open fun bar(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Base2 : Base1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : Base2(), I {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "override", itemText: "override" }
|
||||||
|
// EXIST: { itemText: "override fun bar() {...}", lookupString: "override", tailText: null, typeText: "Base1" }
|
||||||
|
// EXIST: { itemText: "override fun equals(other: Any?): Boolean {...}", lookupString: "override", tailText: null, typeText: "Any" }
|
||||||
|
// EXIST: { itemText: "override fun foo() {...}", lookupString: "override", tailText: null, typeText: "I" }
|
||||||
|
// EXIST: { itemText: "override fun hashCode(): Int {...}", lookupString: "override", tailText: null, typeText: "Any" }
|
||||||
|
// EXIST: { itemText: "override val someVal: Int", lookupString: "override", tailText: null, typeText: "I" }
|
||||||
|
// EXIST: { itemText: "override var someVar: Int", lookupString: "override", tailText: null, typeText: "I" }
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo(p: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun foo(p: Int) {...}"
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo(p: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
override fun foo(p: Int) {
|
||||||
|
<caret><selection>throw UnsupportedOperationException()</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun foo(p: Int) {...}"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
interface I {
|
||||||
|
val someVal: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: String?"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
interface I {
|
||||||
|
val someVal: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
override val someVal: String?
|
||||||
|
get() = <caret><selection>throw UnsupportedOperationException()</selection>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: String?"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
interface I {
|
||||||
|
var someVar: String
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override var someVar: String"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
interface I {
|
||||||
|
var someVar: String
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
override var someVar: String
|
||||||
|
get() = <caret><selection>throw UnsupportedOperationException()</selection>
|
||||||
|
set(value) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override var someVar: String"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
@Deprecated("")
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
class A {
|
||||||
|
@Deprecated("")
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
<caret><selection>return super.equals(other)</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
@Deprecated("") // it is deprecated
|
||||||
|
public o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
class A {
|
||||||
|
@Deprecated("") // it is deprecated
|
||||||
|
public override fun equals(other: Any?): Boolean {
|
||||||
|
<caret><selection>return super.equals(other)</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
class A {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
<caret><selection>return super.equals(other)</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override fun equals(other: Any?): Boolean {...}"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
open class B {
|
||||||
|
open var someVar: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : B {
|
||||||
|
o<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override var someVar: String"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
open class B {
|
||||||
|
open var someVar: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : B {
|
||||||
|
override var someVar: String
|
||||||
|
get() = <caret><selection>super.someVar</selection>
|
||||||
|
set(value) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override var someVar: String"
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
interface I {
|
||||||
|
val someVal: java.io.File?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(public ov<caret>) : I {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: File?"
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
val someVal: java.io.File?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(public override val someVal: File?<caret>) : I {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: File?"
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
interface I {
|
||||||
|
val someVal: java.io.File?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(ov<caret>) : I {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: File?"
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
val someVal: java.io.File?
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(override val someVal: File?<caret>) : I {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT_TEXT: "override val someVal: File?"
|
||||||
+27
@@ -1591,6 +1591,33 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/override")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Override extends AbstractJSBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInOverride() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/override"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Generics.kt")
|
||||||
|
public void testGenerics() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/Generics.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InConstructorParameters.kt")
|
||||||
|
public void testInConstructorParameters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/InConstructorParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/Simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType")
|
@TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+27
@@ -1591,6 +1591,33 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/override")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Override extends AbstractJvmBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInOverride() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/override"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Generics.kt")
|
||||||
|
public void testGenerics() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/Generics.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InConstructorParameters.kt")
|
||||||
|
public void testInConstructorParameters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/InConstructorParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/override/Simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType")
|
@TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+63
@@ -311,6 +311,69 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/handlers/basic/override")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Override extends AbstractBasicCompletionHandlerTest {
|
||||||
|
public void testAllFilesPresentInOverride() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/basic/override"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementFunction.kt")
|
||||||
|
public void testImplementFunction() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/ImplementFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementVal.kt")
|
||||||
|
public void testImplementVal() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/ImplementVal.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementVar.kt")
|
||||||
|
public void testImplementVar() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/ImplementVar.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KeepAnnotationBefore.kt")
|
||||||
|
public void testKeepAnnotationBefore() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/KeepAnnotationBefore.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KeepModifiersBefore.kt")
|
||||||
|
public void testKeepModifiersBefore() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/KeepModifiersBefore.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverrideFunction.kt")
|
||||||
|
public void testOverrideFunction() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/OverrideFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverrideVar.kt")
|
||||||
|
public void testOverrideVar() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/OverrideVar.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PublicValInConstructorParameter.kt")
|
||||||
|
public void testPublicValInConstructorParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/PublicValInConstructorParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ValInConstructorParameter.kt")
|
||||||
|
public void testValInConstructorParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/ValInConstructorParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType")
|
@TestMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+17
-105
@@ -23,18 +23,18 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.DialogWrapper
|
import com.intellij.openapi.ui.DialogWrapper
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.quickfix.moveCaretIntoGeneratedElement
|
import org.jetbrains.kotlin.idea.quickfix.moveCaretIntoGeneratedElement
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.renderer.*
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandler {
|
public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandler {
|
||||||
@@ -86,7 +86,7 @@ public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActio
|
|||||||
|
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
|
|
||||||
generateMethods(editor, classOrObject, selectedElements)
|
generateMembers(editor, classOrObject, selectedElements)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) = invoke(project, editor, file, false)
|
override fun invoke(project: Project, editor: Editor, file: PsiFile) = invoke(project, editor, file, false)
|
||||||
@@ -94,50 +94,33 @@ public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActio
|
|||||||
override fun startInWriteAction(): Boolean = false
|
override fun startInWriteAction(): Boolean = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
|
public fun generateMembers(editor: Editor, classOrObject: JetClassOrObject, selectedElements: Collection<OverrideMemberChooserObject>) {
|
||||||
renderDefaultValues = false
|
|
||||||
modifiers = setOf(DescriptorRendererModifier.OVERRIDE)
|
|
||||||
withDefinedIn = false
|
|
||||||
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
|
||||||
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
|
|
||||||
unitReturnType = false
|
|
||||||
typeNormalizer = IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun generateMethods(editor: Editor, classOrObject: JetClassOrObject, selectedElements: Collection<OverrideMemberChooserObject>) {
|
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
|
if (selectedElements.isEmpty()) return@runWriteAction
|
||||||
|
|
||||||
val body = classOrObject.getOrCreateBody()
|
val body = classOrObject.getOrCreateBody()
|
||||||
|
|
||||||
var afterAnchor = findInsertAfterAnchor(editor, body) ?: return@runWriteAction
|
var afterAnchor = findInsertAfterAnchor(editor, body) ?: return@runWriteAction
|
||||||
|
|
||||||
var firstGenerated: PsiElement? = null
|
var firstGenerated: PsiElement? = null
|
||||||
|
|
||||||
val elementsToCompact = ArrayList<JetElement>()
|
val project = classOrObject.project
|
||||||
for (element in generateOverridingMembers(selectedElements, classOrObject)) {
|
val insertedMembers = ArrayList<JetCallableDeclaration>()
|
||||||
val added = body.addAfter(element, afterAnchor)
|
for (memberObject in selectedElements) {
|
||||||
|
val member = memberObject.generateMember(project)
|
||||||
|
val added = body.addAfter(member, afterAnchor) as JetCallableDeclaration
|
||||||
|
|
||||||
if (firstGenerated == null) {
|
if (firstGenerated == null) {
|
||||||
firstGenerated = added
|
firstGenerated = added
|
||||||
}
|
}
|
||||||
|
|
||||||
afterAnchor = added
|
afterAnchor = added
|
||||||
elementsToCompact.add(added as JetElement)
|
insertedMembers.add(added)
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortenReferences.Companion.DEFAULT.process(elementsToCompact)
|
ShortenReferences.DEFAULT.process(insertedMembers)
|
||||||
|
|
||||||
if (firstGenerated == null) return@runWriteAction
|
|
||||||
|
|
||||||
val project = classOrObject.project
|
|
||||||
val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(firstGenerated)
|
|
||||||
|
|
||||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
|
|
||||||
|
|
||||||
val element = pointer.element
|
|
||||||
if (element != null) {
|
|
||||||
moveCaretIntoGeneratedElement(editor, element)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
moveCaretIntoGeneratedElement(editor, firstGenerated!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,76 +165,5 @@ public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActio
|
|||||||
|
|
||||||
return whiteSpace
|
return whiteSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateOverridingMembers(selectedElements: Collection<OverrideMemberChooserObject>,
|
|
||||||
classOrObject: JetClassOrObject): List<JetElement> {
|
|
||||||
val overridingMembers = ArrayList<JetElement>()
|
|
||||||
for (selectedElement in selectedElements) {
|
|
||||||
val descriptor = selectedElement.immediateSuper
|
|
||||||
when (descriptor) {
|
|
||||||
is SimpleFunctionDescriptor -> overridingMembers.add(overrideFunction(classOrObject, descriptor, selectedElement.bodyType))
|
|
||||||
is PropertyDescriptor -> overridingMembers.add(overrideProperty(classOrObject, descriptor, selectedElement.bodyType))
|
|
||||||
else -> error("Unknown member to override: $descriptor")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return overridingMembers
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun overrideProperty(classOrObject: JetClassOrObject, descriptor: PropertyDescriptor, bodyType: OverrideMemberChooserObject.BodyType): JetElement {
|
|
||||||
val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
|
|
||||||
descriptor.kind, /* copyOverrides = */ true) as PropertyDescriptor
|
|
||||||
newDescriptor.addOverriddenDescriptor(descriptor)
|
|
||||||
|
|
||||||
val body = StringBuilder {
|
|
||||||
append("\nget()")
|
|
||||||
append(" = ")
|
|
||||||
append(generateUnsupportedOrSuperCall(descriptor, bodyType))
|
|
||||||
if (descriptor.isVar) {
|
|
||||||
append("\nset(value) {}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JetPsiFactory(classOrObject.project).createProperty(OVERRIDE_RENDERER.render(newDescriptor) + body)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun overrideFunction(classOrObject: JetClassOrObject, descriptor: FunctionDescriptor, bodyType: OverrideMemberChooserObject.BodyType): JetNamedFunction {
|
|
||||||
val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
|
|
||||||
descriptor.kind, /* copyOverrides = */ true)
|
|
||||||
newDescriptor.addOverriddenDescriptor(descriptor)
|
|
||||||
|
|
||||||
val returnType = descriptor.returnType
|
|
||||||
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
|
||||||
|
|
||||||
val delegation = generateUnsupportedOrSuperCall(descriptor, bodyType)
|
|
||||||
|
|
||||||
val body = "{" + (if (returnsNotUnit && bodyType != OverrideMemberChooserObject.BodyType.EMPTY) "return " else "") + delegation + "}"
|
|
||||||
|
|
||||||
return JetPsiFactory(classOrObject.project).createFunction(OVERRIDE_RENDERER.render(newDescriptor) + body)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateUnsupportedOrSuperCall(descriptor: CallableMemberDescriptor, bodyType: OverrideMemberChooserObject.BodyType): String {
|
|
||||||
if (bodyType == OverrideMemberChooserObject.BodyType.EMPTY) {
|
|
||||||
return "throw UnsupportedOperationException()"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return StringBuilder {
|
|
||||||
append("super")
|
|
||||||
if (bodyType == OverrideMemberChooserObject.BodyType.QUALIFIED_SUPER) {
|
|
||||||
val superClassFqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(descriptor.containingDeclaration as ClassifierDescriptor)
|
|
||||||
append("<").append(superClassFqName).append(">")
|
|
||||||
}
|
|
||||||
append(".").append(descriptor.escapedName())
|
|
||||||
|
|
||||||
if (descriptor is FunctionDescriptor) {
|
|
||||||
val paramTexts = descriptor.valueParameters.map {
|
|
||||||
val renderedName = it.escapedName()
|
|
||||||
if (it.varargElementType != null) "*$renderedName" else renderedName
|
|
||||||
}
|
|
||||||
paramTexts.joinTo(this, prefix="(", postfix=")")
|
|
||||||
}
|
|
||||||
}.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DeclarationDescriptor.escapedName() = name.render()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+94
-3
@@ -21,10 +21,13 @@ import com.intellij.codeInsight.generation.MemberChooserObject
|
|||||||
import com.intellij.codeInsight.generation.MemberChooserObjectBase
|
import com.intellij.codeInsight.generation.MemberChooserObjectBase
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.renderer.*
|
||||||
|
|
||||||
interface OverrideMemberChooserObject : ClassMember {
|
interface OverrideMemberChooserObject : ClassMember {
|
||||||
enum class BodyType {
|
enum class BodyType {
|
||||||
@@ -56,7 +59,7 @@ interface OverrideMemberChooserObject : ClassMember {
|
|||||||
) : DescriptorMemberChooserObject(declaration, descriptor), OverrideMemberChooserObject {
|
) : DescriptorMemberChooserObject(declaration, descriptor), OverrideMemberChooserObject {
|
||||||
|
|
||||||
override val descriptor: CallableMemberDescriptor
|
override val descriptor: CallableMemberDescriptor
|
||||||
get() = super<DescriptorMemberChooserObject>.descriptor as CallableMemberDescriptor
|
get() = super.descriptor as CallableMemberDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
private class WithoutDeclaration(
|
private class WithoutDeclaration(
|
||||||
@@ -72,3 +75,91 @@ interface OverrideMemberChooserObject : ClassMember {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun OverrideMemberChooserObject.generateMember(project: Project, asConstructorParameter: Boolean = false): JetCallableDeclaration {
|
||||||
|
val descriptor = immediateSuper
|
||||||
|
if (asConstructorParameter) {
|
||||||
|
assert(descriptor is PropertyDescriptor) { "asConstructorParameter is valid only for PropertyDescriptor" }
|
||||||
|
return generateConstructorParameter(project, descriptor as PropertyDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (descriptor) {
|
||||||
|
is SimpleFunctionDescriptor -> generateFunction(project, descriptor, bodyType)
|
||||||
|
is PropertyDescriptor -> generateProperty(project, descriptor, bodyType)
|
||||||
|
else -> error("Unknown member to override: $descriptor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
|
||||||
|
renderDefaultValues = false
|
||||||
|
modifiers = setOf(DescriptorRendererModifier.OVERRIDE)
|
||||||
|
withDefinedIn = false
|
||||||
|
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
||||||
|
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
|
||||||
|
unitReturnType = false
|
||||||
|
typeNormalizer = IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateProperty(project: Project, descriptor: PropertyDescriptor, bodyType: OverrideMemberChooserObject.BodyType): JetProperty {
|
||||||
|
val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
|
||||||
|
descriptor.kind, /* copyOverrides = */ true) as PropertyDescriptor
|
||||||
|
newDescriptor.addOverriddenDescriptor(descriptor)
|
||||||
|
|
||||||
|
val body = StringBuilder {
|
||||||
|
append("\nget()")
|
||||||
|
append(" = ")
|
||||||
|
append(generateUnsupportedOrSuperCall(descriptor, bodyType))
|
||||||
|
if (descriptor.isVar) {
|
||||||
|
append("\nset(value) {}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JetPsiFactory(project).createProperty(OVERRIDE_RENDERER.render(newDescriptor) + body)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor): JetParameter {
|
||||||
|
val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
|
||||||
|
descriptor.kind, /* copyOverrides = */ true) as PropertyDescriptor
|
||||||
|
newDescriptor.addOverriddenDescriptor(descriptor)
|
||||||
|
return JetPsiFactory(project).createParameter(OVERRIDE_RENDERER.render(newDescriptor))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateFunction(project: Project, descriptor: FunctionDescriptor, bodyType: OverrideMemberChooserObject.BodyType): JetNamedFunction {
|
||||||
|
val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
|
||||||
|
descriptor.kind, /* copyOverrides = */ true)
|
||||||
|
newDescriptor.addOverriddenDescriptor(descriptor)
|
||||||
|
|
||||||
|
val returnType = descriptor.returnType
|
||||||
|
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
||||||
|
|
||||||
|
val delegation = generateUnsupportedOrSuperCall(descriptor, bodyType)
|
||||||
|
|
||||||
|
val body = "{" + (if (returnsNotUnit && bodyType != OverrideMemberChooserObject.BodyType.EMPTY) "return " else "") + delegation + "}"
|
||||||
|
|
||||||
|
return JetPsiFactory(project).createFunction(OVERRIDE_RENDERER.render(newDescriptor) + body)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateUnsupportedOrSuperCall(descriptor: CallableMemberDescriptor, bodyType: OverrideMemberChooserObject.BodyType): String {
|
||||||
|
if (bodyType == OverrideMemberChooserObject.BodyType.EMPTY) {
|
||||||
|
return "throw UnsupportedOperationException()"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return StringBuilder {
|
||||||
|
append("super")
|
||||||
|
if (bodyType == OverrideMemberChooserObject.BodyType.QUALIFIED_SUPER) {
|
||||||
|
val superClassFqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(descriptor.containingDeclaration as ClassifierDescriptor)
|
||||||
|
append("<").append(superClassFqName).append(">")
|
||||||
|
}
|
||||||
|
append(".").append(descriptor.name.render())
|
||||||
|
|
||||||
|
if (descriptor is FunctionDescriptor) {
|
||||||
|
val paramTexts = descriptor.valueParameters.map {
|
||||||
|
val renderedName = it.name.render()
|
||||||
|
if (it.varargElementType != null) "*$renderedName" else renderedName
|
||||||
|
}
|
||||||
|
paramTexts.joinTo(this, prefix="(", postfix=")")
|
||||||
|
}
|
||||||
|
}.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public abstract class AbstractOverrideImplementTest : JetLightCodeInsightFixture
|
|||||||
selectedElements: List<OverrideMemberChooserObject>) {
|
selectedElements: List<OverrideMemberChooserObject>) {
|
||||||
try {
|
try {
|
||||||
myFixture.project.executeWriteCommand("") {
|
myFixture.project.executeWriteCommand("") {
|
||||||
OverrideImplementMembersHandler.generateMethods(myFixture.editor, classOrObject, selectedElements)
|
OverrideImplementMembersHandler.generateMembers(myFixture.editor, classOrObject, selectedElements)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (throwable: Throwable) {
|
catch (throwable: Throwable) {
|
||||||
|
|||||||
Reference in New Issue
Block a user