@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.util.isFileClass
1111import org.jetbrains.kotlin.ir.util.packageFqName
1212import org.jetbrains.kotlin.ir.util.parentClassOrNull
1313import org.jetbrains.kotlin.name.FqName
14+ import java.io.BufferedWriter
1415import java.io.File
1516import java.util.ArrayList
1617import java.util.HashSet
@@ -25,6 +26,10 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
2526 val propertySignature = " ;property"
2627 val fieldSignature = " ;field"
2728
29+ val output = OdasaOutput (false , logger).also {
30+ it.setCurrentSourceFile(File (sourceFilePath))
31+ }
32+
2833 fun extractLater (d : IrDeclarationWithName , signature : String ): Boolean {
2934 if (d !is IrClass && ! isExternalFileClassMember(d)) {
3035 logger.errorElement(" External declaration is neither a class, nor a top-level declaration" , d)
@@ -37,76 +42,88 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
3742 }
3843 fun extractLater (c : IrClass ) = extractLater(c, " " )
3944
45+ fun noteClassSourceExtractedTo (c : IrClass , sourceFile : String ) {
46+ extractDecl(c, " " ) { trapFileBW, _, _, _ ->
47+ val tw = TrapWriter (logger.loggerBase, TrapLabelManager (), trapFileBW, diagnosticTrapWriter)
48+ tw.writeComment(" .class trap file stubbed as source is extracted to $sourceFile " )
49+ tw.writeComment(" Part of invocation $invocationTrapFile " )
50+ }
51+ }
52+
53+ fun extractDecl (irDecl : IrDeclaration , possiblyLongSignature : String , extractorFn : (BufferedWriter , String , String , OdasaOutput .TrapFileManager ) -> Unit ) {
54+ // In order to avoid excessively long signatures which can lead to trap file names longer than the filesystem
55+ // limit, we truncate and add a hash to preserve uniqueness if necessary.
56+ val signature = if (possiblyLongSignature.length > 100 ) {
57+ possiblyLongSignature.substring(0 , 92 ) + " #" + StringDigestor .digest(possiblyLongSignature).substring(0 , 8 )
58+ } else { possiblyLongSignature }
59+ output.getTrapLockerForDecl(irDecl, signature).useAC { locker ->
60+ locker.trapFileManager.useAC { manager ->
61+ val shortName = when (irDecl) {
62+ is IrDeclarationWithName -> irDecl.name.asString()
63+ else -> " (unknown name)"
64+ }
65+ if (manager == null ) {
66+ logger.info(" Skipping extracting external decl $shortName " )
67+ } else {
68+ val trapFile = manager.file
69+ val trapTmpFile = File .createTempFile(" ${trapFile.nameWithoutExtension} ." , " .${trapFile.extension} .tmp" , trapFile.parentFile)
70+
71+ val containingClass = getContainingClassOrSelf(irDecl)
72+ if (containingClass == null ) {
73+ logger.errorElement(" Unable to get containing class" , irDecl)
74+ return
75+ }
76+ val binaryPath = getIrClassBinaryPath(containingClass)
77+ try {
78+ GZIPOutputStream (trapTmpFile.outputStream()).bufferedWriter().use {
79+ extractorFn(it, binaryPath, signature, manager)
80+ }
81+
82+ if (! trapTmpFile.renameTo(trapFile)) {
83+ logger.error(" Failed to rename $trapTmpFile to $trapFile " )
84+ }
85+ } catch (e: Exception ) {
86+ manager.setHasError()
87+ logger.error(" Failed to extract '$shortName '. Partial TRAP file location is $trapTmpFile " , e)
88+ }
89+ }
90+ }
91+ }
92+ }
93+
4094 fun extractExternalClasses () {
41- val output = OdasaOutput (false , logger)
42- output.setCurrentSourceFile(File (sourceFilePath))
4395 do {
4496 val nextBatch = ArrayList (externalDeclWorkList)
4597 externalDeclWorkList.clear()
4698 nextBatch.forEach { workPair ->
4799 val (irDecl, possiblyLongSignature) = workPair
48- // In order to avoid excessively long signatures which can lead to trap file names longer than the filesystem
49- // limit, we truncate and add a hash to preserve uniqueness if necessary.
50- val signature = if (possiblyLongSignature.length > 100 ) {
51- possiblyLongSignature.substring(0 , 92 ) + " #" + StringDigestor .digest(possiblyLongSignature).substring(0 , 8 )
52- } else { possiblyLongSignature }
53- output.getTrapLockerForDecl(irDecl, signature).useAC { locker ->
54- locker.trapFileManager.useAC { manager ->
55- val shortName = when (irDecl) {
56- is IrDeclarationWithName -> irDecl.name.asString()
57- else -> " (unknown name)"
58- }
59- if (manager == null ) {
60- logger.info(" Skipping extracting external decl $shortName " )
61- } else {
62- val trapFile = manager.file
63- val trapTmpFile = File .createTempFile(" ${trapFile.nameWithoutExtension} ." , " .${trapFile.extension} .tmp" , trapFile.parentFile)
64-
65- val containingClass = getContainingClassOrSelf(irDecl)
66- if (containingClass == null ) {
67- logger.errorElement(" Unable to get containing class" , irDecl)
68- return
69- }
70- val binaryPath = getIrClassBinaryPath(containingClass)
71- try {
72- GZIPOutputStream (trapTmpFile.outputStream()).bufferedWriter().use { trapFileBW ->
73- // We want our comments to be the first thing in the file,
74- // so start off with a mere TrapWriter
75- val tw = TrapWriter (logger.loggerBase, TrapLabelManager (), trapFileBW, diagnosticTrapWriter)
76- tw.writeComment(" Generated by the CodeQL Kotlin extractor for external dependencies" )
77- tw.writeComment(" Part of invocation $invocationTrapFile " )
78- if (signature != possiblyLongSignature) {
79- tw.writeComment(" Function signature abbreviated; full signature is: $possiblyLongSignature " )
80- }
81- // Now elevate to a SourceFileTrapWriter, and populate the
82- // file information if needed:
83- val ftw = tw.makeFileTrapWriter(binaryPath, true )
84-
85- val fileExtractor = KotlinFileExtractor (logger, ftw, null , binaryPath, manager, this , primitiveTypeMapping, pluginContext, KotlinFileExtractor .DeclarationStack (), globalExtensionState)
100+ extractDecl(irDecl, possiblyLongSignature) { trapFileBW, binaryPath, signature, manager ->
101+ // We want our comments to be the first thing in the file,
102+ // so start off with a mere TrapWriter
103+ val tw = TrapWriter (logger.loggerBase, TrapLabelManager (), trapFileBW, diagnosticTrapWriter)
104+ tw.writeComment(" Generated by the CodeQL Kotlin extractor for external dependencies" )
105+ tw.writeComment(" Part of invocation $invocationTrapFile " )
106+ if (signature != possiblyLongSignature) {
107+ tw.writeComment(" Function signature abbreviated; full signature is: $possiblyLongSignature " )
108+ }
109+ // Now elevate to a SourceFileTrapWriter, and populate the
110+ // file information if needed:
111+ val ftw = tw.makeFileTrapWriter(binaryPath, true )
86112
87- if (irDecl is IrClass ) {
88- // Populate a location and compilation-unit package for the file. This is similar to
89- // the beginning of `KotlinFileExtractor.extractFileContents` but without an `IrFile`
90- // to start from.
91- val pkg = irDecl.packageFqName?.asString() ? : " "
92- val pkgId = fileExtractor.extractPackage(pkg)
93- ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
94- ftw.writeCupackage(ftw.fileId, pkgId)
113+ val fileExtractor = KotlinFileExtractor (logger, ftw, null , binaryPath, manager, this , primitiveTypeMapping, pluginContext, KotlinFileExtractor .DeclarationStack (), globalExtensionState)
95114
96- fileExtractor.extractClassSource(irDecl, extractDeclarations = ! irDecl.isFileClass, extractStaticInitializer = false , extractPrivateMembers = false , extractFunctionBodies = false )
97- } else {
98- fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false , extractFunctionBodies = false )
99- }
100- }
115+ if (irDecl is IrClass ) {
116+ // Populate a location and compilation-unit package for the file. This is similar to
117+ // the beginning of `KotlinFileExtractor.extractFileContents` but without an `IrFile`
118+ // to start from.
119+ val pkg = irDecl.packageFqName?.asString() ? : " "
120+ val pkgId = fileExtractor.extractPackage(pkg)
121+ ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
122+ ftw.writeCupackage(ftw.fileId, pkgId)
101123
102- if (! trapTmpFile.renameTo(trapFile)) {
103- logger.error(" Failed to rename $trapTmpFile to $trapFile " )
104- }
105- } catch (e: Exception ) {
106- manager.setHasError()
107- logger.error(" Failed to extract '$shortName '. Partial TRAP file location is $trapTmpFile " , e)
108- }
109- }
124+ fileExtractor.extractClassSource(irDecl, extractDeclarations = ! irDecl.isFileClass, extractStaticInitializer = false , extractPrivateMembers = false , extractFunctionBodies = false )
125+ } else {
126+ fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false , extractFunctionBodies = false )
110127 }
111128 }
112129 }
0 commit comments