@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.util.isFileClass
11
11
import org.jetbrains.kotlin.ir.util.packageFqName
12
12
import org.jetbrains.kotlin.ir.util.parentClassOrNull
13
13
import org.jetbrains.kotlin.name.FqName
14
+ import java.io.BufferedWriter
14
15
import java.io.File
15
16
import java.util.ArrayList
16
17
import java.util.HashSet
@@ -25,6 +26,10 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
25
26
val propertySignature = " ;property"
26
27
val fieldSignature = " ;field"
27
28
29
+ val output = OdasaOutput (false , logger).also {
30
+ it.setCurrentSourceFile(File (sourceFilePath))
31
+ }
32
+
28
33
fun extractLater (d : IrDeclarationWithName , signature : String ): Boolean {
29
34
if (d !is IrClass && ! isExternalFileClassMember(d)) {
30
35
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
37
42
}
38
43
fun extractLater (c : IrClass ) = extractLater(c, " " )
39
44
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
+
40
94
fun extractExternalClasses () {
41
- val output = OdasaOutput (false , logger)
42
- output.setCurrentSourceFile(File (sourceFilePath))
43
95
do {
44
96
val nextBatch = ArrayList (externalDeclWorkList)
45
97
externalDeclWorkList.clear()
46
98
nextBatch.forEach { workPair ->
47
99
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 )
86
112
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)
95
114
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)
101
123
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 )
110
127
}
111
128
}
112
129
}
0 commit comments