From 65e444a39cc70a9cf404a7c29007c129b8bdf4b5 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 15 Apr 2020 18:32:43 +0300 Subject: [PATCH] FIR: Properly support local functions in DEBUG_INFO_CALL --- .../resolve/callResolution/debugInfoCall.kt | 8 +++++- .../resolve/callResolution/debugInfoCall.txt | 8 ++++++ .../kotlin/fir/symbols/CallableId.kt | 26 ++++++++++++++++--- .../kotlin/fir/builder/BaseFirBuilder.kt | 15 +++++++++-- .../kotlin/fir/AbstractFirDiagnosticTest.kt | 2 +- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt index e09b103f10c..5cd9dec1539 100644 --- a/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt @@ -2,7 +2,10 @@ interface B { operator fun invoke(x: Int): String } class A { - fun foo(x: Int) {} + fun foo(x: Int) { + fun baz(x: Double) {} + baz(1.0) + } val bar: B = TODO() } @@ -10,8 +13,11 @@ class A { fun A.foo(x: String) {} fun main() { + fun A.foo(x: Double) {} val a = A() a.foo(1) a.foo("") + a.foo(1.0) + a.bar(1) } diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.txt index 22199236745..4f2f16552b1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.txt +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.txt @@ -9,6 +9,10 @@ FILE: debugInfoCall.kt } public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| { + local final fun baz(x: R|kotlin/Double|): R|kotlin/Unit| { + } + + R|/baz|(Double(1.0)) } public final val bar: R|B| = R|kotlin/TODO|() @@ -18,8 +22,12 @@ FILE: debugInfoCall.kt public final fun R|A|.foo(x: R|kotlin/String|): R|kotlin/Unit| { } public final fun main(): R|kotlin/Unit| { + local final fun R|A|.foo(x: R|kotlin/Double|): R|kotlin/Unit| { + } + lval a: R|A| = R|/A.A|() R|/a|.R|/A.foo|(Int(1)) R|/a|.R|/foo|(String()) + R|/a|.R|/foo|(Double(1.0)) R|/a|.R|/A.bar|.R|/B.invoke|(Int(1)) } diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/CallableId.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/CallableId.kt index 44cdddb5d9f..f1426541597 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/CallableId.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/CallableId.kt @@ -10,7 +10,17 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name // NB: with className == null we are at top level -data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) { +data class CallableId( + val packageName: FqName, + val className: FqName?, + val callableName: Name, + val pathToLocal: FqName? = null +) { + private companion object { + val LOCAL_NAME = Name.special("") + val PACKAGE_FQ_NAME_FOR_LOCAL = FqName.topLevel(LOCAL_NAME) + } + var classId: ClassId? = null get() { if (field == null && className != null) { @@ -26,9 +36,19 @@ data class CallableId(val packageName: FqName, val className: FqName?, val calla constructor(packageName: FqName, callableName: Name) : this(packageName, null, callableName) @Deprecated("TODO: Better solution for local callables?") - constructor(callableName: Name) : this(FqName.topLevel(Name.special("")), null, callableName) + constructor( + callableName: Name, + pathToLocal: FqName? = null + ) : this( + PACKAGE_FQ_NAME_FOR_LOCAL, + className = null, + callableName, + pathToLocal, + ) + + fun asFqNameForDebugInfo(): FqName { + if (pathToLocal != null) return pathToLocal.child(callableName) - fun asFqName(): FqName { if (className == null) return packageName.child(callableName) return classId!!.asSingleFqName().child(callableName) } diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index 4db9d39c303..4bb73ec5765 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -13,8 +13,8 @@ import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.references.FirReference @@ -80,7 +80,18 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte fun callableIdForName(name: Name, local: Boolean = false) = when { - local -> CallableId(name) + local -> { + val pathFqName = + context.firFunctionTargets.fold( + if (context.className == FqName.ROOT) context.packageFqName else context.currentClassId.asSingleFqName() + ) { result, firFunctionTarget -> + if (firFunctionTarget.isLambda || firFunctionTarget.labelName == null) + result + else + result.child(Name.identifier(firFunctionTarget.labelName!!)) + } + CallableId(name, pathFqName) + } context.className == FqName.ROOT -> CallableId(context.packageFqName, name) context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name) else -> CallableId(context.packageFqName, context.className, name) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index 494e68c624f..b4555b38d07 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -215,7 +215,7 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { private fun AbstractFirBasedSymbol<*>.fqNameUnsafe(): FqNameUnsafe? = when (this) { is FirClassLikeSymbol<*> -> classId.asSingleFqName().toUnsafe() - is FirCallableSymbol<*> -> callableId.asFqName().toUnsafe() + is FirCallableSymbol<*> -> callableId.asFqNameForDebugInfo().toUnsafe() else -> null }