Implement Abstract Member Intention: Support primary constructor parameters
#KT-8427 Fixed
This commit is contained in:
@@ -88,3 +88,19 @@ public open class KtClass : KtClassOrObject {
|
||||
|
||||
public fun getClassOrInterfaceKeyword(): PsiElement? = findChildByType(TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD))
|
||||
}
|
||||
|
||||
public fun KtClass.createPrimaryConstructorIfAbsent(): KtPrimaryConstructor {
|
||||
val constructor = getPrimaryConstructor()
|
||||
if (constructor != null) return constructor
|
||||
var anchor: PsiElement? = typeParameterList
|
||||
if (anchor == null) anchor = nameIdentifier
|
||||
if (anchor == null) anchor = lastChild
|
||||
return addAfter(KtPsiFactory(project).createPrimaryConstructor(), anchor) as KtPrimaryConstructor
|
||||
}
|
||||
|
||||
public fun KtClass.createPrimaryConstructorParameterListIfAbsent(): KtParameterList {
|
||||
val constructor = createPrimaryConstructorIfAbsent()
|
||||
val parameterList = constructor.valueParameterList
|
||||
if (parameterList != null) return parameterList
|
||||
return constructor.add(KtPsiFactory(project).createParameterList("()")) as KtParameterList
|
||||
}
|
||||
@@ -153,29 +153,42 @@ public fun <T : KtDeclaration> insertMembersAfter(
|
||||
): List<T> {
|
||||
members.ifEmpty { return emptyList() }
|
||||
|
||||
return runWriteAction<List<T>> {
|
||||
val body = classOrObject.getOrCreateBody()
|
||||
return runWriteAction {
|
||||
val insertedMembers = SmartList<T>()
|
||||
|
||||
var afterAnchor = anchor ?: findInsertAfterAnchor(editor, body) ?: return@runWriteAction emptyList()
|
||||
val insertedMembers = members.mapTo(SmartList<T>()) {
|
||||
if (classOrObject is KtClass && classOrObject.isEnum()) {
|
||||
val enumEntries = classOrObject.declarations.filterIsInstance<KtEnumEntry>()
|
||||
val bound = (enumEntries.lastOrNull() ?: classOrObject.allChildren.firstOrNull { it.node.elementType == KtTokens.SEMICOLON })
|
||||
if (it !is KtEnumEntry) {
|
||||
if (bound != null && afterAnchor.startOffset <= bound.startOffset) {
|
||||
afterAnchor = bound
|
||||
}
|
||||
}
|
||||
else if (bound == null && body.declarations.isNotEmpty()) {
|
||||
afterAnchor = body.lBrace!!
|
||||
}
|
||||
else if (bound != null && afterAnchor.startOffset >= bound.startOffset) {
|
||||
afterAnchor = bound.prevSibling!!
|
||||
}
|
||||
}
|
||||
val (parameters, otherMembers) = members.partition { it is KtParameter }
|
||||
|
||||
parameters.mapNotNullTo(insertedMembers) {
|
||||
if (classOrObject !is KtClass) return@mapNotNullTo null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this }
|
||||
(classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T)
|
||||
}
|
||||
|
||||
if (otherMembers.isNotEmpty()) {
|
||||
val body = classOrObject.getOrCreateBody()
|
||||
|
||||
var afterAnchor = anchor ?: findInsertAfterAnchor(editor, body) ?: return@runWriteAction emptyList()
|
||||
otherMembers.mapNotNullTo(insertedMembers) {
|
||||
if (classOrObject is KtClass && classOrObject.isEnum()) {
|
||||
val enumEntries = classOrObject.declarations.filterIsInstance<KtEnumEntry>()
|
||||
val bound = (enumEntries.lastOrNull() ?: classOrObject.allChildren.firstOrNull { it.node.elementType == KtTokens.SEMICOLON })
|
||||
if (it !is KtEnumEntry) {
|
||||
if (bound != null && afterAnchor.startOffset <= bound.startOffset) {
|
||||
afterAnchor = bound
|
||||
}
|
||||
}
|
||||
else if (bound == null && body.declarations.isNotEmpty()) {
|
||||
afterAnchor = body.lBrace!!
|
||||
}
|
||||
else if (bound != null && afterAnchor.startOffset >= bound.startOffset) {
|
||||
afterAnchor = bound.prevSibling!!
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this }
|
||||
}
|
||||
}
|
||||
|
||||
ShortenReferences.DEFAULT.process(insertedMembers)
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
interface A {
|
||||
val foo: Int
|
||||
}
|
||||
|
||||
class B(<spot>override val foo: Int</spot>) : A {
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
interface A {
|
||||
<spot>val foo: Int</spot>
|
||||
}
|
||||
|
||||
class B : A {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention searches for all classes that can implement selected abstract property, and creates corresponding property parameter there.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1115,6 +1115,11 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.ImplementAbstractMemberAsConstructorParameterIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterAction$Intention</className>
|
||||
<category>Kotlin</category>
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.ide.util.PsiElementListCellRenderer
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.popup.PopupChooserBuilder
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiClass
|
||||
@@ -40,7 +39,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
||||
import org.jetbrains.kotlin.idea.refactoring.runSynchronouslyWithProgress
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||
@@ -48,6 +46,7 @@ import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
@@ -57,10 +56,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import java.util.*
|
||||
import javax.swing.ListSelectionModel
|
||||
|
||||
class ImplementAbstractMemberIntention :
|
||||
abstract class ImplementAbstractMemberIntentionBase :
|
||||
SelfTargetingRangeIntention<KtNamedDeclaration>(KtNamedDeclaration::class.java, "", "Implement abstract member") {
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance("#${ImplementAbstractMemberIntention::class.java.canonicalName}")
|
||||
private val LOG = Logger.getInstance("#${ImplementAbstractMemberIntentionBase::class.java.canonicalName}")
|
||||
}
|
||||
|
||||
private fun isAbstract(element: KtNamedDeclaration): Boolean {
|
||||
@@ -73,7 +72,7 @@ class ImplementAbstractMemberIntention :
|
||||
}
|
||||
}
|
||||
|
||||
private fun findExistingImplementation(
|
||||
protected fun findExistingImplementation(
|
||||
subClass: ClassDescriptor,
|
||||
superMember: CallableMemberDescriptor
|
||||
): CallableMemberDescriptor? {
|
||||
@@ -83,6 +82,8 @@ class ImplementAbstractMemberIntention :
|
||||
if (subMember?.kind?.isReal ?: false) return subMember else return null
|
||||
}
|
||||
|
||||
protected abstract fun acceptSubClass(subClassDescriptor: ClassDescriptor, memberDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
private fun findClassesToProcess(member: KtNamedDeclaration): Sequence<PsiElement> {
|
||||
val baseClass = member.containingClassOrObject as? KtClass ?: return emptySequence()
|
||||
val memberDescriptor = member.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return emptySequence()
|
||||
@@ -94,7 +95,7 @@ class ImplementAbstractMemberIntention :
|
||||
is PsiClass -> subClass.getJavaClassDescriptor()
|
||||
else -> null
|
||||
} as? ClassDescriptor ?: return false
|
||||
return classDescriptor.kind != ClassKind.INTERFACE && findExistingImplementation(classDescriptor, memberDescriptor) == null
|
||||
return acceptSubClass(classDescriptor, memberDescriptor)
|
||||
}
|
||||
|
||||
if (baseClass.isEnum()) {
|
||||
@@ -110,20 +111,20 @@ class ImplementAbstractMemberIntention :
|
||||
.filter(::acceptSubClass)
|
||||
}
|
||||
|
||||
protected abstract fun computeText(element: KtNamedDeclaration): String?
|
||||
|
||||
override fun applicabilityRange(element: KtNamedDeclaration): TextRange? {
|
||||
if (!isAbstract(element)) return null
|
||||
|
||||
text = when(element) {
|
||||
is KtProperty -> "Implement abstract property"
|
||||
is KtNamedFunction -> "Implement abstract function"
|
||||
else -> return null
|
||||
}
|
||||
text = computeText(element) ?: return null
|
||||
|
||||
if (!findClassesToProcess(element).any()) return null
|
||||
|
||||
return element.nameIdentifier?.textRange
|
||||
}
|
||||
|
||||
protected abstract val preferConstructorParameters: Boolean
|
||||
|
||||
private fun implementInKotlinClass(member: KtNamedDeclaration, targetClass: KtClassOrObject) {
|
||||
val subClassDescriptor = targetClass.resolveToDescriptorIfAny() as? ClassDescriptor ?: return
|
||||
val superMemberDescriptor = member.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return
|
||||
@@ -134,7 +135,8 @@ class ImplementAbstractMemberIntention :
|
||||
val chooserObject = OverrideMemberChooserObject.create(member.project,
|
||||
descriptorToImplement,
|
||||
descriptorToImplement,
|
||||
OverrideMemberChooserObject.BodyType.EMPTY)
|
||||
OverrideMemberChooserObject.BodyType.EMPTY,
|
||||
preferConstructorParameters)
|
||||
OverrideImplementMembersHandler.generateMembers(null, targetClass, chooserObject.singletonList())
|
||||
}
|
||||
|
||||
@@ -229,4 +231,43 @@ class ImplementAbstractMemberIntention :
|
||||
.createPopup()
|
||||
.showInBestPositionFor(editor)
|
||||
}
|
||||
}
|
||||
|
||||
class ImplementAbstractMemberIntention : ImplementAbstractMemberIntentionBase() {
|
||||
override fun computeText(element: KtNamedDeclaration): String? {
|
||||
return when(element) {
|
||||
is KtProperty -> "Implement abstract property"
|
||||
is KtNamedFunction -> "Implement abstract function"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun acceptSubClass(subClassDescriptor: ClassDescriptor, memberDescriptor: CallableMemberDescriptor): Boolean {
|
||||
return subClassDescriptor.kind != ClassKind.INTERFACE && findExistingImplementation(subClassDescriptor, memberDescriptor) == null
|
||||
}
|
||||
|
||||
override val preferConstructorParameters: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
class ImplementAbstractMemberAsConstructorParameterIntention : ImplementAbstractMemberIntentionBase() {
|
||||
override fun computeText(element: KtNamedDeclaration): String? {
|
||||
if (element !is KtProperty) return null
|
||||
return "Implement as constructor parameter"
|
||||
}
|
||||
|
||||
override fun acceptSubClass(subClassDescriptor: ClassDescriptor, memberDescriptor: CallableMemberDescriptor): Boolean {
|
||||
val kind = subClassDescriptor.kind
|
||||
return (kind == ClassKind.CLASS || kind == ClassKind.ENUM_CLASS)
|
||||
&& subClassDescriptor !is JavaClassDescriptor
|
||||
&& findExistingImplementation(subClassDescriptor, memberDescriptor) == null
|
||||
}
|
||||
|
||||
override val preferConstructorParameters: Boolean
|
||||
get() = true
|
||||
|
||||
override fun applicabilityRange(element: KtNamedDeclaration): TextRange? {
|
||||
if (element !is KtProperty) return null
|
||||
return super.applicabilityRange(element)
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.isVisible
|
||||
import org.jetbrains.kotlin.idea.refactoring.createPrimaryConstructorParameterListIfAbsent
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
|
||||
+2
-3
@@ -26,15 +26,14 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.refactoring.createPrimaryConstructorIfAbsent
|
||||
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
||||
import org.jetbrains.kotlin.idea.refactoring.replaceListPsiAndKeepDelimiters
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.core.toKeywordToken
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinParameterInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.getCallableSubstitutor
|
||||
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
||||
import org.jetbrains.kotlin.idea.refactoring.replaceListPsiAndKeepDelimiters
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
-1
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages
|
||||
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.refactoring.createPrimaryConstructorParameterListIfAbsent
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.getAffectedCallables
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.isInsideOfCallerBody
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.ui.JBColor
|
||||
import com.intellij.ui.NonFocusableCheckBox
|
||||
import org.jetbrains.kotlin.idea.refactoring.createPrimaryConstructorParameterListIfAbsent
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.AbstractKotlinInplaceIntroducer
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinInplaceVariableIntroducer
|
||||
|
||||
@@ -701,22 +701,6 @@ public fun String.quoteIfNeeded(): String = if (KotlinNameSuggester.isIdentifier
|
||||
|
||||
public fun FqNameUnsafe.hasIdentifiersOnly(): Boolean = pathSegments().all { KotlinNameSuggester.isIdentifier(it.asString()) }
|
||||
|
||||
public fun KtClass.createPrimaryConstructorIfAbsent(): KtPrimaryConstructor {
|
||||
val constructor = getPrimaryConstructor()
|
||||
if (constructor != null) return constructor
|
||||
var anchor: PsiElement? = typeParameterList
|
||||
if (anchor == null) anchor = nameIdentifier
|
||||
if (anchor == null) anchor = lastChild
|
||||
return addAfter(KtPsiFactory(project).createPrimaryConstructor(), anchor) as KtPrimaryConstructor
|
||||
}
|
||||
|
||||
public fun KtClass.createPrimaryConstructorParameterListIfAbsent(): KtParameterList {
|
||||
val constructor = createPrimaryConstructorIfAbsent()
|
||||
val parameterList = constructor.valueParameterList
|
||||
if (parameterList != null) return parameterList
|
||||
return constructor.add(KtPsiFactory(project).createParameterList("()")) as KtParameterList
|
||||
}
|
||||
|
||||
fun PsiNamedElement.isInterfaceClass(): Boolean = this is KtClass && isInterface() || this is PsiClass && isInterface
|
||||
|
||||
fun <ListType : KtElement> replaceListPsiAndKeepDelimiters(
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.core.dropDefaultValue
|
||||
import org.jetbrains.kotlin.idea.intentions.setType
|
||||
import org.jetbrains.kotlin.idea.refactoring.createJavaField
|
||||
import org.jetbrains.kotlin.idea.refactoring.createPrimaryConstructorIfAbsent
|
||||
import org.jetbrains.kotlin.idea.refactoring.safeDelete.removeOverrideModifier
|
||||
import org.jetbrains.kotlin.idea.util.anonymousObjectSuperTypeOrNull
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiUnifier
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.intentions.ImplementAbstractMemberAsConstructorParameterIntention
|
||||
@@ -0,0 +1,9 @@
|
||||
// WITH_RUNTIME
|
||||
// DISABLE-ERRORS
|
||||
interface T<X> {
|
||||
val <caret>foo: X
|
||||
}
|
||||
|
||||
enum class E : T<Int> {
|
||||
A, B, C
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// WITH_RUNTIME
|
||||
// DISABLE-ERRORS
|
||||
interface T<X> {
|
||||
val <caret>foo: X
|
||||
}
|
||||
|
||||
enum class E(override val foo: Int) : T<Int> {
|
||||
A, B, C
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// IS_APPLICABLE: false
|
||||
// DISABLE-ERRORS
|
||||
interface A {
|
||||
abstract fun <caret>foo(): Int
|
||||
}
|
||||
|
||||
class B : A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// WITH_RUNTIME
|
||||
// DISABLE-ERRORS
|
||||
interface T<X> {
|
||||
val <caret>foo: X
|
||||
}
|
||||
|
||||
class U : T<String> {
|
||||
|
||||
}
|
||||
|
||||
class V : T<Int> {
|
||||
|
||||
}
|
||||
|
||||
class Z : T<Int> by V() {
|
||||
|
||||
}
|
||||
|
||||
class W : T<Boolean> {
|
||||
override val foo: Boolean
|
||||
get() = throw UnsupportedOperationException()
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// WITH_RUNTIME
|
||||
// DISABLE-ERRORS
|
||||
interface T<X> {
|
||||
val <caret>foo: X
|
||||
}
|
||||
|
||||
class U(override val foo: String) : T<String> {
|
||||
|
||||
}
|
||||
|
||||
class V(override val foo: Int) : T<Int> {
|
||||
|
||||
}
|
||||
|
||||
class Z : T<Int> by V() {
|
||||
|
||||
}
|
||||
|
||||
class W : T<Boolean> {
|
||||
override val foo: Boolean
|
||||
get() = throw UnsupportedOperationException()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
// DISABLE-ERRORS
|
||||
enum class E {
|
||||
A, B, C;
|
||||
|
||||
abstract val <caret>foo: Int
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: Abstract property 'foo' in non-abstract class 'A'
|
||||
class A {
|
||||
abstract val <caret>foo: Int
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: Abstract property 'foo' in non-abstract class 'A'
|
||||
object A {
|
||||
abstract val <caret>foo: Int
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: Class 'C' must be declared abstract or implement abstract base class member public abstract val foo: kotlin.Int defined in B
|
||||
interface A {
|
||||
val <caret>foo: Int
|
||||
}
|
||||
|
||||
class X : A {
|
||||
override val foo = 1
|
||||
}
|
||||
|
||||
abstract class B : A {
|
||||
abstract override val foo: Int
|
||||
}
|
||||
|
||||
class C: B() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// IS_APPLICABLE: false
|
||||
interface A {
|
||||
val <caret>foo: Int
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// IS_APPLICABLE: false
|
||||
open class A {
|
||||
val <caret>foo = 1
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: Property must be initialized or be abstract
|
||||
open class A {
|
||||
val <caret>foo: Int
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
// IS_APPLICABLE: false
|
||||
interface A {
|
||||
val <caret>foo: Int
|
||||
get() = 1
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package source;
|
||||
|
||||
abstract class X<S> implements T<S> {
|
||||
|
||||
}
|
||||
|
||||
class Y implements T<String> {
|
||||
|
||||
}
|
||||
|
||||
class Z implements T<Boolean> {
|
||||
@Override
|
||||
public Boolean getFoo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface U extends T<Object> {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package source
|
||||
|
||||
interface T<X> {
|
||||
val foo: X
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package source;
|
||||
|
||||
abstract class X<S> implements T<S> {
|
||||
|
||||
}
|
||||
|
||||
class Y implements T<String> {
|
||||
|
||||
}
|
||||
|
||||
class Z implements T<Boolean> {
|
||||
@Override
|
||||
public Boolean getFoo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface U extends T<Object> {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package source
|
||||
|
||||
interface T<X> {
|
||||
val <caret>foo: X
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"mainFile": "source/test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.intentions.ImplementAbstractMemberAsConstructorParameterIntention",
|
||||
"isApplicable": "false",
|
||||
"withRuntime": "true"
|
||||
}
|
||||
@@ -5464,6 +5464,81 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/intentions/implementAsConstructorParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ImplementAsConstructorParameter extends AbstractIntentionTest {
|
||||
public void testAllFilesPresentInImplementAsConstructorParameter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/implementAsConstructorParameter"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("enumClass.kt")
|
||||
public void testEnumClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/enumClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("function.kt")
|
||||
public void testFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/function.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implementAll.kt")
|
||||
public void testImplementAll() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/implementAll.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inEnumClass.kt")
|
||||
public void testInEnumClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/inEnumClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inFinalClass.kt")
|
||||
public void testInFinalClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/inFinalClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inObject.kt")
|
||||
public void testInObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/inObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noDirectOverridesNeeded.kt")
|
||||
public void testNoDirectOverridesNeeded() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/noDirectOverridesNeeded.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noInheritors.kt")
|
||||
public void testNoInheritors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/noInheritors.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notAbstractInClass.kt")
|
||||
public void testNotAbstractInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/notAbstractInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notAbstractNoBodyInClass.kt")
|
||||
public void testNotAbstractNoBodyInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/notAbstractNoBodyInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notAbstractWithGetterInInterface.kt")
|
||||
public void testNotAbstractWithGetterInInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/implementAsConstructorParameter/notAbstractWithGetterInInterface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/intentions/importAllMembers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -53,6 +53,12 @@ public class MultiFileIntentionTestGenerated extends AbstractMultiFileIntentionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implementAsConstructorParameter/implementValInJava/implementAllInJava.test")
|
||||
public void testImplementAsConstructorParameter_implementValInJava_ImplementAllInJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/implementAsConstructorParameter/implementValInJava/implementAllInJava.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveDeclarationToSeparateFile/moveClassToExistingFile/moveClassToExistingFile.test")
|
||||
public void testMoveDeclarationToSeparateFile_moveClassToExistingFile_MoveClassToExistingFile() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/moveDeclarationToSeparateFile/moveClassToExistingFile/moveClassToExistingFile.test");
|
||||
|
||||
Reference in New Issue
Block a user