FIR: Properly support local functions in DEBUG_INFO_CALL
This commit is contained in:
+7
-1
@@ -2,7 +2,10 @@ interface B {
|
|||||||
operator fun invoke(x: Int): String
|
operator fun invoke(x: Int): String
|
||||||
}
|
}
|
||||||
class A {
|
class A {
|
||||||
fun foo(x: Int) {}
|
fun foo(x: Int) {
|
||||||
|
fun baz(x: Double) {}
|
||||||
|
<!DEBUG_INFO_CALL("fqName: A.foo.baz; typeCall: function")!>baz(1.0)<!>
|
||||||
|
}
|
||||||
|
|
||||||
val bar: B = TODO()
|
val bar: B = TODO()
|
||||||
}
|
}
|
||||||
@@ -10,8 +13,11 @@ class A {
|
|||||||
fun A.foo(x: String) {}
|
fun A.foo(x: String) {}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
fun A.foo(x: Double) {}
|
||||||
val a = A()
|
val a = A()
|
||||||
a.<!DEBUG_INFO_CALL("fqName: A.foo; typeCall: function")!>foo(1)<!>
|
a.<!DEBUG_INFO_CALL("fqName: A.foo; typeCall: function")!>foo(1)<!>
|
||||||
a.<!DEBUG_INFO_CALL("fqName: foo; typeCall: extension function")!>foo("")<!>
|
a.<!DEBUG_INFO_CALL("fqName: foo; typeCall: extension function")!>foo("")<!>
|
||||||
|
a.<!DEBUG_INFO_CALL("fqName: main.foo; typeCall: extension function")!>foo(1.0)<!>
|
||||||
|
|
||||||
a.<!DEBUG_INFO_CALL("fqName: B.invoke; typeCall: variable&invoke")!>bar(1)<!>
|
a.<!DEBUG_INFO_CALL("fqName: B.invoke; typeCall: variable&invoke")!>bar(1)<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ FILE: debugInfoCall.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| {
|
public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||||
|
local final fun baz(x: R|kotlin/Double|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
|
||||||
|
R|<local>/baz|(Double(1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
public final val bar: R|B| = R|kotlin/TODO|()
|
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 R|A|.foo(x: R|kotlin/String|): R|kotlin/Unit| {
|
||||||
}
|
}
|
||||||
public final fun main(): 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|()
|
lval a: R|A| = R|/A.A|()
|
||||||
R|<local>/a|.R|/A.foo|(Int(1))
|
R|<local>/a|.R|/A.foo|(Int(1))
|
||||||
R|<local>/a|.R|/foo|(String())
|
R|<local>/a|.R|/foo|(String())
|
||||||
|
R|<local>/a|.R|<local>/foo|(Double(1.0))
|
||||||
R|<local>/a|.R|/A.bar|.R|/B.invoke|(Int(1))
|
R|<local>/a|.R|/A.bar|.R|/B.invoke|(Int(1))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,17 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
// NB: with className == null we are at top level
|
// 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("<local>")
|
||||||
|
val PACKAGE_FQ_NAME_FOR_LOCAL = FqName.topLevel(LOCAL_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
var classId: ClassId? = null
|
var classId: ClassId? = null
|
||||||
get() {
|
get() {
|
||||||
if (field == null && className != null) {
|
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)
|
constructor(packageName: FqName, callableName: Name) : this(packageName, null, callableName)
|
||||||
|
|
||||||
@Deprecated("TODO: Better solution for local callables?")
|
@Deprecated("TODO: Better solution for local callables?")
|
||||||
constructor(callableName: Name) : this(FqName.topLevel(Name.special("<local>")), 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)
|
if (className == null) return packageName.child(callableName)
|
||||||
return classId!!.asSingleFqName().child(callableName)
|
return classId!!.asSingleFqName().child(callableName)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-2
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.fir.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
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.ConeSimpleDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||||
import org.jetbrains.kotlin.fir.references.FirReference
|
import org.jetbrains.kotlin.fir.references.FirReference
|
||||||
@@ -80,7 +80,18 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
|||||||
|
|
||||||
fun callableIdForName(name: Name, local: Boolean = false) =
|
fun callableIdForName(name: Name, local: Boolean = false) =
|
||||||
when {
|
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 == FqName.ROOT -> CallableId(context.packageFqName, name)
|
||||||
context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name)
|
context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name)
|
||||||
else -> CallableId(context.packageFqName, context.className, name)
|
else -> CallableId(context.packageFqName, context.className, name)
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
|||||||
|
|
||||||
private fun AbstractFirBasedSymbol<*>.fqNameUnsafe(): FqNameUnsafe? = when (this) {
|
private fun AbstractFirBasedSymbol<*>.fqNameUnsafe(): FqNameUnsafe? = when (this) {
|
||||||
is FirClassLikeSymbol<*> -> classId.asSingleFqName().toUnsafe()
|
is FirClassLikeSymbol<*> -> classId.asSingleFqName().toUnsafe()
|
||||||
is FirCallableSymbol<*> -> callableId.asFqName().toUnsafe()
|
is FirCallableSymbol<*> -> callableId.asFqNameForDebugInfo().toUnsafe()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user