Skip to content

Commit 7f7cb2c

Browse files
committed
Kotlin: refactor declaration stack to handle file as declaration parent
1 parent 2597777 commit 7f7cb2c

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ open class KotlinFileExtractor(
8585
file.declarations.forEach { extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) }
8686
extractStaticInitializer(file, null)
8787
CommentExtractor(this, file, tw.fileId).extract()
88+
89+
if (!declarationStack.isEmpty()) {
90+
logger.errorElement("Declaration stack is not empty after processing the file", file)
91+
}
8892
}
8993
}
9094

@@ -306,7 +310,7 @@ open class KotlinFileExtractor(
306310
}
307311
}.firstOrNull { it != null } ?: false)
308312

309-
extractEnclosingClass(c, id, locId, if (useBoundOuterType) argsIncludingOuterClasses?.drop(c.typeParameters.size) else listOf())
313+
extractEnclosingClass(c.parent, id, c, locId, if (useBoundOuterType) argsIncludingOuterClasses?.drop(c.typeParameters.size) else listOf())
310314

311315
return id
312316
}
@@ -415,7 +419,7 @@ open class KotlinFileExtractor(
415419
val locId = tw.getLocation(c)
416420
tw.writeHasLocation(id, locId)
417421

418-
extractEnclosingClass(c, id, locId, listOf())
422+
extractEnclosingClass(c.parent, id, c, locId, listOf())
419423

420424
val javaClass = (c.source as? JavaSourceElement)?.javaElement as? JavaClass
421425

@@ -522,10 +526,15 @@ open class KotlinFileExtractor(
522526
}
523527
}
524528

525-
// If `parentClassTypeArguments` is null, the parent class is a raw type.
526-
private fun extractEnclosingClass(innerDeclaration: IrDeclaration, innerId: Label<out DbClassorinterface>, innerLocId: Label<DbLocation>, parentClassTypeArguments: List<IrTypeArgument>?) {
527-
with("enclosing class", innerDeclaration) {
528-
var parent: IrDeclarationParent? = innerDeclaration.parent
529+
private fun extractEnclosingClass(
530+
declarationParent: IrDeclarationParent, // The declaration parent if the element for which we are extracting the enclosing class
531+
innerId: Label<out DbClassorinterface>, // ID of the inner class
532+
innerClass: IrClass?, // The inner class, if available. It's not available if the enclosing class of a generated class is being extracted
533+
innerLocId: Label<DbLocation>, // Location of the inner class
534+
parentClassTypeArguments: List<IrTypeArgument>? // Type arguments of the parent class. If `parentClassTypeArguments` is null, the parent class is a raw type
535+
) {
536+
with("enclosing class", declarationParent) {
537+
var parent: IrDeclarationParent? = declarationParent
529538
while (parent != null) {
530539
if (parent is IrClass) {
531540
val parentId =
@@ -535,13 +544,13 @@ open class KotlinFileExtractor(
535544
useClassInstance(parent, parentClassTypeArguments).typeResult.id
536545
}
537546
tw.writeEnclInReftype(innerId, parentId)
538-
if (innerDeclaration is IrClass && innerDeclaration.isCompanion) {
547+
if (innerClass is IrClass && innerClass.isCompanion) {
539548
// If we are a companion then our parent has a
540549
// public static final ParentClass$CompanionObjectClass CompanionObjectName;
541550
// that we need to fabricate here
542-
val instance = useCompanionObjectClassInstance(innerDeclaration)
551+
val instance = useCompanionObjectClassInstance(innerClass)
543552
if (instance != null) {
544-
val type = useSimpleTypeClass(innerDeclaration, emptyList(), false)
553+
val type = useSimpleTypeClass(innerClass, emptyList(), false)
545554
tw.writeFields(instance.id, instance.name, type.javaResult.id, parentId, instance.id)
546555
tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id)
547556
tw.writeHasLocation(instance.id, innerLocId)
@@ -552,7 +561,7 @@ open class KotlinFileExtractor(
552561

553562
break
554563
} else if (parent is IrFile) {
555-
if (innerDeclaration is IrClass) {
564+
if (innerClass is IrClass) {
556565
// We don't have to extract file class containers for classes
557566
break
558567
}
@@ -2440,9 +2449,6 @@ open class KotlinFileExtractor(
24402449
}
24412450
}
24422451

2443-
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
2444-
private val declarationStack: Stack<IrDeclaration> = Stack()
2445-
24462452
abstract inner class StmtExprParent {
24472453
abstract fun stmt(e: IrExpression, callable: Label<out DbCallable>): StmtParent
24482454
abstract fun expr(e: IrExpression, callable: Label<out DbCallable>): ExprParent
@@ -3697,12 +3703,12 @@ open class KotlinFileExtractor(
36973703
constructorBlock = tw.getFreshIdLabel()
36983704
)
36993705

3700-
val currentDeclaration = declarationStack.peek()
3706+
val declarationParent = declarationStack.peekAsDeclarationParent()
37013707
val prefix = if (kPropertyClass.owner.name.asString().startsWith("KMutableProperty")) "Mutable" else ""
37023708
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.${prefix}PropertyReference${kPropertyType.arguments.size - 1}"))?.owner?.typeWith()
37033709
?: pluginContext.irBuiltIns.anyType
37043710

3705-
val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, currentDeclaration)
3711+
val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, propertyReferenceExpr, declarationParent)
37063712

37073713
val helper = PropertyReferenceHelper(propertyReferenceExpr, locId, ids)
37083714

@@ -3904,12 +3910,12 @@ open class KotlinFileExtractor(
39043910
if (fnInterfaceType == null) {
39053911
logger.warnElement("Cannot find functional interface type for function reference", functionReferenceExpr)
39063912
} else {
3907-
val currentDeclaration = declarationStack.peek()
3913+
val declarationParent = declarationStack.peekAsDeclarationParent()
39083914
// `FunctionReference` base class is required, because that's implementing `KFunction`.
39093915
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.FunctionReference"))?.owner?.typeWith()
39103916
?: pluginContext.irBuiltIns.anyType
39113917

3912-
val classId = extractGeneratedClass(ids, listOf(baseClass, fnInterfaceType), locId, currentDeclaration)
3918+
val classId = extractGeneratedClass(ids, listOf(baseClass, fnInterfaceType), locId, functionReferenceExpr, declarationParent)
39133919

39143920
helper.extractReceiverField()
39153921

@@ -4513,8 +4519,8 @@ open class KotlinFileExtractor(
45134519
val locId = tw.getLocation(e)
45144520
val helper = GeneratedClassHelper(locId, ids)
45154521

4516-
val currentDeclaration = declarationStack.peek()
4517-
val classId = extractGeneratedClass(ids, listOf(pluginContext.irBuiltIns.anyType, e.typeOperand), locId, currentDeclaration)
4522+
val declarationParent = declarationStack.peekAsDeclarationParent()
4523+
val classId = extractGeneratedClass(ids, listOf(pluginContext.irBuiltIns.anyType, e.typeOperand), locId, e, declarationParent)
45184524

45194525
// add field
45204526
val fieldId = tw.getFreshIdLabel<DbField>()
@@ -4656,7 +4662,8 @@ open class KotlinFileExtractor(
46564662
ids: GeneratedClassLabels,
46574663
superTypes: List<IrType>,
46584664
locId: Label<DbLocation>,
4659-
currentDeclaration: IrDeclaration
4665+
elementToReportOn: IrElement,
4666+
declarationParent: IrDeclarationParent
46604667
): Label<out DbClass> {
46614668
// Write class
46624669
val id = ids.type.javaResult.id.cast<DbClass>()
@@ -4679,7 +4686,7 @@ open class KotlinFileExtractor(
46794686
// Super call
46804687
val baseClass = superTypes.first().classOrNull
46814688
if (baseClass == null) {
4682-
logger.warnElement("Cannot find base class", currentDeclaration)
4689+
logger.warnElement("Cannot find base class", elementToReportOn)
46834690
} else {
46844691
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
46854692
if (baseConstructor == null) {
@@ -4699,7 +4706,7 @@ open class KotlinFileExtractor(
46994706
addVisibilityModifierToLocalOrAnonymousClass(id)
47004707
extractClassSupertypes(superTypes, listOf(), id, inReceiverContext = true)
47014708

4702-
extractEnclosingClass(currentDeclaration, id, locId, listOf())
4709+
extractEnclosingClass(declarationParent, id, null, locId, listOf())
47034710

47044711
return id
47054712
}
@@ -4711,7 +4718,7 @@ open class KotlinFileExtractor(
47114718
with("generated class", localFunction) {
47124719
val ids = getLocallyVisibleFunctionLabels(localFunction)
47134720

4714-
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction)
4721+
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction, localFunction.parent)
47154722

47164723
// Extract local function as a member
47174724
extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, null, listOf())
@@ -4720,6 +4727,30 @@ open class KotlinFileExtractor(
47204727
}
47214728
}
47224729

4730+
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
4731+
private val declarationStack = DeclarationStack()
4732+
4733+
private inner class DeclarationStack {
4734+
private val stack: Stack<IrDeclaration> = Stack()
4735+
4736+
fun push(item: IrDeclaration) = stack.push(item)
4737+
4738+
fun pop() = stack.pop()
4739+
4740+
fun isEmpty() = stack.isEmpty()
4741+
4742+
fun peek() = stack.peek()
4743+
4744+
fun peekAsDeclarationParent(): IrDeclarationParent {
4745+
val trapWriter = tw
4746+
if (isEmpty() && trapWriter is SourceFileTrapWriter) {
4747+
// If the current declaration is used as a parent, we might end up with an empty stack. In this case, the source file is the parent.
4748+
return trapWriter.irFile
4749+
}
4750+
4751+
return peek() as IrDeclarationParent
4752+
}
4753+
}
47234754

47244755
private inner class DeclarationStackAdjuster(declaration: IrDeclaration): Closeable {
47254756
init {

java/kotlin-extractor/src/main/kotlin/TrapWriter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class SourceFileTrapWriter (
319319
lm: TrapLabelManager,
320320
bw: BufferedWriter,
321321
diagnosticTrapWriter: TrapWriter?,
322-
irFile: IrFile,
322+
val irFile: IrFile,
323323
populateFileTables: Boolean) :
324324
FileTrapWriter(loggerBase, lm, bw, diagnosticTrapWriter, irFile.path, populateFileTables) {
325325

0 commit comments

Comments
 (0)