[FIR] Fix resolving of local class reference chain ^KT-47135 Fixed

This commit is contained in:
Ivan Kochurkin
2021-10-06 20:20:30 +03:00
committed by TeamCityServer
parent cbfe0ac073
commit 3dd8ad3599
8 changed files with 78 additions and 8 deletions
@@ -24083,6 +24083,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt");
} }
@Test
@TestMetadata("LocalClassReferenceChain.kt")
public void testLocalClassReferenceChain() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt");
}
@Test @Test
@TestMetadata("noThis.kt") @TestMetadata("noThis.kt")
public void testNoThis() throws Exception { public void testNoThis() throws Exception {
@@ -24083,6 +24083,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt");
} }
@Test
@TestMetadata("LocalClassReferenceChain.kt")
public void testLocalClassReferenceChain() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt");
}
@Test @Test
@TestMetadata("noThis.kt") @TestMetadata("noThis.kt")
public void testNoThis() throws Exception { public void testNoThis() throws Exception {
@@ -24083,6 +24083,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt");
} }
@Test
@TestMetadata("LocalClassReferenceChain.kt")
public void testLocalClassReferenceChain() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt");
}
@Test @Test
@TestMetadata("noThis.kt") @TestMetadata("noThis.kt")
public void testNoThis() throws Exception { public void testNoThis() throws Exception {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -68,19 +69,21 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
val qualifierResolver = session.qualifierResolver val qualifierResolver = session.qualifierResolver
var resolvedSymbol: FirBasedSymbol<*>? = null var resolvedSymbol: FirBasedSymbol<*>? = null
var substitutor: ConeSubstitutor? = null var substitutor: ConeSubstitutor? = null
scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope -> val qualifier = typeRef.qualifier
scope.processClassifiersByNameWithSubstitution(qualifier.first().name) { symbol, substitutorFromScope ->
if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution
resolvedSymbol = when (symbol) { resolvedSymbol = when (symbol) {
is FirClassLikeSymbol<*> -> { is FirClassLikeSymbol<*> -> {
if (typeRef.qualifier.size == 1) { if (qualifier.size == 1) {
symbol symbol
} else { } else {
qualifierResolver.resolveSymbolWithPrefix(typeRef.qualifier, symbol.classId) resolveLocalClassChain(symbol, qualifier)
?: qualifierResolver.resolveEnumEntrySymbol(typeRef.qualifier, symbol.classId) ?: qualifierResolver.resolveSymbolWithPrefix(qualifier, symbol.classId)
?: qualifierResolver.resolveEnumEntrySymbol(qualifier, symbol.classId)
} }
} }
is FirTypeParameterSymbol -> { is FirTypeParameterSymbol -> {
assert(typeRef.qualifier.size == 1) assert(qualifier.size == 1)
symbol symbol
} }
else -> error("!") else -> error("!")
@@ -89,7 +92,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
} }
// TODO: Imports // TODO: Imports
val resultSymbol: FirBasedSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier) val resultSymbol: FirBasedSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(qualifier)
resultSymbol to substitutor resultSymbol to substitutor
} }
@@ -101,6 +104,31 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
} }
} }
private fun resolveLocalClassChain(symbol: FirClassLikeSymbol<*>, qualifier: List<FirQualifierPart>): FirRegularClassSymbol? {
if (symbol !is FirRegularClassSymbol || !symbol.isLocal) {
return null
}
fun resolveLocalClassChain(classSymbol: FirRegularClassSymbol, qualifierIndex: Int): FirRegularClassSymbol? {
if (qualifierIndex == qualifier.size) {
return classSymbol
}
val qualifierName = qualifier[qualifierIndex].name
for (declarationSymbol in classSymbol.declarationSymbols) {
if (declarationSymbol is FirRegularClassSymbol) {
if (declarationSymbol.toLookupTag().name == qualifierName) {
return resolveLocalClassChain(declarationSymbol, qualifierIndex + 1)
}
}
}
return null
}
return resolveLocalClassChain(symbol, 1)
}
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
private fun FirQualifierResolver.resolveEnumEntrySymbol( private fun FirQualifierResolver.resolveEnumEntrySymbol(
qualifier: List<FirQualifierPart>, qualifier: List<FirQualifierPart>,
@@ -18,11 +18,11 @@ fun <E> foo(x: Any, y: Any) : Any {
} }
// bare type // bare type
if (y is <!UNRESOLVED_REFERENCE!>Outer.Inner<!>) { if (y is <!NO_TYPE_ARGUMENTS_ON_RHS!>Outer.Inner<!>) {
return y return y
} }
y as <!UNRESOLVED_REFERENCE!>Outer<*>.Inner<!> y as Outer<*>.Inner
return C() return C()
} }
@@ -0,0 +1,15 @@
// FIR_IDENTICAL
// KT-47135
fun test2() {
class LocalA {
inner class LocalB {
inner class LocalC {
}
}
}
fun LocalA.LocalB.blah() {
val c: LocalA.LocalB.LocalC = LocalC()
}
}
@@ -0,0 +1,3 @@
package
public fun test2(): kotlin.Unit
@@ -24095,6 +24095,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt");
} }
@Test
@TestMetadata("LocalClassReferenceChain.kt")
public void testLocalClassReferenceChain() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt");
}
@Test @Test
@TestMetadata("noThis.kt") @TestMetadata("noThis.kt")
public void testNoThis() throws Exception { public void testNoThis() throws Exception {