Misc: Support light-methodless members in overrider search

In particular, support line markers for expect-class members
and navigation to expect-class members from corresponding base members
This commit is contained in:
Alexey Sedunov
2017-09-27 13:29:58 +03:00
parent 17abce2811
commit 4cc1e22a5a
22 changed files with 292 additions and 86 deletions
@@ -18,14 +18,19 @@ package org.jetbrains.kotlin.idea.caches.resolve.lightClasses
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElementFactory
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiType
import com.intellij.psi.impl.light.AbstractLightClass
import com.intellij.psi.impl.light.LightMethod
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -58,4 +63,28 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
val thisDescriptor = kotlinOrigin.resolveToDescriptorIfAny() as? ClassDescriptor ?: return false
return if (checkDeep) DescriptorUtils.isSubclass(thisDescriptor, baseDescriptor) else DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
}
}
class KtFakeLightMethod private constructor(
val ktDeclaration: KtNamedDeclaration,
ktClassOrObject : KtClassOrObject
) : LightMethod (
ktDeclaration.manager,
PsiElementFactory.SERVICE.getInstance(ktDeclaration.project).createMethod(ktDeclaration.name ?: "", PsiType.VOID),
KtFakeLightClass(ktClassOrObject),
KotlinLanguage.INSTANCE
), KtLightElement<KtNamedDeclaration, PsiMethod> {
override val kotlinOrigin get() = ktDeclaration
override val clsDelegate get() = myMethod
override fun getNavigationElement() = ktDeclaration
override fun getIcon(flags: Int) = ktDeclaration.getIcon(flags)
override fun getUseScope() = ktDeclaration.useScope
companion object {
fun get(ktDeclaration: KtNamedDeclaration): KtFakeLightMethod? {
val ktClassOrObject = ktDeclaration.containingClassOrObject ?: return null
return KtFakeLightMethod(ktDeclaration, ktClassOrObject)
}
}
}
@@ -23,12 +23,13 @@ import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.util.EmptyQuery
import com.intellij.util.Query
import org.jetbrains.kotlin.asJava.toLightClassWithBuiltinMapping
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtClassOrObject
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
val psiClass: PsiClass = when (originalElement) {
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() }
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) }
is PsiClass -> originalElement
else -> null
} ?: return EmptyQuery.getEmptyQuery()
@@ -29,14 +29,14 @@ import com.intellij.util.EmptyQuery
import com.intellij.util.MergeQuery
import com.intellij.util.Processor
import com.intellij.util.Query
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.isOverridable
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
@@ -45,10 +45,7 @@ import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
@@ -122,6 +119,17 @@ object PsiMethodOverridingHierarchyTraverser: HierarchyTraverser<PsiMethod> {
override fun shouldDescend(element: PsiMethod): Boolean = PsiUtil.canBeOverriden(element)
}
fun PsiElement.toPossiblyFakeLightMethods(): List<PsiMethod> {
if (this is PsiMethod) return listOf(this)
val element = unwrapped ?: return emptyList()
val lightMethods = element.toLightMethods()
if (lightMethods.isNotEmpty()) return lightMethods
return if (element is KtNamedDeclaration) listOfNotNull(KtFakeLightMethod.get(element)) else emptyList()
}
private fun forEachKotlinOverride(
ktClass: KtClass,
members: List<KtNamedDeclaration>,
@@ -133,7 +141,7 @@ private fun forEachKotlinOverride(
if (baseDescriptors.isEmpty()) return true
HierarchySearchRequest(ktClass, scope.restrictToKotlinSources(), true).searchInheritors().forEach {
val inheritor = (it as? KtLightClass)?.kotlinOrigin ?: return@forEach
val inheritor = it.unwrapped as? KtClassOrObject ?: return@forEach
val inheritorDescriptor = runReadAction { inheritor.unsafeResolveToDescriptor() as ClassDescriptor }
val substitutor = getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@forEach
baseDescriptors.forEach {
@@ -149,16 +157,31 @@ private fun forEachKotlinOverride(
return true
}
fun KtNamedDeclaration.forEachOverridingElement(
scope: SearchScope = runReadAction { useScope },
processor: (PsiElement) -> Boolean
): Boolean {
val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true
toLightMethods().forEach {
if (!OverridingMethodsSearch.search(it, scope.excludeKotlinSources(), true).all(processor)) return false
}
return forEachKotlinOverride(ktClass, listOf(this), scope) { _, overrider -> processor(overrider) }
}
fun PsiMethod.forEachOverridingMethod(
scope: SearchScope = runReadAction { useScope },
processor: (PsiMethod) -> Boolean
): Boolean {
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
if (this !is KtFakeLightMethod) {
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
}
val ktMember = (this as? KtLightMethod)?.kotlinOrigin as? KtNamedDeclaration ?: return true
val ktMember = this.unwrapped as? KtNamedDeclaration ?: return true
val ktClass = runReadAction { ktMember.containingClassOrObject as? KtClass } ?: return true
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
val lightMethods = runReadAction { overrider.toLightMethods() }
val lightMethods = runReadAction { overrider.toPossiblyFakeLightMethods() }
lightMethods.all { processor(it) }
}
}
@@ -174,9 +197,11 @@ fun PsiMethod.forEachImplementation(
fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) {
val scope = runReadAction { useScope }
AllOverridingMethodsSearch.search(this, scope.excludeKotlinSources()).all { processor(it.first, it.second) }
if (this !is KtFakeLightClass) {
AllOverridingMethodsSearch.search(this, scope.excludeKotlinSources()).all { processor(it.first, it.second) }
}
val ktClass = (this as? KtLightClass)?.kotlinOrigin as? KtClass ?: return
val ktClass = unwrapped as? KtClass ?: return
val members = ktClass.declarations.filterIsInstance<KtNamedDeclaration>() +
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
forEachKotlinOverride(ktClass, members, scope, processor)
@@ -21,13 +21,11 @@ import com.intellij.psi.CommonClassNames
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.*
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import java.util.*
fun collectContainingClasses(methods: Collection<PsiMethod>): Set<PsiClass> {
@@ -58,7 +56,8 @@ internal fun getPsiMethod(element: PsiElement?): PsiMethod? {
return when {
element == null -> null
element is PsiMethod -> element
parent is KtNamedFunction || parent is KtSecondaryConstructor -> LightClassUtil.getLightClassMethod(parent as KtFunction)
parent is KtNamedFunction || parent is KtSecondaryConstructor ->
LightClassUtil.getLightClassMethod(parent as KtFunction) ?: KtFakeLightMethod.get(parent)
else -> null
}
}
@@ -34,7 +34,6 @@ import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.search.searches.ClassInheritorsSearch
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
@@ -42,11 +41,13 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
import org.jetbrains.kotlin.idea.core.isInheritable
import org.jetbrains.kotlin.idea.core.isOverridable
import org.jetbrains.kotlin.idea.core.toDescriptor
import org.jetbrains.kotlin.idea.facet.implementedDescriptor
import org.jetbrains.kotlin.idea.facet.implementingDescriptors
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
@@ -271,10 +272,7 @@ private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDec
val mappingToJava = HashMap<PsiElement, KtNamedDeclaration>()
for (property in properties) {
if (property.isOverridable()) {
val accessorsPsiMethods = property.getAccessorLightMethods()
for (psiMethod in accessorsPsiMethods) {
mappingToJava.put(psiMethod, property)
}
property.toPossiblyFakeLightMethods().forEach { mappingToJava.put(it, property) }
mappingToJava[property] = property
}
}
@@ -352,7 +350,7 @@ private fun collectOverriddenFunctions(functions: Collection<KtNamedFunction>, r
val mappingToJava = HashMap<PsiElement, KtNamedFunction>()
for (function in functions) {
if (function.isOverridable()) {
val method = LightClassUtil.getLightClassMethod(function)
val method = LightClassUtil.getLightClassMethod(function) ?: KtFakeLightMethod.get(function)
if (method != null) {
mappingToJava.put(method, function)
}
@@ -24,18 +24,20 @@ import com.intellij.ide.util.PsiElementListCellRenderer
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.DumbService
import com.intellij.psi.*
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.search.PsiElementProcessor
import com.intellij.psi.search.PsiElementProcessorAdapter
import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.psi.util.PsiFormatUtil
import com.intellij.util.CommonProcessors
import gnu.trove.THashSet
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.isTraitFakeOverride
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachDeclaredMemberOverride
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.awt.event.MouseEvent
import java.util.*
@@ -50,7 +52,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
for (aClass in classes) {
aClass.forEachDeclaredMemberOverride { superMember, overridingMember ->
ProgressManager.checkCanceled()
if (overridingMember.toLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
if (overridingMember.toPossiblyFakeLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
val declaration = mappingToJava[superMember]
if (declaration != null) {
mappingToJava.remove(superMember)
@@ -67,7 +69,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
fun getOverriddenMethodTooltip(method: PsiMethod): String? {
val processor = PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5)
OverridingMethodsSearch.search(method, true).forEach(PsiElementProcessorAdapter(processor))
method.forEachOverridingMethod(processor = PsiElementProcessorAdapter(processor)::process)
val isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT)
@@ -109,15 +111,7 @@ fun buildNavigateToOverriddenMethodPopup(e: MouseEvent?, element: PsiElement?):
var overridingJavaMethods = processor.collection.filter { !it.isMethodWithDeclarationInOtherClass() }
if (overridingJavaMethods.isEmpty()) return null
val renderedSignatures = overridingJavaMethods.map {
PsiFormatUtil.formatMethod(it,
PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_PARAMETERS + PsiFormatUtil.SHOW_FQ_CLASS_NAMES,
PsiFormatUtil.SHOW_TYPE + PsiFormatUtil.SHOW_FQ_CLASS_NAMES)
}
val showMethodNames = renderedSignatures.distinct().size > 1
val renderer = MethodCellRenderer(showMethodNames)
val renderer = MethodCellRenderer(false)
overridingJavaMethods = overridingJavaMethods.sortedWith(renderer.comparator)
val methodsUpdater = OverridingMethodsUpdater(method, renderer)
@@ -33,9 +33,10 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.util.AdapterProcessor
import com.intellij.util.CommonProcessors
import com.intellij.util.Function
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
@@ -50,9 +51,9 @@ fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? {
Function { method: PsiMethod? -> method?.containingClass }
)
for (method in property.getAccessorLightMethods()) {
for (method in property.toPossiblyFakeLightMethods()) {
if (!overriddenInClassesProcessor.isOverflow) {
OverridingMethodsSearch.search(method, true).forEach(consumer)
method.forEachOverridingMethod(processor = consumer::process)
}
}
@@ -85,11 +86,7 @@ fun buildNavigateToPropertyOverriddenDeclarationsPopup(e: MouseEvent?, element:
return null
}
val psiPropertyMethods = when(propertyOrParameter) {
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
else -> return null
}
val psiPropertyMethods = propertyOrParameter.toPossiblyFakeLightMethods()
val elementProcessor = CommonProcessors.CollectUniquesProcessor<PsiElement>()
val ktPsiMethodProcessor = Runnable {
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.search.ideaExtensions
import com.intellij.codeInsight.navigation.MethodImplementationsSearch
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
@@ -28,13 +27,14 @@ import com.intellij.psi.search.searches.DefinitionsScopedSearch
import com.intellij.util.Processor
import com.intellij.util.QueryExecutor
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachImplementation
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.contains
@@ -117,29 +117,21 @@ class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSea
}
private fun processFunctionImplementations(function: KtFunction, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
val psiMethod = runReadAction { LightClassUtil.getLightClassMethod(function) }
return psiMethod?.forEachImplementation(scope, consumer::process) ?: true
return runReadAction {
function.toPossiblyFakeLightMethods().firstOrNull()?.forEachImplementation(scope, consumer::process) ?: true
}
}
private fun processPropertyImplementations(parameter: KtParameter, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(parameter) }
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
private fun processPropertyImplementations(declaration: KtNamedDeclaration, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
return runReadAction {
processPropertyImplementationsMethods(declaration.toPossiblyFakeLightMethods(), scope, consumer)
}
}
private fun processPropertyImplementations(property: KtProperty, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(property) }
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
}
fun processPropertyImplementationsMethods(accessors: LightClassUtil.PropertyAccessorsPsiMethods, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
for (method in accessors) {
val implementations = ArrayList<PsiMethod>()
MethodImplementationsSearch.getOverridingMethods(method, implementations, scope)
for (implementation in implementations) {
if (isDelegated(implementation)) continue
fun processPropertyImplementationsMethods(accessors: Iterable<PsiMethod>, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
return accessors.all { method ->
method.forEachOverridingMethod(scope) { implementation ->
if (isDelegated(implementation)) return@forEachOverridingMethod true
val elementToProcess = runReadAction {
val mirrorElement = (implementation as? KtLightMethod)?.kotlinOrigin
@@ -150,12 +142,9 @@ class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSea
}
}
if (!consumer.process(elementToProcess)) {
return false
}
consumer.process(elementToProcess)
}
}
return true
}
}
}
@@ -3,5 +3,5 @@ enum class SampleEnum {
override fun <lineMarker descr="Overrides function in 'SampleEnum'">any</lineMarker>() { super.any() }
};
open fun <lineMarker descr="<html><body>Is overridden in <br>&nbsp;&nbsp;&nbsp;&nbsp;Enum constant 'V1' in 'SampleEnum'</body></html>">any</lineMarker>() {}
open fun <lineMarker descr="<html><body>Is overridden in <br>&nbsp;&nbsp;&nbsp;&nbsp;SampleEnum.V1</body></html>">any</lineMarker>() {}
}
@@ -1,9 +1,21 @@
package test
open class <lineMarker>SimpleParent</lineMarker>
open class <lineMarker>SimpleParent</lineMarker> {
open fun <lineMarker>foo</lineMarker>(n: Int) {}
open val <lineMarker>bar</lineMarker>: Int get() = 1
}
expect open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent
expect open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent {
override fun <lineMarker><lineMarker>foo</lineMarker></lineMarker>(n: Int)
override val <lineMarker><lineMarker>bar</lineMarker></lineMarker>: Int
}
class ExpectedChildChild : ExpectedChild()
class ExpectedChildChild : ExpectedChild() {
override fun <lineMarker>foo</lineMarker>(n: Int) {}
override val <lineMarker>bar</lineMarker>: Int get() = 1
}
class SimpleChild : SimpleParent()
class SimpleChild : SimpleParent() {
override fun <lineMarker>foo</lineMarker>(n: Int) {}
override val <lineMarker>bar</lineMarker>: Int get() = 1
}
@@ -2,6 +2,12 @@
package test
actual open class ExpectedChild : SimpleParent()
actual open class ExpectedChild : SimpleParent() {
actual override fun foo(n: Int) {}
actual override val bar: Int get() = 1
}
class ExpectedChildChildJvm : ExpectedChild()
class ExpectedChildChildJvm : ExpectedChild() {
override fun foo(n: Int) {}
override val bar: Int get() = 1
}
@@ -2,10 +2,22 @@
package test
open class <caret>SimpleParent
open class SimpleParent {
open fun foo(n: Int) {}
open val bar: Int get() = 1
}
expect open class ExpectedChild : SimpleParent
expect open class ExpectedChild : SimpleParent {
override fun foo(n: Int)
override val bar: Int
}
class ExpectedChildChild : ExpectedChild()
class ExpectedChildChild : ExpectedChild() {
override fun foo(n: Int) {}
override val bar: Int get() = 1
}
class SimpleChild : SimpleParent()
class SimpleChild : SimpleParent() {
override fun foo(n: Int) {}
override val bar: Int get() = 1
}
@@ -1,5 +1,11 @@
package test
actual open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent()
actual open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent() {
actual override fun <lineMarker><lineMarker><lineMarker>foo</lineMarker></lineMarker></lineMarker>(n: Int) {}
actual override val <lineMarker><lineMarker><lineMarker>bar</lineMarker></lineMarker></lineMarker>: Int get() = 1
}
class ExpectedChildChildJvm : ExpectedChild()
class ExpectedChildChildJvm : ExpectedChild() {
override fun <lineMarker>foo</lineMarker>(n: Int) {}
override val <lineMarker>bar</lineMarker>: Int get() = 1
}
@@ -0,0 +1,20 @@
package test
open class SimpleParent {
open fun foo(n: Int) {}
}
expect open class ExpectedChild : SimpleParent {
override fun <caret>foo(n: Int)
}
class ExpectedChildChild : ExpectedChild() {
override fun foo(n: Int) {}
}
class SimpleChild : SimpleParent() {
override fun foo(n: Int) {}
}
// REF: [common] (in test.ExpectedChildChild).foo(Int)
// REF: [jvm] (in test.ExpectedChildChildJvm).foo(Int)
@@ -0,0 +1,9 @@
package test
actual open class ExpectedChild : SimpleParent() {
actual override fun foo(n: Int) {}
}
class ExpectedChildChildJvm : ExpectedChild() {
override fun foo(n: Int) {}
}
@@ -0,0 +1,20 @@
package test
open class SimpleParent {
open val bar: Int get() = 1
}
expect open class ExpectedChild : SimpleParent {
override val <caret>bar: Int
}
class ExpectedChildChild : ExpectedChild() {
override val bar: Int get() = 1
}
class SimpleChild : SimpleParent() {
override val bar: Int get() = 1
}
// REF: [common] (in test.ExpectedChildChild).bar
// REF: [jvm] (in test.ExpectedChildChildJvm).bar
@@ -0,0 +1,9 @@
package test
actual open class ExpectedChild : SimpleParent() {
actual override val bar: Int get() = 1
}
class ExpectedChildChildJvm : ExpectedChild() {
override val bar: Int get() = 1
}
@@ -0,0 +1,23 @@
package test
open class SimpleParent {
open fun <caret>foo(n: Int) {}
}
expect open class ExpectedChild : SimpleParent {
override fun foo(n: Int)
}
class ExpectedChildChild : ExpectedChild() {
override fun foo(n: Int) {}
}
class SimpleChild : SimpleParent() {
override fun foo(n: Int) {}
}
// REF: [common] (in test.ExpectedChild).foo(Int)
// REF: [common] (in test.ExpectedChildChild).foo(Int)
// REF: [common] (in test.SimpleChild).foo(Int)
// REF: [jvm] (in test.ExpectedChild).foo(Int)
// REF: [jvm] (in test.ExpectedChildChildJvm).foo(Int)
@@ -0,0 +1,9 @@
package test
actual open class ExpectedChild : SimpleParent() {
actual override fun foo(n: Int) {}
}
class ExpectedChildChildJvm : ExpectedChild() {
override fun foo(n: Int) {}
}
@@ -0,0 +1,23 @@
package test
open class SimpleParent {
open val <caret>bar: Int get() = 1
}
expect open class ExpectedChild : SimpleParent {
override val bar: Int
}
class ExpectedChildChild : ExpectedChild() {
override val bar: Int get() = 1
}
class SimpleChild : SimpleParent() {
override val bar: Int get() = 1
}
// REF: [common] (in test.ExpectedChild).bar
// REF: [common] (in test.ExpectedChildChild).bar
// REF: [common] (in test.SimpleChild).bar
// REF: [jvm] (in test.ExpectedChild).bar
// REF: [jvm] (in test.ExpectedChildChildJvm).bar
@@ -0,0 +1,9 @@
package test
actual open class ExpectedChild : SimpleParent() {
actual override val bar: Int get() = 1
}
class ExpectedChildChildJvm : ExpectedChild() {
override val bar: Int get() = 1
}
@@ -72,7 +72,23 @@ class KotlinGotoImplementationMultiModuleTest : AbstractMultiModuleTest() {
doMultiPlatformTest("common.kt")
}
fun testExpectClassSuperclassFun() {
doMultiPlatformTest("common.kt")
}
fun testExpectClassSuperclassProperty() {
doMultiPlatformTest("common.kt")
}
fun testExpectClass() {
doMultiPlatformTest("common.kt")
}
fun testExpectClassFun() {
doMultiPlatformTest("common.kt")
}
fun testExpectClassProperty() {
doMultiPlatformTest("common.kt")
}
}