Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c5e8562

Browse files
smowtonigfoo
authored andcommitted
Rework conditional generic extraction to use global state
1 parent 2567424 commit c5e8562

5 files changed

Lines changed: 45 additions & 44 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import java.util.ArrayList
99
import java.util.HashSet
1010
import java.util.zip.GZIPOutputStream
1111

12-
class ExternalClassExtractor(val logger: FileLogger, val invocationTrapFile: String, val sourceFilePath: String, val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext) {
12+
class ExternalClassExtractor(val logger: FileLogger, val invocationTrapFile: String, val sourceFilePath: String, val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val genericSpecialisationsExtracted: MutableSet<String>) {
1313

1414
val externalClassesDone = HashSet<IrClass>()
1515
val externalClassWorkList = ArrayList<IrClass>()
@@ -43,7 +43,7 @@ class ExternalClassExtractor(val logger: FileLogger, val invocationTrapFile: Str
4343
val binaryPath = getIrClassBinaryPath(irClass)
4444
val ftw = tw.makeFileTrapWriter(binaryPath, true)
4545

46-
val fileExtractor = KotlinFileExtractor(logger, ftw, manager, this, primitiveTypeMapping, pluginContext)
46+
val fileExtractor = KotlinFileExtractor(logger, ftw, manager, this, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
4747
fileExtractor.extractClassSource(irClass)
4848
}
4949
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ class KotlinExtractorExtension(
4242
FileUtil.logger = logger
4343
val srcDir = File(System.getenv("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR").takeUnless { it.isNullOrEmpty() } ?: "kotlin-extractor/src")
4444
srcDir.mkdirs()
45+
val genericSpecialisationsExtracted = HashSet<String>()
4546
moduleFragment.files.mapIndexed { index: Int, file: IrFile ->
4647
val fileTrapWriter = tw.makeSourceFileTrapWriter(file, true)
4748
fileTrapWriter.writeCompilation_compiling_files(compilation, index, fileTrapWriter.fileId)
48-
doFile(invocationTrapFile, fileTrapWriter, checkTrapIdentical, logCounter, trapDir, srcDir, file, primitiveTypeMapping, pluginContext)
49+
doFile(invocationTrapFile, fileTrapWriter, checkTrapIdentical, logCounter, trapDir, srcDir, file, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
4950
}
5051
logger.printLimitedWarningCounts()
5152
// We don't want the compiler to continue and generate class
@@ -92,7 +93,8 @@ fun doFile(invocationTrapFile: String,
9293
srcDir: File,
9394
file: IrFile,
9495
primitiveTypeMapping: PrimitiveTypeMapping,
95-
pluginContext: IrPluginContext) {
96+
pluginContext: IrPluginContext,
97+
genericSpecialisationsExtracted: MutableSet<String>) {
9698
val filePath = file.path
9799
val logger = FileLogger(logCounter, fileTrapWriter)
98100
logger.info("Extracting file $filePath")
@@ -120,8 +122,8 @@ fun doFile(invocationTrapFile: String,
120122
// Now elevate to a SourceFileTrapWriter, and populate the
121123
// file information
122124
val sftw = tw.makeSourceFileTrapWriter(file, true)
123-
val externalClassExtractor = ExternalClassExtractor(logger, invocationTrapFile, file.path, primitiveTypeMapping, pluginContext)
124-
val fileExtractor = KotlinSourceFileExtractor(logger, sftw, file, externalClassExtractor, primitiveTypeMapping, pluginContext)
125+
val externalClassExtractor = ExternalClassExtractor(logger, invocationTrapFile, file.path, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
126+
val fileExtractor = KotlinSourceFileExtractor(logger, sftw, file, externalClassExtractor, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
125127
fileExtractor.extractFileContents(sftw.fileId)
126128
externalClassExtractor.extractExternalClasses()
127129
}

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.IrElement
1313
import org.jetbrains.kotlin.ir.IrStatement
1414
import org.jetbrains.kotlin.ir.declarations.*
1515
import org.jetbrains.kotlin.ir.expressions.*
16-
import org.jetbrains.kotlin.ir.interpreter.toIrConst
1716
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
1817
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
1918
import org.jetbrains.kotlin.ir.types.*
@@ -28,8 +27,9 @@ open class KotlinFileExtractor(
2827
dependencyCollector: OdasaOutput.TrapFileManager?,
2928
externalClassExtractor: ExternalClassExtractor,
3029
primitiveTypeMapping: PrimitiveTypeMapping,
31-
pluginContext: IrPluginContext
32-
): KotlinUsesExtractor(logger, tw, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext) {
30+
pluginContext: IrPluginContext,
31+
genericSpecialisationsExtracted: MutableSet<String>
32+
): KotlinUsesExtractor(logger, tw, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted) {
3333

3434
fun extractDeclaration(declaration: IrDeclaration, parentId: Label<out DbReftype>) {
3535
when (declaration) {
@@ -92,15 +92,15 @@ open class KotlinFileExtractor(
9292
return id
9393
}
9494

95-
fun extractClassInstance(c: IrClass, typeArgs: List<IrTypeArgument>, extractFunctionPrototypes: Boolean): Label<out DbClassorinterface> {
95+
fun extractClassInstance(c: IrClass, typeArgs: List<IrTypeArgument>): Label<out DbClassorinterface> {
9696
if (typeArgs.isEmpty()) {
9797
logger.warn(Severity.ErrorSevere, "Instance without type arguments: " + c.name.asString())
9898
}
9999

100-
val results = addClassLabel(c, typeArgs)
101-
val id = results.id
100+
val classLabelResults = getClassLabel(c, typeArgs)
101+
val id = tw.getLabelFor<DbClassorinterface>(classLabelResults.classLabel)
102102
val pkg = c.packageFqName?.asString() ?: ""
103-
val cls = results.shortName
103+
val cls = classLabelResults.shortName
104104
val pkgId = extractPackage(pkg)
105105
if(c.kind == ClassKind.INTERFACE) {
106106
@Suppress("UNCHECKED_CAST")
@@ -133,19 +133,19 @@ open class KotlinFileExtractor(
133133
val locId = tw.getLocation(c)
134134
tw.writeHasLocation(id, locId)
135135

136-
if (extractFunctionPrototypes) {
137-
val typeParamSubstitution = c.typeParameters.map({ it.symbol }).zip(typeArgs).toMap()
136+
return id
137+
}
138138

139-
c.declarations.map {
140-
when(it) {
141-
is IrFunction -> extractFunction(it, id, false, typeParamSubstitution)
142-
is IrProperty -> extractProperty(it, id, false, typeParamSubstitution)
143-
else -> {}
144-
}
139+
fun extractMemberPrototypes(c: IrClass, typeArgs: List<IrTypeArgument>, id: Label<out DbClassorinterface>) {
140+
val typeParamSubstitution = c.typeParameters.map({ it.symbol }).zip(typeArgs).toMap()
141+
142+
c.declarations.map {
143+
when(it) {
144+
is IrFunction -> extractFunction(it, id, false, typeParamSubstitution)
145+
is IrProperty -> extractProperty(it, id, false, typeParamSubstitution)
146+
else -> {}
145147
}
146148
}
147-
148-
return id
149149
}
150150

151151
private fun extracLocalTypeDeclStmt(c: IrClass, callable: Label<out DbCallable>, parent: Label<out DbStmtparent>, idx: Int) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ class KotlinSourceFileExtractor(
1717
val file: IrFile,
1818
externalClassExtractor: ExternalClassExtractor,
1919
primitiveTypeMapping: PrimitiveTypeMapping,
20-
pluginContext: IrPluginContext
20+
pluginContext: IrPluginContext,
21+
genericSpecialisationsExtracted: MutableSet<String>
2122
) :
22-
KotlinFileExtractor(logger, tw, null, externalClassExtractor, primitiveTypeMapping, pluginContext) {
23+
KotlinFileExtractor(logger, tw, null, externalClassExtractor, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted) {
2324

2425
val fileClass by lazy {
2526
extractFileClass(file)

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

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ open class KotlinUsesExtractor(
2323
val dependencyCollector: OdasaOutput.TrapFileManager?,
2424
val externalClassExtractor: ExternalClassExtractor,
2525
val primitiveTypeMapping: PrimitiveTypeMapping,
26-
val pluginContext: IrPluginContext
26+
val pluginContext: IrPluginContext,
27+
val genericSpecialisationsExtracted: MutableSet<String>
2728
) {
2829
fun usePackage(pkg: String): Label<out DbPackage> {
2930
return extractPackage(pkg)
@@ -77,7 +78,7 @@ open class KotlinUsesExtractor(
7778
if (isExternalDeclaration(cls) || clsFile == null) {
7879
val newTrapWriter = tw.makeFileTrapWriter(getIrClassBinaryPath(cls), false)
7980
val newLogger = FileLogger(logger.logCounter, newTrapWriter)
80-
return KotlinFileExtractor(newLogger, newTrapWriter, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext)
81+
return KotlinFileExtractor(newLogger, newTrapWriter, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
8182
}
8283

8384
if (this is KotlinSourceFileExtractor && this.file == clsFile) {
@@ -86,16 +87,9 @@ open class KotlinUsesExtractor(
8687

8788
val newTrapWriter = tw.makeSourceFileTrapWriter(clsFile, false)
8889
val newLogger = FileLogger(logger.logCounter, newTrapWriter)
89-
return KotlinSourceFileExtractor(newLogger, newTrapWriter, clsFile, externalClassExtractor, primitiveTypeMapping, pluginContext)
90+
return KotlinSourceFileExtractor(newLogger, newTrapWriter, clsFile, externalClassExtractor, primitiveTypeMapping, pluginContext, genericSpecialisationsExtracted)
9091
}
9192

92-
private fun anyDeclarationExtracted(c: IrClass, id: Label<out DbClassorinterface>) =
93-
c.declarations.any {
94-
it is IrFunction &&
95-
tw.getExistingLabelFor<DbCallable>(getFunctionLabel(
96-
id, it.name.asString(), it.valueParameters, it.returnType, it.extensionReceiverParameter)) != null
97-
}
98-
9993
fun useClassInstance(c: IrClass, typeArgs: List<IrTypeArgument>, inReceiverContext: Boolean = false): UseClassInstanceResult {
10094
if (c.isAnonymousObject) {
10195
logger.warn(Severity.ErrorSevere, "Unexpected access to anonymous class instance")
@@ -150,22 +144,26 @@ open class KotlinUsesExtractor(
150144
fun addClassLabel(c: IrClass, typeArgs: List<IrTypeArgument>, inReceiverContext: Boolean = false): TypeResult<DbClassorinterface> {
151145
val classLabelResult = getClassLabel(c, typeArgs)
152146

153-
var shouldExtractClass = false
147+
var instanceSeenBefore = true
154148

155149
val classLabel : Label<out DbClassorinterface> = tw.getLabelFor(classLabelResult.classLabel, {
156-
// If this is a generic type instantiation then it has no
157-
// source entity, so we need to extract it here
158-
shouldExtractClass = true
150+
instanceSeenBefore = false
159151

160152
extractClassLaterIfExternal(c)
161153
})
162154

163155
if (typeArgs.isNotEmpty()) {
164-
// Extract again if we've already extracted the class itself but not its declared functions:
165-
// This might happen e.g. if we see it for the first time in the context of a parameter type (which doesn't
166-
// require method prototype extraction), then later as a function receiver (which does).
167-
if (shouldExtractClass || (inReceiverContext && !anyDeclarationExtracted(c, classLabel)))
168-
this.withSourceFileOfClass(c).extractClassInstance(c, typeArgs, inReceiverContext)
156+
// If this is a generic type instantiation then it has no
157+
// source entity, so we need to extract it here
158+
val extractorWithCSource by lazy { this.withSourceFileOfClass(c) }
159+
160+
if (!instanceSeenBefore) {
161+
extractorWithCSource.extractClassInstance(c, typeArgs)
162+
}
163+
164+
if (inReceiverContext && genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
165+
extractorWithCSource.extractMemberPrototypes(c, typeArgs, classLabel)
166+
}
169167
}
170168

171169
return TypeResult(

0 commit comments

Comments
 (0)