@@ -123,10 +123,39 @@ open class KotlinFileExtractor(
123123 return id
124124 }
125125
126+ private val anonymousTypeMapping: MutableMap <IrClass , TypeResults > = mutableMapOf ()
127+
128+ fun useAnonymousClass (c : IrClass ): TypeResults {
129+ var res = anonymousTypeMapping[c]
130+ if (res == null ) {
131+ val javaResult = TypeResult (tw.getFreshIdLabel<DbClass >(), " " , " " )
132+ val kotlinResult = TypeResult (tw.getFreshIdLabel<DbKt_notnull_type >(), " " , " " )
133+ tw.writeKt_notnull_types(kotlinResult.id, javaResult.id)
134+ res = TypeResults (javaResult, kotlinResult)
135+ anonymousTypeMapping[c] = res
136+ }
137+
138+ return res
139+ }
140+
141+ private fun extractAnonymousClassStmt (c : IrClass , callable : Label <out DbCallable >, parent : Label <out DbStmtparent >, idx : Int ) {
142+ @Suppress(" UNCHECKED_CAST" )
143+ val id = extractClassSource(c) as Label <out DbClass >
144+ extractAnonymousClassStmt(id, c, callable, parent, idx)
145+ }
146+
147+ private fun extractAnonymousClassStmt (id : Label <out DbClass >, locElement : IrElement , callable : Label <out DbCallable >, parent : Label <out DbStmtparent >, idx : Int ) {
148+ val stmtId = tw.getFreshIdLabel<DbAnonymousclassdeclstmt >()
149+ tw.writeStmts_anonymousclassdeclstmt(stmtId, parent, idx, callable)
150+ tw.writeKtAnonymousClassDeclarationStmts(stmtId, id)
151+ val locId = tw.getLocation(locElement)
152+ tw.writeHasLocation(stmtId, locId)
153+ }
154+
126155 fun extractClassSource (c : IrClass ): Label <out DbClassorinterface > {
127156 val id = if (c.isAnonymousObject) {
128157 @Suppress(" UNCHECKED_CAST" )
129- withSourceFile(c.fileOrNull !! ). useAnonymousClass(c).javaResult.id as Label <out DbClass >
158+ useAnonymousClass(c).javaResult.id as Label <out DbClass >
130159 } else {
131160 useClassSource(c)
132161 }
@@ -156,7 +185,7 @@ open class KotlinFileExtractor(
156185 val parentId =
157186 if (parent.isAnonymousObject) {
158187 @Suppress(" UNCHECKED_CAST" )
159- withSourceFile(c.fileOrNull !! ). useAnonymousClass(c).javaResult.id as Label <out DbClass >
188+ useAnonymousClass(c).javaResult.id as Label <out DbClass >
160189 } else {
161190 useClassInstance(parent, listOf ()).typeResult.id
162191 }
@@ -323,7 +352,7 @@ open class KotlinFileExtractor(
323352
324353 val id =
325354 if (f.isLocalFunction())
326- withSourceFile(f.fileOrNull !! ). getLocalFunctionLabels(f).function
355+ getLocalFunctionLabels(f).function
327356 else
328357 useFunction<DbCallable >(f)
329358
@@ -507,16 +536,15 @@ open class KotlinFileExtractor(
507536 }
508537 is IrClass -> {
509538 if (s.isAnonymousObject) {
510- withSourceFile(s.fileOrNull !! ). extractAnonymousClassStmt(s, callable, parent, idx)
539+ extractAnonymousClassStmt(s, callable, parent, idx)
511540 } else {
512541 logger.warnElement(Severity .ErrorSevere , " Found non anonymous IrClass as IrStatement: " + s.javaClass, s)
513542 }
514543 }
515544 is IrFunction -> {
516545 if (s.isLocalFunction()) {
517- val extractor = withSourceFile(s.fileOrNull!! )
518- val classId = extractor.extractGeneratedClass(s, listOf (pluginContext.irBuiltIns.anyType))
519- extractor.extractAnonymousClassStmt(classId, s, callable, parent, idx)
546+ val classId = extractGeneratedClass(s, listOf (pluginContext.irBuiltIns.anyType))
547+ extractAnonymousClassStmt(classId, s, callable, parent, idx)
520548 } else {
521549 logger.warnElement(Severity .ErrorSevere , " Expected to find local function" , s)
522550 }
@@ -684,7 +712,7 @@ open class KotlinFileExtractor(
684712 }
685713
686714 if (callTarget.isLocalFunction()) {
687- val ids = withSourceFile(callTarget.fileOrNull !! ). getLocalFunctionLabels(callTarget)
715+ val ids = getLocalFunctionLabels(callTarget)
688716
689717 val methodId = ids.function
690718 tw.writeCallableBinding(id, methodId)
@@ -1063,7 +1091,7 @@ open class KotlinFileExtractor(
10631091
10641092 val c = (e.type as IrSimpleType ).classifier.owner as IrClass
10651093
1066- type = withSourceFile(c.fileOrNull !! ). useAnonymousClass(c)
1094+ type = useAnonymousClass(c)
10671095
10681096 @Suppress(" UNCHECKED_CAST" )
10691097 tw.writeIsAnonymClass(type.javaResult.id as Label <DbClass >, id)
@@ -1737,4 +1765,71 @@ open class KotlinFileExtractor(
17371765
17381766 private val IrType .isAnonymous: Boolean
17391767 get() = ((this as ? IrSimpleType )?.classifier?.owner as ? IrClass )?.isAnonymousObject ? : false
1768+
1769+
1770+ private val generatedLocalFunctionTypeMapping: MutableMap <IrFunction , LocalFunctionLabels > = mutableMapOf ()
1771+
1772+ data class LocalFunctionLabels (val type : TypeResults , val constructor : Label <DbConstructor >, val function : Label <DbMethod >)
1773+
1774+ fun getLocalFunctionLabels (f : IrFunction ): LocalFunctionLabels {
1775+ if (! f.isLocalFunction()){
1776+ logger.warnElement(Severity .ErrorSevere , " Extracting a non-local function as a local one" , f)
1777+ }
1778+
1779+ var res = generatedLocalFunctionTypeMapping[f]
1780+ if (res == null ) {
1781+ val javaResult = TypeResult (tw.getFreshIdLabel<DbClass >(), " " , " " )
1782+ val kotlinResult = TypeResult (tw.getFreshIdLabel<DbKt_notnull_type >(), " " , " " )
1783+ tw.writeKt_notnull_types(kotlinResult.id, javaResult.id)
1784+ res = LocalFunctionLabels (
1785+ TypeResults (javaResult, kotlinResult),
1786+ tw.getFreshIdLabel(),
1787+ tw.getFreshIdLabel())
1788+ generatedLocalFunctionTypeMapping[f] = res
1789+ }
1790+
1791+ return res
1792+ }
1793+
1794+ fun extractGeneratedClass (localFunction : IrFunction , superTypes : List <IrType >) : Label <out DbClass > {
1795+ val ids = getLocalFunctionLabels(localFunction)
1796+
1797+ // Write class
1798+ @Suppress(" UNCHECKED_CAST" )
1799+ val id = ids.type.javaResult.id as Label <out DbClass >
1800+ val pkgId = extractPackage(" " )
1801+ tw.writeClasses(id, " " , pkgId, id)
1802+ val locId = tw.getLocation(localFunction)
1803+ tw.writeHasLocation(id, locId)
1804+
1805+ // Extract local function as a member
1806+ extractFunction(localFunction, id)
1807+
1808+ // Extract constructor
1809+ tw.writeConstrs(ids.constructor , " " , " " , ids.type.javaResult.id, ids.type.kotlinResult.id, id, ids.constructor )
1810+ tw.writeHasLocation(ids.constructor , locId)
1811+
1812+ // Constructor body
1813+ val constructorBlockId = tw.getFreshIdLabel<DbBlock >()
1814+ tw.writeStmts_block(constructorBlockId, ids.constructor , 0 , ids.constructor )
1815+ tw.writeHasLocation(constructorBlockId, locId)
1816+
1817+ // Super call
1818+ val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt >()
1819+ tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0 , ids.function)
1820+
1821+ val baseConstructor = superTypes.first().classOrNull!! .owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol }
1822+ val baseConstructorId = useFunction<DbConstructor >(baseConstructor as IrFunction )
1823+
1824+ tw.writeHasLocation(superCallId, locId)
1825+ @Suppress(" UNCHECKED_CAST" )
1826+ tw.writeCallableBinding(superCallId as Label <DbCaller >, baseConstructorId)
1827+
1828+ // TODO: We might need to add an `<obinit>` function, and a call to it to match other classes
1829+
1830+ addModifiers(id, " public" , " static" , " final" )
1831+ extractClassSupertypes(superTypes, listOf (), id)
1832+
1833+ return id
1834+ }
17401835}
0 commit comments