FIR: handle member scope for anonymous objects

#KT-37120 fixed
This commit is contained in:
Ilya Kirillov
2020-04-22 11:58:32 +03:00
parent fdfb544730
commit 1a90866ce1
6 changed files with 89 additions and 67 deletions
@@ -7,22 +7,22 @@
val case1 = object : A { val case1 = object : A {
inner class Child(property: B) : Base(property) { inner class Child(property: B) : Base(property) {
fun Base.zoo() { fun Base.zoo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
fun foo() { fun foo() {
<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE baseFun()
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
<!UNRESOLVED_REFERENCE!>zoo<!>() //UNRESOLVED_REFERENCE zoo()
hoo() hoo()
} }
} }
fun Child.voo() { fun <!EXPOSED_RECEIVER_TYPE!>Child<!>.voo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
fun Base.hoo() { fun <!EXPOSED_RECEIVER_TYPE!>Base<!>.hoo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
open inner class Base(/*protected*/ val property: B) { open inner class Base(/*protected*/ val property: B) {
@@ -32,8 +32,8 @@ val case1 = object : A {
fun caseForBase() { fun caseForBase() {
val base = Base(B()) val base = Base(B())
/*member of Base*/ /*member of Base*/
base.<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE base.baseFun()
base.<!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE base.property
/*extensions*/ /*extensions*/
base.hoo() base.hoo()
} }
@@ -41,10 +41,10 @@ val case1 = object : A {
fun caseForChild() { fun caseForChild() {
val child = Child(B()) val child = Child(B())
/*member of Base*/ /*member of Base*/
child.<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE child.baseFun()
child.<!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE child.property
/*member of Child*/ /*member of Child*/
child.<!UNRESOLVED_REFERENCE!>foo<!>() //UNRESOLVED_REFERENCE child.foo()
/*extensions*/ /*extensions*/
child.hoo() child.hoo()
child.voo() child.voo()
@@ -100,22 +100,22 @@ class Case3() {
val x = object : A { val x = object : A {
inner class Child(property: B) : Base(property) { inner class Child(property: B) : Base(property) {
fun Base.zoo() { fun Base.zoo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
fun foo() { fun foo() {
<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE baseFun()
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
<!UNRESOLVED_REFERENCE!>zoo<!>() zoo()
hoo() hoo()
} }
} }
fun Child.voo() { fun <!EXPOSED_RECEIVER_TYPE!>Child<!>.voo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
fun Base.hoo() { fun <!EXPOSED_RECEIVER_TYPE!>Base<!>.hoo() {
val x = <!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE val x = property
} }
open inner class Base(/*protected*/ val property: B) { open inner class Base(/*protected*/ val property: B) {
@@ -125,8 +125,8 @@ class Case3() {
fun caseForBase() { fun caseForBase() {
val base = Base(B()) val base = Base(B())
/*member of Base*/ /*member of Base*/
base.<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE base.baseFun()
base.<!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE base.property
/*extensions*/ /*extensions*/
base.hoo() base.hoo()
} }
@@ -134,10 +134,10 @@ class Case3() {
fun caseForChild() { fun caseForChild() {
val child = Child(B()) val child = Child(B())
/*member of Base*/ /*member of Base*/
child.<!UNRESOLVED_REFERENCE!>baseFun<!>() //UNRESOLVED_REFERENCE child.baseFun()
child.<!UNRESOLVED_REFERENCE!>property<!> //UNRESOLVED_REFERENCE child.property
/*member of Child*/ /*member of Child*/
child.<!UNRESOLVED_REFERENCE!>foo<!>() //UNRESOLVED_REFERENCE child.foo()
/*extensions*/ /*extensions*/
child.hoo() child.hoo()
child.voo() child.voo()
@@ -4,30 +4,30 @@ FILE: objectInnerClass.kt
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
local final inner class Child : R|ERROR CLASS: Symbol not found, for `Base`| { local final inner class Child : R|<anonymous>.Base| {
public[local] constructor(property: R|B|): R|<anonymous>.Child| { public[local] constructor(property: R|B|): R|<anonymous>.Child| {
super<R|ERROR CLASS: Symbol not found, for `Base`|>(R|<local>/property|) super<R|<anonymous>.Base|>(R|<local>/property|)
} }
public[local] final fun R|ERROR CLASS: Symbol not found, for `Base`|.zoo(): R|kotlin/Unit| { public[local] final fun R|<anonymous>.Base|.zoo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/<anonymous>.Child.zoo|.R|/<anonymous>.Base.property|
} }
public[local] final fun foo(): R|kotlin/Unit| { public[local] final fun foo(): R|kotlin/Unit| {
<Unresolved name: baseFun>#() this@R|/<anonymous>.Child|.R|/<anonymous>.Base.baseFun|()
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/<anonymous>.Child|.R|/<anonymous>.Base.property|
<Unresolved name: zoo>#() (this@R|/<anonymous>.Child|, this@R|/<anonymous>.Child|).R|/<anonymous>.Child.zoo|()
(this@R|/anonymous|, this@R|/<anonymous>.Child|).R|/anonymous.hoo|() (this@R|/anonymous|, this@R|/<anonymous>.Child|).R|/anonymous.hoo|()
} }
} }
public final fun R|ERROR CLASS: Symbol not found, for `Child`|.voo(): R|kotlin/Unit| { public final fun R|<anonymous>.Child|.voo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/anonymous.voo|.R|/<anonymous>.Base.property|
} }
public final fun R|ERROR CLASS: Symbol not found, for `Base`|.hoo(): R|kotlin/Unit| { public final fun R|<anonymous>.Base|.hoo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/anonymous.hoo|.R|/<anonymous>.Base.property|
} }
local open inner class Base : R|kotlin/Any| { local open inner class Base : R|kotlin/Any| {
@@ -45,16 +45,16 @@ FILE: objectInnerClass.kt
public final fun caseForBase(): R|kotlin/Unit| { public final fun caseForBase(): R|kotlin/Unit| {
lval base: R|<anonymous>.Base| = this@R|/anonymous|.R|/<anonymous>.Base.Base|(R|/B.B|()) lval base: R|<anonymous>.Base| = this@R|/anonymous|.R|/<anonymous>.Base.Base|(R|/B.B|())
R|<local>/base|.<Unresolved name: baseFun>#() R|<local>/base|.R|/<anonymous>.Base.baseFun|()
R|<local>/base|.<Unresolved name: property># R|<local>/base|.R|/<anonymous>.Base.property|
(this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|() (this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|()
} }
public final fun caseForChild(): R|kotlin/Unit| { public final fun caseForChild(): R|kotlin/Unit| {
lval child: R|<anonymous>.Child| = this@R|/anonymous|.R|/<anonymous>.Child.Child|(R|/B.B|()) lval child: R|<anonymous>.Child| = this@R|/anonymous|.R|/<anonymous>.Child.Child|(R|/B.B|())
R|<local>/child|.<Unresolved name: baseFun>#() R|<local>/child|.R|/<anonymous>.Base.baseFun|()
R|<local>/child|.<Unresolved name: property># R|<local>/child|.R|/<anonymous>.Base.property|
R|<local>/child|.<Unresolved name: foo>#() R|<local>/child|.R|/<anonymous>.Child.foo|()
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|() (this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|()
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|() (this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|()
} }
@@ -129,30 +129,30 @@ FILE: objectInnerClass.kt
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
local final inner class Child : R|ERROR CLASS: Symbol not found, for `Base`| { local final inner class Child : R|Case3.<anonymous>.Base| {
public[local] constructor(property: R|B|): R|Case3.<anonymous>.Child| { public[local] constructor(property: R|B|): R|Case3.<anonymous>.Child| {
super<R|ERROR CLASS: Symbol not found, for `Base`|>(R|<local>/property|) super<R|Case3.<anonymous>.Base|>(R|<local>/property|)
} }
public[local] final fun R|ERROR CLASS: Symbol not found, for `Base`|.zoo(): R|kotlin/Unit| { public[local] final fun R|Case3.<anonymous>.Base|.zoo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/Case3.<anonymous>.Child.zoo|.R|/Case3.<anonymous>.Base.property|
} }
public[local] final fun foo(): R|kotlin/Unit| { public[local] final fun foo(): R|kotlin/Unit| {
<Unresolved name: baseFun>#() this@R|/Case3.<anonymous>.Child|.R|/Case3.<anonymous>.Base.baseFun|()
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/Case3.<anonymous>.Child|.R|/Case3.<anonymous>.Base.property|
<Unresolved name: zoo>#() (this@R|/Case3.<anonymous>.Child|, this@R|/Case3.<anonymous>.Child|).R|/Case3.<anonymous>.Child.zoo|()
(this@R|/anonymous|, this@R|/Case3.<anonymous>.Child|).R|/anonymous.hoo|() (this@R|/anonymous|, this@R|/Case3.<anonymous>.Child|).R|/anonymous.hoo|()
} }
} }
public final fun R|ERROR CLASS: Symbol not found, for `Child`|.voo(): R|kotlin/Unit| { public final fun R|Case3.<anonymous>.Child|.voo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/anonymous.voo|.R|/Case3.<anonymous>.Base.property|
} }
public final fun R|ERROR CLASS: Symbol not found, for `Base`|.hoo(): R|kotlin/Unit| { public final fun R|Case3.<anonymous>.Base|.hoo(): R|kotlin/Unit| {
lval x: <ERROR TYPE REF: Unresolved name: property> = <Unresolved name: property># lval x: R|B| = this@R|/anonymous.hoo|.R|/Case3.<anonymous>.Base.property|
} }
local open inner class Base : R|kotlin/Any| { local open inner class Base : R|kotlin/Any| {
@@ -170,16 +170,16 @@ FILE: objectInnerClass.kt
public final fun caseForBase(): R|kotlin/Unit| { public final fun caseForBase(): R|kotlin/Unit| {
lval base: R|Case3.<anonymous>.Base| = R|/Case3.<anonymous>.Base.Base|(R|/B.B|()) lval base: R|Case3.<anonymous>.Base| = R|/Case3.<anonymous>.Base.Base|(R|/B.B|())
R|<local>/base|.<Unresolved name: baseFun>#() R|<local>/base|.R|/Case3.<anonymous>.Base.baseFun|()
R|<local>/base|.<Unresolved name: property># R|<local>/base|.R|/Case3.<anonymous>.Base.property|
(this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|() (this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|()
} }
public final fun caseForChild(): R|kotlin/Unit| { public final fun caseForChild(): R|kotlin/Unit| {
lval child: R|Case3.<anonymous>.Child| = R|/Case3.<anonymous>.Child.Child|(R|/B.B|()) lval child: R|Case3.<anonymous>.Child| = R|/Case3.<anonymous>.Child.Child|(R|/B.B|())
R|<local>/child|.<Unresolved name: baseFun>#() R|<local>/child|.R|/Case3.<anonymous>.Base.baseFun|()
R|<local>/child|.<Unresolved name: property># R|<local>/child|.R|/Case3.<anonymous>.Base.property|
R|<local>/child|.<Unresolved name: foo>#() R|<local>/child|.R|/Case3.<anonymous>.Child.foo|()
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|() (this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|()
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|() (this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|()
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
@@ -32,25 +33,28 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
} }
protected fun resolveNestedClassesSupertypes( protected fun resolveNestedClassesSupertypes(
regularClass: FirRegularClass, firClass: FirClass<*>,
data: Nothing? data: Nothing?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
return withScopeCleanup { return withScopeCleanup {
// ? Is it Ok to use original file session here ? // ? Is it Ok to use original file session here ?
val superTypes = lookupSuperTypes(regularClass, lookupInterfaces = false, deep = true, useSiteSession = session).asReversed() val superTypes = lookupSuperTypes(firClass, lookupInterfaces = false, deep = true, useSiteSession = session).asReversed()
for (superType in superTypes) { for (superType in superTypes) {
session.getNestedClassifierScope(superType.lookupTag)?.let { session.getNestedClassifierScope(superType.lookupTag)?.let {
towerScope.addScope(it) towerScope.addScope(it)
} }
} }
regularClass.addTypeParametersScope() if (firClass is FirRegularClass) {
val companionObject = regularClass.companionObject firClass.addTypeParametersScope()
if (companionObject != null) { val companionObject = firClass.companionObject
towerScope.addScope(nestedClassifierScope(companionObject)) if (companionObject != null) {
towerScope.addScope(nestedClassifierScope(companionObject))
}
} }
towerScope.addScope(nestedClassifierScope(regularClass))
transformElement(regularClass, data) towerScope.addScope(nestedClassifierScope(firClass))
transformElement(firClass, data)
} }
} }
@@ -77,6 +77,10 @@ private class FirTypeResolveTransformer(
return resolveNestedClassesSupertypes(regularClass, data) return resolveNestedClassesSupertypes(regularClass, data)
} }
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Nothing?): CompositeTransformResult<FirStatement> {
return resolveNestedClassesSupertypes(anonymousObject, data)
}
override fun transformConstructor(constructor: FirConstructor, data: Nothing?): CompositeTransformResult<FirDeclaration> { override fun transformConstructor(constructor: FirConstructor, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup { return withScopeCleanup {
constructor.addTypeParametersScope() constructor.addTypeParametersScope()
@@ -0,0 +1,15 @@
class A<T> {
fun foo() {
val q = object {
open inner class B
inner class C : B()
// No WRONG_NUMBER_OF_TYPE_ARGUMENTS should be reported on these types
val <!EXPOSED_PROPERTY_TYPE!>x<!>: B = B()
val <!EXPOSED_PROPERTY_TYPE!>y<!>: C = C()
}
q.x
q.y
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
class A<T> { class A<T> {
fun foo() { fun foo() {
val q = object { val q = object {