Tidy and use version 0 for classes extracted from source

This commit is contained in:
Chris Smowton
2022-12-01 10:01:59 +00:00
parent e34d72aee9
commit 748637c2d8
2 changed files with 48 additions and 46 deletions

View File

@@ -422,7 +422,7 @@ public class OdasaOutput {
* previously set by a call to {@link OdasaOutput#setCurrentSourceFile(File)}.
*/
public TrapLocker getTrapLockerForCurrentSourceFile() {
return new TrapLocker((IrClass)null, null);
return new TrapLocker((IrClass)null, null, true);
}
/**
@@ -460,8 +460,8 @@ public class OdasaOutput {
*
* @return a {@link TrapLocker} for the trap file corresponding to the given class symbol.
*/
public TrapLocker getTrapLockerForDecl(IrDeclaration sym, String signature) {
return new TrapLocker(sym, signature);
public TrapLocker getTrapLockerForDecl(IrDeclaration sym, String signature, boolean fromSource) {
return new TrapLocker(sym, signature, fromSource);
}
public class TrapLocker implements AutoCloseable {
@@ -472,7 +472,7 @@ public class OdasaOutput {
private File trapFileBase = null;
private TrapClassVersion trapFileVersion = null;
private final String signature;
private TrapLocker(IrDeclaration decl, String signature) {
private TrapLocker(IrDeclaration decl, String signature, boolean fromSource) {
this.sym = decl;
this.signature = signature;
if (sym==null) {
@@ -485,7 +485,10 @@ public class OdasaOutput {
} else {
// We encode the metadata into the filename, so that the
// TRAP filenames for different metadatas don't overlap.
trapFileVersion = TrapClassVersion.fromSymbol(sym, log);
if (fromSource)
trapFileVersion = new TrapClassVersion(0, 0, 0, "kotlin");
else
trapFileVersion = TrapClassVersion.fromSymbol(sym, log);
String baseName = normalTrapFile.getName().replace(".trap.gz", "");
// If a class has lots of inner classes, then we get lots of files
// in a single directory. This makes our directory listings later slow.

View File

@@ -43,40 +43,32 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
fun extractLater(c: IrClass) = extractLater(c, "")
fun noteClassSourceExtractedTo(c: IrClass, sourceFile: String) {
extractDecl(c, "") { trapFileBW, _, _, _ ->
val tw = TrapWriter(logger.loggerBase, TrapLabelManager(), trapFileBW, diagnosticTrapWriter)
tw.writeComment(".class trap file stubbed as source is extracted to $sourceFile")
tw.writeComment("Part of invocation $invocationTrapFile")
extractDecl(c, "", true) { trapFileBW, _, _ ->
trapFileBW.write("// .class trap file stubbed because this class was extracted from source in $sourceFile\n")
trapFileBW.write("// Part of invocation $invocationTrapFile\n")
}
}
fun extractDecl(irDecl: IrDeclaration, possiblyLongSignature: String, extractorFn: (BufferedWriter, String, String, OdasaOutput.TrapFileManager) -> Unit) {
private fun extractDecl(irDecl: IrDeclaration, possiblyLongSignature: String, fromSource: Boolean, extractorFn: (BufferedWriter, String, OdasaOutput.TrapFileManager) -> Unit) {
// In order to avoid excessively long signatures which can lead to trap file names longer than the filesystem
// limit, we truncate and add a hash to preserve uniqueness if necessary.
val signature = if (possiblyLongSignature.length > 100) {
possiblyLongSignature.substring(0, 92) + "#" + StringDigestor.digest(possiblyLongSignature).substring(0, 8)
} else { possiblyLongSignature }
output.getTrapLockerForDecl(irDecl, signature).useAC { locker ->
output.getTrapLockerForDecl(irDecl, signature, fromSource).useAC { locker ->
locker.trapFileManager.useAC { manager ->
val shortName = when(irDecl) {
is IrDeclarationWithName -> irDecl.name.asString()
else -> "(unknown name)"
}
if(manager == null) {
if (manager == null) {
logger.info("Skipping extracting external decl $shortName")
} else {
val trapFile = manager.file
val trapTmpFile = File.createTempFile("${trapFile.nameWithoutExtension}.", ".${trapFile.extension}.tmp", trapFile.parentFile)
val containingClass = getContainingClassOrSelf(irDecl)
if (containingClass == null) {
logger.errorElement("Unable to get containing class", irDecl)
return
}
val binaryPath = getIrClassBinaryPath(containingClass)
try {
GZIPOutputStream(trapTmpFile.outputStream()).bufferedWriter().use {
extractorFn(it, binaryPath, signature, manager)
extractorFn(it, signature, manager)
}
if (!trapTmpFile.renameTo(trapFile)) {
@@ -97,33 +89,40 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
externalDeclWorkList.clear()
nextBatch.forEach { workPair ->
val (irDecl, possiblyLongSignature) = workPair
extractDecl(irDecl, possiblyLongSignature) { trapFileBW, binaryPath, signature, manager ->
// We want our comments to be the first thing in the file,
// so start off with a mere TrapWriter
val tw = TrapWriter(logger.loggerBase, TrapLabelManager(), trapFileBW, diagnosticTrapWriter)
tw.writeComment("Generated by the CodeQL Kotlin extractor for external dependencies")
tw.writeComment("Part of invocation $invocationTrapFile")
if (signature != possiblyLongSignature) {
tw.writeComment("Function signature abbreviated; full signature is: $possiblyLongSignature")
}
// Now elevate to a SourceFileTrapWriter, and populate the
// file information if needed:
val ftw = tw.makeFileTrapWriter(binaryPath, true)
val fileExtractor = KotlinFileExtractor(logger, ftw, null, binaryPath, manager, this, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState)
if (irDecl is IrClass) {
// Populate a location and compilation-unit package for the file. This is similar to
// the beginning of `KotlinFileExtractor.extractFileContents` but without an `IrFile`
// to start from.
val pkg = irDecl.packageFqName?.asString() ?: ""
val pkgId = fileExtractor.extractPackage(pkg)
ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
ftw.writeCupackage(ftw.fileId, pkgId)
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
extractDecl(irDecl, possiblyLongSignature, false) { trapFileBW, signature, manager ->
val containingClass = getContainingClassOrSelf(irDecl)
if (containingClass == null) {
logger.errorElement("Unable to get containing class", irDecl)
} else {
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
val binaryPath = getIrClassBinaryPath(containingClass)
// We want our comments to be the first thing in the file,
// so start off with a mere TrapWriter
val tw = TrapWriter(logger.loggerBase, TrapLabelManager(), trapFileBW, diagnosticTrapWriter)
tw.writeComment("Generated by the CodeQL Kotlin extractor for external dependencies")
tw.writeComment("Part of invocation $invocationTrapFile")
if (signature != possiblyLongSignature) {
tw.writeComment("Function signature abbreviated; full signature is: $possiblyLongSignature")
}
// Now elevate to a SourceFileTrapWriter, and populate the
// file information if needed:
val ftw = tw.makeFileTrapWriter(binaryPath, true)
val fileExtractor = KotlinFileExtractor(logger, ftw, null, binaryPath, manager, this, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState)
if (irDecl is IrClass) {
// Populate a location and compilation-unit package for the file. This is similar to
// the beginning of `KotlinFileExtractor.extractFileContents` but without an `IrFile`
// to start from.
val pkg = irDecl.packageFqName?.asString() ?: ""
val pkgId = fileExtractor.extractPackage(pkg)
ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
ftw.writeCupackage(ftw.fileId, pkgId)
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
} else {
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
}
}
}
}