From 1fc2a61f9590a0b94723d79a87e817b7867d8aff Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 15:30:11 +0000 Subject: [PATCH 01/11] KE2: basic external class extraction --- .../semmle/extractor/java/OdasaOutput.java | 59 +++++---- .../src/main/kotlin/ExternalDeclExtractor.kt | 63 +++++---- .../src/main/kotlin/KotlinExtractor.kt | 57 ++++---- .../src/main/kotlin/KotlinFileExtractor.kt | 10 +- .../src/main/kotlin/KotlinUsesExtractor.kt | 70 +--------- .../src/main/kotlin/TrapWriter.kt | 41 +++--- .../src/main/kotlin/entities/Class.kt | 124 +++++++++++------- .../src/main/kotlin/entities/Expression.kt | 2 + .../src/main/kotlin/entities/Function.kt | 16 ++- .../src/main/kotlin/entities/Types.kt | 63 ++++++++- .../src/main/kotlin/utils/AutoCloseableUse.kt | 3 - .../src/main/kotlin/utils/ClassNames.kt | 80 ++++++----- .../src/main/kotlin/utils/Logger.kt | 2 +- 13 files changed, 324 insertions(+), 266 deletions(-) diff --git a/java/kotlin-extractor2/src/main/java/com/semmle/extractor/java/OdasaOutput.java b/java/kotlin-extractor2/src/main/java/com/semmle/extractor/java/OdasaOutput.java index a731bdddf59..99f882f17ef 100644 --- a/java/kotlin-extractor2/src/main/java/com/semmle/extractor/java/OdasaOutput.java +++ b/java/kotlin-extractor2/src/main/java/com/semmle/extractor/java/OdasaOutput.java @@ -23,13 +23,11 @@ import com.github.codeql.Logger; //import static com.github.codeql.ClassNamesKt.getIrElementBinaryName; //import static com.github.codeql.ClassNamesKt.getIrClassVirtualFile; -import org.jetbrains.kotlin.ir.IrElement; -import org.jetbrains.kotlin.ir.declarations.IrClass; +import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol; +import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.kotlin.ir.declarations.IrDeclaration; -import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName; import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.Opcodes; @@ -51,6 +49,8 @@ import com.semmle.util.trap.pathtransformers.PathTransformer; import com.github.codeql.Compression; +import static com.github.codeql.ClassNamesKt.getSymbolBinaryName; + public class OdasaOutput { private final File trapFolder; private final File sourceArchiveFolder; @@ -136,7 +136,7 @@ public class OdasaOutput { currentSpecFileEntry.getTrapFolder(), PathTransformer.std().fileAsDatabaseString(file) + ".set"); } - public void addDependency(IrDeclaration sym, String signature) { + public void addDependency(KaSymbol sym, String signature) { String path = trapFilePathForDecl(sym, signature); trapDependenciesForSource.addDependency(path); } @@ -203,29 +203,28 @@ public class OdasaOutput { PathTransformer.std().fileAsDatabaseString(file) + ".trap" + compression.getExtension()); } - private File getTrapFileForDecl(IrElement sym, String signature) { + private File getTrapFileForDecl(KaSymbol sym, String signature) { if (currentSpecFileEntry == null) return null; return trapFileForDecl(sym, signature); } - private File trapFileForDecl(IrElement sym, String signature) { + private File trapFileForDecl(KaSymbol sym, String signature) { return FileUtil.fileRelativeTo(currentSpecFileEntry.getTrapFolder(), trapFilePathForDecl(sym, signature)); } - private String trapFilePathForDecl(IrElement sym, String signature) { - // String binaryName = getIrElementBinaryName(sym); + private String trapFilePathForDecl(KaSymbol sym, String signature) { + String binaryName = getSymbolBinaryName(sym); // TODO: Reinstate this? // if (getTrackClassOrigins()) // classId += "-" + StringDigestor.digest(sym.getSourceFileId()); - // String result = CLASSES_DIR + "/" + - // binaryName.replace('.', '/') + - // signature + - // ".members" + - // ".trap" + compression.getExtension(); - // return result; - return null; + String result = CLASSES_DIR + "/" + + binaryName.replace('.', '/') + + signature + + ".members" + + ".trap" + compression.getExtension(); + return result; } /* @@ -248,7 +247,7 @@ public class OdasaOutput { * signature. */ private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, TrapClassVersion trapFileVersion, - IrElement sym, String signature) { + KaSymbol sym, String signature) { // If the TRAP file already exists then we // don't need to write it. if (trap.exists()) { @@ -288,7 +287,7 @@ public class OdasaOutput { return trapWriter(trap, sym, signature); } - private TrapFileManager trapWriter(File trapFile, IrElement sym, String signature) { + private TrapFileManager trapWriter(File trapFile, KaSymbol sym, String signature) { if (!trapFile.getName().endsWith(".trap" + compression.getExtension())) throw new CatastrophicError("OdasaOutput only supports writing to compressed trap files"); String relative = FileUtil.relativePath(trapFile, currentSpecFileEntry.getTrapFolder()); @@ -297,7 +296,7 @@ public class OdasaOutput { return concurrentWriter(trapFile, relative, log, sym, signature); } - private TrapFileManager concurrentWriter(File trapFile, String relative, Logger log, IrElement sym, + private TrapFileManager concurrentWriter(File trapFile, String relative, Logger log, KaSymbol sym, String signature) { if (trapFile.exists()) return null; @@ -308,11 +307,11 @@ public class OdasaOutput { private TrapDependencies trapDependenciesForClass; private File trapFile; - private IrElement sym; + private KaSymbol sym; private String signature; private boolean hasError = false; - private TrapFileManager(File trapFile, String relative, boolean concurrentCreation, Logger log, IrElement sym, + private TrapFileManager(File trapFile, String relative, boolean concurrentCreation, Logger log, KaSymbol sym, String signature) { trapDependenciesForClass = new TrapDependencies(relative); this.trapFile = trapFile; @@ -324,11 +323,11 @@ public class OdasaOutput { return trapFile; } - public void addDependency(IrElement dep, String signature) { + public void addDependency(KaSymbol dep, String signature) { trapDependenciesForClass.addDependency(trapFilePathForDecl(dep, signature)); } - public void addDependency(IrClass c) { + public void addDependency(KaClassSymbol c) { addDependency(c, ""); } @@ -374,7 +373,7 @@ public class OdasaOutput { * {@link OdasaOutput#setCurrentSourceFile(File)}. */ public TrapLocker getTrapLockerForCurrentSourceFile() { - return new TrapLocker((IrClass) null, null, true); + return new TrapLocker((KaClassSymbol) null, null, true); } /** @@ -427,12 +426,12 @@ public class OdasaOutput { * @return a {@link TrapLocker} for the trap file corresponding to the given * class symbol. */ - public TrapLocker getTrapLockerForDecl(IrElement sym, String signature, boolean fromSource) { + public TrapLocker getTrapLockerForDecl(KaSymbol sym, String signature, boolean fromSource) { return new TrapLocker(sym, signature, fromSource); } public class TrapLocker implements AutoCloseable { - private final IrElement sym; + private final KaSymbol sym; private final File trapFile; // trapFileBase is used when doing lockless TRAP file writing. // It is trapFile without the #metadata.trap.gz suffix. @@ -440,7 +439,7 @@ public class OdasaOutput { private TrapClassVersion trapFileVersion = null; private final String signature; - private TrapLocker(IrElement decl, String signature, boolean fromSource) { + private TrapLocker(KaSymbol decl, String signature, boolean fromSource) { this.sym = decl; this.signature = signature; if (sym == null) { @@ -675,7 +674,7 @@ public class OdasaOutput { return vf.getTimeStamp(); } - private static VirtualFile getVirtualFileIfClass(IrElement e) { + private static VirtualFile getVirtualFileIfClass(KaSymbol e) { // TODO: return null; // if (e instanceof IrClass) @@ -684,10 +683,12 @@ public class OdasaOutput { // return null; } - private static TrapClassVersion fromSymbol(IrElement sym, Logger log) { + private static TrapClassVersion fromSymbol(KaSymbol sym, Logger log) { VirtualFile vf = getVirtualFileIfClass(sym); + /* OLD: KE1 if (vf == null && sym instanceof IrDeclaration) vf = getVirtualFileIfClass(((IrDeclaration) sym).getParent()); + */ if (vf == null) return new TrapClassVersion(-1, 0, 0, null); diff --git a/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt index a93065bed11..9816cd26c2f 100644 --- a/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt @@ -1,34 +1,32 @@ package com.github.codeql -/* -OLD: KE1 -import com.github.codeql.utils.isExternalFileClassMember import com.semmle.extractor.java.OdasaOutput import com.semmle.util.data.StringDigestor +import org.jetbrains.kotlin.analysis.api.KaSession +import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol import java.io.BufferedWriter import java.io.File import java.util.ArrayList import java.util.HashSet -import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.util.isFileClass -import org.jetbrains.kotlin.ir.util.packageFqName +context (KaSession) class ExternalDeclExtractor( val logger: FileLogger, val compression: Compression, val invocationTrapFile: String, val sourceFilePath: String, + /* OLD: KE1 val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState, + */ val diagnosticTrapWriter: DiagnosticTrapWriter ) { - val declBinaryNames = HashMap() + val declBinaryNames = HashMap() val externalDeclsDone = HashSet>() - val externalDeclWorkList = ArrayList>() + val externalDeclWorkList = ArrayList>() val propertySignature = ";property" val fieldSignature = ";field" @@ -38,7 +36,8 @@ class ExternalDeclExtractor( it.setCurrentSourceFile(File(sourceFilePath)) } - fun extractLater(d: IrDeclarationWithName, signature: String): Boolean { + fun extractLater(d: KaSymbol, signature: String): Boolean { + /* OLD: KE1 if (d !is IrClass && !isExternalFileClassMember(d)) { logger.errorElement( "External declaration is neither a class, nor a top-level declaration", @@ -46,15 +45,16 @@ class ExternalDeclExtractor( ) return false } - val declBinaryName = declBinaryNames.getOrPut(d) { getIrElementBinaryName(d) } + */ + val declBinaryName = declBinaryNames.getOrPut(d) { getSymbolBinaryName(d) } val ret = externalDeclsDone.add(Pair(declBinaryName, signature)) if (ret) externalDeclWorkList.add(Pair(d, signature)) return ret } - fun extractLater(c: IrClass) = extractLater(c, "") + fun extractLater(c: KaClassSymbol) = extractLater(c, "") - fun writeStubTrapFile(e: IrElement, signature: String = "") { + fun writeStubTrapFile(e: KaSymbol, signature: String = "") { extractElement(e, signature, true) { trapFileBW, _, _ -> trapFileBW.write( "// Trap file stubbed because this declaration was extracted from source in $sourceFilePath\n" @@ -64,7 +64,7 @@ class ExternalDeclExtractor( } private fun extractElement( - element: IrElement, + element: KaSymbol, possiblyLongSignature: String, fromSource: Boolean, extractorFn: (BufferedWriter, String, OdasaOutput.TrapFileManager) -> Unit @@ -84,8 +84,8 @@ class ExternalDeclExtractor( locker.trapFileManager.useAC { manager -> val shortName = when (element) { - is IrDeclarationWithName -> element.name.asString() - is IrFile -> element.name + is KaNamedSymbol -> element.name.asString() + is KaFileSymbol -> "(TODO file symbol name)" else -> "(unknown name)" } if (manager == null) { @@ -126,14 +126,16 @@ class ExternalDeclExtractor( val nextBatch = ArrayList(externalDeclWorkList) externalDeclWorkList.clear() nextBatch.forEach { workPair -> - val (irDecl, possiblyLongSignature) = workPair - extractElement(irDecl, possiblyLongSignature, false) { + val (sym, possiblyLongSignature) = workPair + extractElement(sym, possiblyLongSignature, false) { trapFileBW, signature, manager -> - val binaryPath = getIrDeclarationBinaryPath(irDecl) + val binaryPath = getSymbolBinaryPath(sym) if (binaryPath == null) { - logger.errorElement("Unable to get binary path", irDecl) + sym.psi?.also { + logger.errorElement("Unable to get binary path", it) + } ?: logger.error("Unable to get binary path") } else { // We want our comments to be the first thing in the file, // so start off with a PlainTrapWriter @@ -161,40 +163,46 @@ class ExternalDeclExtractor( KotlinFileExtractor( logger, ftw, + this, + /* OLD: KE1 null, binaryPath, manager, - this, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState + */ ) - if (irDecl is IrClass) { + if (sym is KaClassSymbol) { // 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 pkg = sym.classId?.packageFqName?.asString() ?: "" val pkgId = fileExtractor.extractPackage(pkg) ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation()) ftw.writeCupackage(ftw.fileId, pkgId) fileExtractor.extractClassSource( - irDecl, - extractDeclarations = !irDecl.isFileClass, + sym, + extractDeclarations = /* OLD: KE1 !sym.isFileClass */true, + /* OLD: KE1 extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false + */ ) } else { fileExtractor.extractDeclaration( - irDecl, + sym as KaDeclarationSymbol, + /* OLD: KE1 extractPrivateMembers = false, extractFunctionBodies = false, extractAnnotations = true + */ ) } } @@ -204,4 +212,3 @@ class ExternalDeclExtractor( output.writeTrapSet() } } -*/ diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt index e2285471088..7105f2225b4 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt @@ -149,7 +149,7 @@ OLD: KE1 OLD: KE1 val globalExtensionState = KotlinExtractorGlobalState() */ - doAnalysis(compression, trapDir, srcDir, loggerBase, dtw, compilation, invocationExtractionProblems, kotlinArgs) + doAnalysis(compression, trapDir, srcDir, loggerBase, dtw, compilation, invocationExtractionProblems, kotlinArgs, invocationTrapFile) loggerBase.printLimitedDiagnosticCounts(dtw) /* OLD: KE1 @@ -177,7 +177,8 @@ fun doAnalysis( dtw: DiagnosticTrapWriter, compilation: Label, invocationExtractionProblems: ExtractionProblems, - args: List + args: List, + invocationTrapFile: String ) { lateinit var sourceModule: KaSourceModule val k2args: K2JVMCompilerArguments = parseCommandLineArguments(args.toList()) @@ -266,8 +267,8 @@ fun doAnalysis( /* OLD: KE1 fileExtractionProblems, - invocationTrapFile, */ + invocationTrapFile, fileDiagnosticTrapWriter, loggerBase, checkTrapIdentical, @@ -290,11 +291,8 @@ fun doAnalysis( // continue trying to extract everything else even if we get a // stack overflow or an assertion failure in one file. } catch (e: Throwable) { - /* - OLD: KE1 - logger.error("Extraction failed while extracting '${psiFile.virtualFilePath}'.", e) fileExtractionProblems.setNonRecoverableProblem() - */ + loggerBase.error(dtw, "Extraction failed while extracting '${psiFile.virtualFilePath}'.", e.stackTraceToString()) } } else { System.out.println("Warning: Not a KtFile") @@ -494,8 +492,8 @@ private fun doFile( /* OLD: KE1 fileExtractionProblems: FileExtractionProblems, - invocationTrapFile: String, - */ + */ + invocationTrapFile: String, fileDiagnosticTrapWriter: FileTrapWriter, loggerBase: LoggerBase, checkTrapIdentical: Boolean, @@ -566,31 +564,35 @@ private fun doFile( // Now elevate to a SourceFileTrapWriter, and populate the // file information val sftw = tw.makeSourceFileTrapWriter(srcFile, true) - /* - OLD: KE1 - val externalDeclExtractor = - ExternalDeclExtractor( - logger, - compression, - invocationTrapFile, - srcFilePath, - primitiveTypeMapping, - pluginContext, - globalExtensionState, - fileDiagnosticTrapWriter.getDiagnosticTrapWriter() - ) - val linesOfCode = LinesOfCode(logger, sftw, srcFile) - */ + val externalDeclExtractor = + ExternalDeclExtractor( + logger, + compression, + invocationTrapFile, + srcFilePath, + /* + OLD: KE1 + primitiveTypeMapping, + pluginContext, + globalExtensionState, + */ + fileDiagnosticTrapWriter.getDiagnosticTrapWriter() + ) + /* OLD: KE1 + val linesOfCode = LinesOfCode(logger, sftw, srcFile) + */ + val fileExtractor = KotlinFileExtractor( logger, sftw, + externalDeclExtractor, /* OLD: KE1 linesOfCode, srcFilePath, null, - externalDeclExtractor, + primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), @@ -599,9 +601,6 @@ private fun doFile( ) fileExtractor.extractFileContents(srcFile, sftw.fileId) - /* - OLD: KE1 - externalDeclExtractor.extractExternalClasses() - */ + externalDeclExtractor.extractExternalClasses() } } diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt index c0fe5279a36..7d949abc971 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt @@ -86,12 +86,12 @@ context (KaSession) open class KotlinFileExtractor( override val logger: FileLogger, override val tw: FileTrapWriter, + externalClassExtractor: ExternalDeclExtractor, /* OLD: KE1 val linesOfCode: LinesOfCode?, val filePath: String, dependencyCollector: OdasaOutput.TrapFileManager?, - externalClassExtractor: ExternalDeclExtractor, primitiveTypeMapping: PrimitiveTypeMapping, pluginContext: IrPluginContext, val declarationStack: DeclarationStack, @@ -101,10 +101,10 @@ open class KotlinFileExtractor( KotlinUsesExtractor( logger, tw, + externalClassExtractor, /* OLD: KE1 dependencyCollector, - externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState @@ -117,14 +117,14 @@ open class KotlinFileExtractor( val metaAnnotationSupport = MetaAnnotationSupport(logger, pluginContext, this) */ - inline fun with(kind: String, element: KtElement, f: () -> T): T { + inline fun with(kind: String, element: KtElement?, f: () -> T): T { val name = when (element) { is KtFile -> element.virtualFilePath is KtNamed -> element.getNameAsName()?.asString() ?: "" else -> "" } - val loc = tw.getLocationString(element) + val loc = element?.let { tw.getLocationString(it) } ?: "" val context = logger.loggerState.extractorContextStack context.push(ExtractorContext(kind, element, name, loc)) try { @@ -299,7 +299,7 @@ open class KotlinFileExtractor( extractAnnotations: Boolean */ ) { - with("declaration", declaration.psiSafe() ?: TODO()) { + with("declaration", declaration.psiSafe()) { /* OLD: KE1 if (!shouldExtractDecl(declaration, extractPrivateMembers)) return diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinUsesExtractor.kt index f32b3c643d6..495d782bc96 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinUsesExtractor.kt @@ -42,10 +42,11 @@ context (KaSession) open class KotlinUsesExtractor( open val logger: Logger, open val tw: TrapWriter, + val externalClassExtractor: ExternalDeclExtractor, /* OLD: KE1 val dependencyCollector: OdasaOutput.TrapFileManager?, - val externalClassExtractor: ExternalDeclExtractor, + val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState @@ -317,12 +318,6 @@ open class KotlinUsesExtractor( return UseClassInstanceResult(classTypeResult, extractClass) } - private fun extractClassLaterIfExternal(c: IrClass) { - if (isExternalDeclaration(c)) { - extractExternalClassLater(c) - } - } - private fun extractExternalEnclosingClassLater(d: IrDeclaration) { when (val parent = d.parent) { is IrClass -> extractExternalClassLater(parent) @@ -516,15 +511,6 @@ open class KotlinUsesExtractor( } ?: f } - private fun tryReplaceType( - cBeforeReplacement: IrClass, - argsIncludingOuterClassesBeforeReplacement: List? - ): Pair?> { - val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement) - val p = tryReplaceParcelizeRawType(c) - return Pair(p?.first ?: c, p?.second ?: argsIncludingOuterClassesBeforeReplacement) - } - */ /* @@ -1313,58 +1299,6 @@ open class KotlinUsesExtractor( data class ClassLabelResults(val classLabel: String /* TODO , val shortName: String */) - - /* - OLD: KE1 - fun getTypeParameterParentLabel(param: IrTypeParameter) = - param.parent.let { - when (it) { - is IrClass -> useClassSource(it) - is IrFunction -> - (if (this is KotlinFileExtractor) - this.declarationStack - .findOverriddenAttributes(it) - ?.takeUnless { - // When extracting the `static fun f$default(...)` that accompanies - // `fun f(val x: T? = defaultExpr, ...)`, - // `f$default` has no type parameters, and so there is no - // `f$default::T` to refer to. - // We have no good way to extract references to `T` in - // `defaultExpr`, so we just fall back on describing it - // in terms of `f::T`, even though that type variable ought to be - // out of scope here. - attribs -> - attribs.typeParameters?.isEmpty() == true - } - ?.id - else null) ?: useFunction(it, noReplace = true) - else -> { - logger.error("Unexpected type parameter parent $it") - null - } - } - } - - fun getTypeParameterLabel(param: IrTypeParameter): String { - // Use this instead of `useDeclarationParent` so we can use useFunction with noReplace = - // true, - // ensuring that e.g. a method-scoped type variable declared on kotlin.String.transform - // gets - // a different name to the corresponding java.lang.String.transform , even though - // useFunction - // will usually replace references to one function with the other. - val parentLabel = getTypeParameterParentLabel(param) - return "@\"typevar;{$parentLabel};${param.name}\"" - } - - private fun useTypeParameter(param: IrTypeParameter) = - TypeResult( - tw.getLabelFor(getTypeParameterLabel(param)), - useType(eraseTypeParameter(param)).javaResult.signature, - param.name.asString() - ) - - */ private fun extractModifier(m: String): Label { val modifierLabel = "@\"modifier;$m\"" val id: Label = tw.getLabelFor(modifierLabel, { tw.writeModifiers(it, m) }) diff --git a/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt b/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt index 441dc99cd58..a2449d0552d 100644 --- a/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt +++ b/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt @@ -304,27 +304,24 @@ abstract class TrapWriter( } } - /* - OLD: KE1 - /** - * Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the - * given `filePath` for locations. - */ - fun makeFileTrapWriter(filePath: String, populateFileTables: Boolean) = - FileTrapWriter( - basicLogger, - lm, - bw, - this.getDiagnosticTrapWriter(), - filePath, - populateFileTables - ) + /** + * Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the + * given `filePath` for locations. + */ + fun makeFileTrapWriter(filePath: String, populateFileTables: Boolean) = + FileTrapWriter( + basicLogger, + lm, + bw, + this.getDiagnosticTrapWriter(), + filePath, + populateFileTables + ) - /** - * Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the - * given `IrFile` for locations. - */ - */ + /** + * Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the + * given `IrFile` for locations. + */ fun makeSourceFileTrapWriter(file: KtFile, populateFileTables: Boolean) = SourceFileTrapWriter( basicLogger, @@ -452,6 +449,10 @@ open class FileTrapWriter( return getLocation(file, range) } + fun getFileOnlyLocation(): Label { + return getLocation(fileId, 0, 0, 0, 0) + } + /* OLD: KE1 /** Gets a label for the location of `e`. */ diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index 51e4ecc4320..bb00156677d 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -6,6 +6,7 @@ import org.jetbrains.kotlin.analysis.api.KaExperimentalApi import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.KaClassType +import org.jetbrains.kotlin.psi.KtElement context(KaSession) @OptIn(KaExperimentalApi::class) @@ -19,7 +20,7 @@ fun KotlinFileExtractor.extractClassSource( extractFunctionBodies: Boolean */ ): Label { - with("class source", c.psiSafe() ?: TODO()) { + with("class source", c.psiSafe()) { // OLD: KE1: DeclarationStackAdjuster(c).use { val id = useClassSource(c) val pkg = c.classId?.packageFqName?.asString() ?: "" @@ -40,8 +41,13 @@ fun KotlinFileExtractor.extractClassSource( kind != KaClassKind.CLASS && kind != KaClassKind.OBJECT //&& //OLD KE1: kind != ClassKind.ENUM_ENTRY - ) { - logger.warnElement("Unrecognised class kind $kind", c.psiSafe() ?: TODO()) + ) else { + c.psiSafe().let { e -> + if (e != null) + logger.warnElement("Unrecognised class kind $kind", e) + else + logger.warn("Unrecognised class kind $kind") + } } /* @@ -56,7 +62,7 @@ fun KotlinFileExtractor.extractClassSource( } } - val locId = tw.getLocation(c.psiSafe() ?: TODO()) + val locId = c.psiSafe()?.let { tw.getLocation(it) } ?: tw.getFileOnlyLocation() tw.writeHasLocation(id, locId) // OLD: KE1 @@ -187,12 +193,10 @@ fun KotlinFileExtractor.extractClassSource( // `args` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. */ +context(KaSession) private fun KotlinUsesExtractor.getClassLabel( c: KaClassSymbol, - /* - OLD: KE1 - argsIncludingOuterClasses: List? - */ + argsIncludingOuterClasses: List? ): ClassLabelResults { val unquotedLabel = getUnquotedClassLabel(c /* TODO , argsIncludingOuterClasses */) return ClassLabelResults("@\"class;${unquotedLabel.classLabel}\"" /* TODO , unquotedLabel.shortName */) @@ -201,30 +205,59 @@ private fun KotlinUsesExtractor.getClassLabel( context(KaSession) fun KotlinUsesExtractor.useClassSource(c: KaClassSymbol): Label { // For source classes, the label doesn't include any type arguments - val id = addClassLabel(c) + val id = addClassLabel(c, listOf()) return id } +private fun tryReplaceType( + cBeforeReplacement: KaClassSymbol, + argsIncludingOuterClassesBeforeReplacement: List? +): Pair?> { + return Pair(cBeforeReplacement, argsIncludingOuterClassesBeforeReplacement) + /* + OLD: KE1 + val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement) + val p = tryReplaceParcelizeRawType(c) + return Pair(p?.first ?: c, p?.second ?: argsIncludingOuterClassesBeforeReplacement) + */ +} + +private fun isExternalDeclaration(d: KaSymbol): Boolean { + return d.origin == KaSymbolOrigin.LIBRARY || d.origin == KaSymbolOrigin.JAVA_LIBRARY +} + +private fun KotlinUsesExtractor.extractExternalClassLater(c: KaClassSymbol) { + /* OLD: KE1 + dependencyCollector?.addDependency(c) + */ + externalClassExtractor.extractLater(c) +} + + +private fun KotlinUsesExtractor.extractClassLaterIfExternal(c: KaClassSymbol) { + if (isExternalDeclaration(c)) { + extractExternalClassLater(c) + } +} + // `typeArgs` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. // TODO: Should this be private? +context(KaSession) fun KotlinUsesExtractor.addClassLabel( - c: KaClassSymbol, // TODO cBeforeReplacement: IrClass, + cBeforeReplacement: KaClassSymbol, // TODO cBeforeReplacement: IrClass, + argsIncludingOuterClassesBeforeReplacement: List?, /* OLD: KE1 - argsIncludingOuterClassesBeforeReplacement: List?, inReceiverContext: Boolean = false */ ): Label { - /* - OLD: KE1 - val replaced = - tryReplaceType(cBeforeReplacement, argsIncludingOuterClassesBeforeReplacement) - val replacedClass = replaced.first - val replacedArgsIncludingOuterClasses = replaced.second + val replaced = + tryReplaceType(cBeforeReplacement, argsIncludingOuterClassesBeforeReplacement) + val replacedClass = replaced.first + val replacedArgsIncludingOuterClasses = replaced.second - */ - val classLabelResult = getClassLabel(c /* TODO replacedClass, replacedArgsIncludingOuterClasses */) + val classLabelResult = getClassLabel(replacedClass, replacedArgsIncludingOuterClasses) /* OLD: KE1 @@ -237,16 +270,9 @@ fun KotlinUsesExtractor.addClassLabel( OLD: KE1 instanceSeenBefore = false - extractClassLaterIfExternal(replacedClass) */ + extractClassLaterIfExternal(replacedClass) // TODO: This shouldn't be done here, but keeping it simple for now - val classId = c.classId - if (classId == null) { - TODO() // this is a local class - } else { - val pkgId = extractPackage(classId.packageFqName.asString()) - tw.writeClasses_or_interfaces(it, classId.relativeClassName.asString(), pkgId, it) - } } /* @@ -297,6 +323,7 @@ OLD: KE1 * it will be zero-length list. */ */ +context(KaSession) private fun KotlinUsesExtractor.getUnquotedClassLabel( c: KaClassSymbol, /* @@ -309,25 +336,32 @@ private fun KotlinUsesExtractor.getUnquotedClassLabel( TODO() // This is a local class } val pkg = classId.packageFqName.asString() - val cls = classId.relativeClassName.asString() + val cls = classId.shortClassName.asString() val label = - /* - OLD: KE1 - if (c.isAnonymousObject) "{${useAnonymousClass(c).javaResult.id}}" - else - when (val parent = c.parent) { - is IrClass -> { - "${getUnquotedClassLabel(parent, listOf()).classLabel}\$$cls" - } - is IrFunction -> { - "{${useFunction(parent)}}.$cls" - } - is IrField -> { - "{${useField(parent)}}.$cls" - } - else -> { - */ - if (pkg.isEmpty()) cls else "$pkg.$cls" + /* OLD: KE1 + if (c.isAnonymousObject) "{${useAnonymousClass(c).javaResult.id}}" + else + */ + when (val parent = c.containingSymbol) { + is KaClassSymbol -> { + "${getUnquotedClassLabel(parent).classLabel}\$$cls" + } + + is KaFunctionSymbol -> { + "{${useFunction(parent)}}.$cls" + } + + is KaPropertySymbol -> { + TODO() + /* OLD: KE1 + "{${useField(parent)}}.$cls" + */ + } + + else -> { + if (pkg.isEmpty()) cls else "$pkg.$cls" + } + } /* OLD: KE1 } diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Expression.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Expression.kt index 7f085db2b6f..a09e7fed241 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Expression.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Expression.kt @@ -166,6 +166,7 @@ OLD: KE1 } */ +context(KaSession) fun KotlinFileExtractor.extractConstantInteger( text: String, t: KaType, @@ -1576,6 +1577,7 @@ private fun KotlinFileExtractor.extractVariableAccess( } } +context(KaSession) private fun KotlinFileExtractor.extractVariableAccess( variable: Label?, type: KaType, diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt index 7a3904a5307..81885251179 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt @@ -409,7 +409,7 @@ private fun KotlinFileExtractor.forceExtractFunction( overriddenAttributes: OverriddenFunctionAttributes? = null */ ): Label { - with("function", f.psiSafe() ?: TODO()) { + with("function", f.psiSafe()) { /* OLD: KE1 DeclarationStackAdjuster(f, overriddenAttributes).use { @@ -508,8 +508,9 @@ OLD: KE1 } ?: adjustedReturnType */ val functionSyntax = f.psi as? KtDeclarationWithBody - val locId = + val locId = functionSyntax?.let { tw.getLocation(functionSyntax ?: TODO()) + } ?: tw.getFileOnlyLocation() /* OLD: KE1 overriddenAttributes?.sourceLoc @@ -672,6 +673,7 @@ fun KotlinFileExtractor.extractValueParameter( } // TODO: Can this be inlined? +context(KaSession) private fun KotlinFileExtractor.extractMethod( id: Label, /* @@ -724,6 +726,16 @@ private fun KotlinFileExtractor.extractMethod( */ } +context(KaSession) +fun KotlinUsesExtractor.useFunction( + f: KaFunctionSymbol, + /* + OLD: KE1 + classTypeArgsIncludingOuterClasses: List?, + noReplace: Boolean = false + */ +): Label = useFunction(f, useDeclarationParentOf(f, true)!! /* TODO */) + context(KaSession) fun KotlinUsesExtractor.useFunction( f: KaFunctionSymbol, diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt index 18b7a00ead4..da7228ade92 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt @@ -1,15 +1,19 @@ package com.github.codeql +import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol import org.jetbrains.kotlin.analysis.api.types.KaClassType import org.jetbrains.kotlin.analysis.api.types.KaFlexibleType import org.jetbrains.kotlin.analysis.api.types.KaType +import org.jetbrains.kotlin.analysis.api.types.KaTypeParameterType +context(KaSession) private fun KotlinUsesExtractor.useClassType( c: KaClassType ): TypeResults { // TODO: this cast is unsafe; .symbol is actually a KaClassLikeSymbol - val classId = addClassLabel(c.symbol as KaClassSymbol) + val classId = addClassLabel(c.symbol as KaClassSymbol, listOf()) val javaResult = TypeResult(classId /* , TODO, TODO */) val kotlinTypeId = tw.getLabelFor("@\"kt_class;{$classId}\"") { @@ -19,6 +23,60 @@ private fun KotlinUsesExtractor.useClassType( return TypeResults(javaResult, kotlinResult) } +context(KaSession) +fun KotlinUsesExtractor.getTypeParameterParentLabel(param: KaTypeParameterType) = + param.symbol.containingSymbol?.let { + when (it) { + is KaClassSymbol -> useClassSource(it) + is KaFunctionSymbol -> + /* OLD: KE1 + (if (this is KotlinFileExtractor) + this.declarationStack + .findOverriddenAttributes(it) + ?.takeUnless { + // When extracting the `static fun f$default(...)` that accompanies + // `fun f(val x: T? = defaultExpr, ...)`, + // `f$default` has no type parameters, and so there is no + // `f$default::T` to refer to. + // We have no good way to extract references to `T` in + // `defaultExpr`, so we just fall back on describing it + // in terms of `f::T`, even though that type variable ought to be + // out of scope here. + attribs -> + attribs.typeParameters?.isEmpty() == true + } + ?.id + else null) ?: + */ + useFunction(it, useDeclarationParentOf(it, true) ?: TODO() /* OLD: KE1 noReplace = true */) + else -> { + logger.error("Unexpected type parameter parent $it") + null + } + } + } + +context(KaSession) +fun KotlinUsesExtractor.getTypeParameterLabel(param: KaTypeParameterType): String { + // Use this instead of `useDeclarationParent` so we can use useFunction with noReplace = true, + // ensuring that e.g. a method-scoped type variable declared on kotlin.String.transform gets + // a different name to the corresponding java.lang.String.transform, even though + // useFunction will usually replace references to one function with the other. + val parentLabel = getTypeParameterParentLabel(param) + return "@\"typevar;{$parentLabel};${param.name}\"" +} + +context(KaSession) +private fun KotlinUsesExtractor.useTypeParameterType(param: KaTypeParameterType) = + TypeResult( + tw.getLabelFor(getTypeParameterLabel(param)), + /* OLD: KE1 + useType(eraseTypeParameter(param)).javaResult.signature, + param.name.asString() + */ + ) + +context(KaSession) fun KotlinUsesExtractor.useType(t: KaType?, context: TypeContext = TypeContext.OTHER): TypeResults { val tr = when (t) { null -> { @@ -27,6 +85,7 @@ fun KotlinUsesExtractor.useType(t: KaType?, context: TypeContext = TypeContext.O } is KaClassType -> useClassType(t) is KaFlexibleType -> useType(t.lowerBound) // TODO: take a more reasoned choice here + is KaTypeParameterType -> TypeResults(useTypeParameterType(t), extractErrorType().kotlinResult /* TODO */) else -> TODO() } val javaResult = tr.javaResult @@ -34,7 +93,7 @@ fun KotlinUsesExtractor.useType(t: KaType?, context: TypeContext = TypeContext.O val abbreviation = t.abbreviatedType val kotlinResultAlias = if (abbreviation == null) kotlinResultBase else { // TODO: this cast is unsafe; .symbol is actually a KaClassLikeSymbol - val classId = addClassLabel(abbreviation.symbol as KaClassSymbol) + val classId = addClassLabel(abbreviation.symbol as KaClassSymbol, listOf() /* TODO */) val kotlinBaseTypeId = kotlinResultBase.id val kotlinAliasTypeId = tw.getLabelFor("@\"kt_type_alias;{$classId};{$kotlinBaseTypeId}\"") { diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/AutoCloseableUse.kt b/java/kotlin-extractor2/src/main/kotlin/utils/AutoCloseableUse.kt index 363afdf82d4..7883d04b8e4 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/AutoCloseableUse.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/AutoCloseableUse.kt @@ -1,7 +1,5 @@ package com.github.codeql -/* -OLD: KE1 // Functions copied from stdlib/jdk7/src/kotlin/AutoCloseable.kt, which is not available within // kotlinc, // but allows the `.use` pattern to be applied to JDK7 AutoCloseables: @@ -47,4 +45,3 @@ fun AutoCloseable?.closeFinallyAC(cause: Throwable?) = cause.addSuppressed(closeException) } } -*/ diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/ClassNames.kt b/java/kotlin-extractor2/src/main/kotlin/utils/ClassNames.kt index b362eb668fc..c04aa7013a8 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/ClassNames.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/ClassNames.kt @@ -1,5 +1,13 @@ package com.github.codeql +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaFileSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaNamedClassSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.* /* @@ -19,15 +27,18 @@ import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass +*/ // Adapted from Kotlin's interpreter/Utils.kt function 'internalName' // Translates class names into their JLS section 13.1 binary name, // and declarations within them into the parent class' JLS 13.1 name as // specified above, followed by a `$` separator and then the short name // for `that`. -private fun getName(d: IrDeclarationWithName) = +private fun getName(d: KaNamedSymbol) = + d.name.identifier + /* OLD: KE1 (d as? IrAnnotationContainer)?.let { getJvmName(it) } ?: d.name.asString() -*/ + */ fun getFileClassName(f: KtFile): String = null /* OLD: KE1: getJvmName(f) */ @@ -36,27 +47,31 @@ fun getFileClassName(f: KtFile): String = .replaceFirst(Regex("""\.kt$"""), "") .replaceFirstChar { it.uppercase() }) + "Kt") -/* -OLD: KE1 -fun getIrElementBinaryName(that: IrElement): String { - if (that is IrFile) { +private fun getBinaryName(cid: ClassId): String = + (cid.outerClassId?.let { ocid -> "${getBinaryName(ocid)}${'$'}" } ?: "${cid.packageFqName}.") + cid.shortClassName + +fun getSymbolBinaryName(that: KaSymbol): String { + if (that is KaFileSymbol) { + return "TODO" + /* OLD: KE1 val shortName = getFileClassName(that) val pkg = that.packageFqName.asString() return if (pkg.isEmpty()) shortName else "$pkg.$shortName" + */ } + /* OLD: KE1 if (that !is IrDeclaration) { return "(unknown-name)" } + */ - val shortName = - when (that) { - is IrDeclarationWithName -> getName(that) - else -> "(unknown-name)" - } + val internalName = + (that as? KaNamedClassSymbol)?.classId?.let { getBinaryName(it) } + ?: "(unknown-binary-name)" + /* OLD: KE1 + if (that !is KaClassSymbol) { - val internalName = StringBuilder(shortName) - if (that !is IrClass) { val parent = that.parent if (parent is IrFile) { // Note we'll fall through and do the IrPackageFragment case as well, since IrFile <: @@ -64,22 +79,14 @@ fun getIrElementBinaryName(that: IrElement): String { internalName.insert(0, getFileClassName(parent) + "$") } } + */ - generateSequence(that.parent) { (it as? IrDeclaration)?.parent } - .forEach { - when (it) { - is IrClass -> internalName.insert(0, getName(it) + "$") - is IrPackageFragment -> - it.packageFqName - .asString() - .takeIf { fqName -> fqName.isNotEmpty() } - ?.let { fqName -> internalName.insert(0, "$fqName.") } - } - } - return internalName.toString() + return internalName } -fun getIrClassVirtualFile(irClass: IrClass): VirtualFile? { +fun getIrClassVirtualFile(c: KaClassSymbol): VirtualFile? { + return c.psi?.containingFile?.virtualFile + /* OLD: KE1 val cSource = irClass.source // Don't emit a location for multi-file classes until we're sure we can cope with different // declarations @@ -113,10 +120,11 @@ fun getIrClassVirtualFile(irClass: IrClass): VirtualFile? { } } return null + */ } -private fun getRawIrClassBinaryPath(irClass: IrClass) = - getIrClassVirtualFile(irClass)?.let { +private fun getRawClassSymbolBinaryPath(c: KaClassSymbol) = + getIrClassVirtualFile(c)?.let { val path = it.path if (it.fileSystem.protocol == StandardFileSystems.JRT_PROTOCOL) // For JRT files, which we assume to be the JDK, hide the containing JAR path to match the @@ -125,16 +133,18 @@ private fun getRawIrClassBinaryPath(irClass: IrClass) = else path } -fun getIrClassBinaryPath(irClass: IrClass): String { - return getRawIrClassBinaryPath(irClass) +fun getClassSymbolBinaryPath(c: KaClassSymbol): String { + return getRawClassSymbolBinaryPath(c) // Otherwise, make up a fake location: - ?: getUnknownBinaryLocation(getIrElementBinaryName(irClass)) + ?: getUnknownBinaryLocation(getSymbolBinaryName(c)) } -fun getIrDeclarationBinaryPath(d: IrDeclaration): String? { - if (d is IrClass) { - return getIrClassBinaryPath(d) +fun getSymbolBinaryPath(d: KaSymbol): String? { + if (d is KaClassSymbol) { + return getClassSymbolBinaryPath(d) } + /* + OLD: KE1 val parentClass = d.parentClassOrNull if (parentClass != null) { return getIrClassBinaryPath(parentClass) @@ -146,6 +156,7 @@ fun getIrDeclarationBinaryPath(d: IrDeclaration): String? { return getUnknownBinaryLocation(fqName.asString()) } } + */ return null } @@ -153,6 +164,7 @@ private fun getUnknownBinaryLocation(s: String): String { return "/!unknown-binary-location/${s.replace(".", "/")}.class" } +/* OLD: KE1 fun getJavaEquivalentClassId(c: IrClass) = c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) } */ diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt index 04e63e6abab..7615e865929 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt @@ -101,7 +101,7 @@ class LogMessage(private val kind: String, private val message: String) { data class ExtractorContext( val kind: String, - val element: PsiElement, + val element: PsiElement?, val name: String, val loc: String ) From dfad8c84758e6a20ba4c95ca62e77e74f77b634a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 15:39:48 +0000 Subject: [PATCH 02/11] Don't bubble TODOs and other unchecked exceptions up to top level --- .../kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt index 9816cd26c2f..cb317e4e61e 100644 --- a/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/ExternalDeclExtractor.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol import java.io.BufferedWriter import java.io.File +import java.lang.Error import java.util.ArrayList import java.util.HashSet @@ -109,7 +110,7 @@ class ExternalDeclExtractor( logger.error("Failed to rename $trapTmpFile to $trapFile") } logger.info("Finished writing TRAP file $trapFile") - } catch (e: Exception) { + } catch (e: Throwable) { manager.setHasError() logger.error( "Failed to extract '$shortName'. Partial TRAP file location is $trapTmpFile", From bfdb5e0b1732903bdf547971870ad39dd1314fbb Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 16:29:31 +0000 Subject: [PATCH 03/11] Add error function taking a throwable to LoggerBase --- java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt | 2 +- java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt index 7105f2225b4..d2161502d58 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinExtractor.kt @@ -292,7 +292,7 @@ fun doAnalysis( // stack overflow or an assertion failure in one file. } catch (e: Throwable) { fileExtractionProblems.setNonRecoverableProblem() - loggerBase.error(dtw, "Extraction failed while extracting '${psiFile.virtualFilePath}'.", e.stackTraceToString()) + loggerBase.error(dtw, "Extraction failed while extracting '${psiFile.virtualFilePath}'.", e) } } else { System.out.println("Warning: Not a KtFile") diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt index 7615e865929..b5656da5a88 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt @@ -286,6 +286,10 @@ class LoggerBase(val diagnosticCounter: DiagnosticCounter) : BasicLogger { error(dtw, msg, extraInfo, null) } + fun error(dtw: DiagnosticTrapWriter, msg: String, exn: Throwable) { + error(dtw, msg, exn.stackTraceToString()) + } + fun error(dtw: DiagnosticTrapWriter, msg: String, extraInfo: String?, loggerState: LoggerState?) { if (verbosity >= 1) { diagnostic(dtw, Severity.Error, msg, extraInfo, loggerState) @@ -385,7 +389,7 @@ open class Logger(val loggerBase: LoggerBase, val dtw: DiagnosticTrapWriter) : B } fun error(msg: String, exn: Throwable) { - error(msg, exn.stackTraceToString()) + loggerBase.error(dtw, msg, exn) } } From e29d9ddacb42a98efcdaa85aa04c866c5d742153 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 16:49:37 +0000 Subject: [PATCH 04/11] Restore location and name reporting for symbols --- .../src/main/kotlin/KotlinFileExtractor.kt | 19 +++++++------ .../src/main/kotlin/entities/Class.kt | 2 +- .../src/main/kotlin/entities/Function.kt | 2 +- .../src/main/kotlin/utils/Logger.kt | 28 ++++++++++++++++++- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt index 7d949abc971..bc6346a3b9c 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt @@ -117,14 +117,15 @@ open class KotlinFileExtractor( val metaAnnotationSupport = MetaAnnotationSupport(logger, pluginContext, this) */ - inline fun with(kind: String, element: KtElement?, f: () -> T): T { - val name = - when (element) { - is KtFile -> element.virtualFilePath - is KtNamed -> element.getNameAsName()?.asString() ?: "" - else -> "" - } - val loc = element?.let { tw.getLocationString(it) } ?: "" + inline fun with(kind: String, element: PsiElement, f: () -> T) = with(kind, PsiElementWrapper(element), f) + inline fun with(kind: String, element: KaSymbol, f: () -> T) = + with(kind, + element.psiSafe()?.let { PsiElementWrapper(it) } ?: SymbolWrapper(element), + f) + + inline fun with(kind: String, element: PsiElementOrSymbol, f: () -> T): T { + val name = element.getName() + val loc = element.getLocationString(tw) val context = logger.loggerState.extractorContextStack context.push(ExtractorContext(kind, element, name, loc)) try { @@ -299,7 +300,7 @@ open class KotlinFileExtractor( extractAnnotations: Boolean */ ) { - with("declaration", declaration.psiSafe()) { + with("declaration", declaration) { /* OLD: KE1 if (!shouldExtractDecl(declaration, extractPrivateMembers)) return diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index bb00156677d..9c98f4cba1b 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -20,7 +20,7 @@ fun KotlinFileExtractor.extractClassSource( extractFunctionBodies: Boolean */ ): Label { - with("class source", c.psiSafe()) { + with("class source", c) { // OLD: KE1: DeclarationStackAdjuster(c).use { val id = useClassSource(c) val pkg = c.classId?.packageFqName?.asString() ?: "" diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt index 81885251179..08112355d06 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt @@ -409,7 +409,7 @@ private fun KotlinFileExtractor.forceExtractFunction( overriddenAttributes: OverriddenFunctionAttributes? = null */ ): Label { - with("function", f.psiSafe()) { + with("function", f) { /* OLD: KE1 DeclarationStackAdjuster(f, overriddenAttributes).use { diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt index b5656da5a88..a3c0e0af9d6 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt @@ -1,6 +1,10 @@ package com.github.codeql import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNamed import java.io.BufferedWriter import java.io.File import java.io.FileWriter @@ -99,9 +103,31 @@ class LogMessage(private val kind: String, private val message: String) { } } +sealed class PsiElementOrSymbol { + abstract fun getLocationString(ftw: FileTrapWriter): String + abstract fun getName(): String +} + +data class PsiElementWrapper(val e: PsiElement) : PsiElementOrSymbol() { + override fun getLocationString(ftw: FileTrapWriter) = ftw.getLocationString(e) + override fun getName() = when (e) { + is KtFile -> e.virtualFilePath + is KtNamed -> e.nameAsName?.asString() ?: "" + else -> "" + } +} + +data class SymbolWrapper(val e: KaSymbol) : PsiElementOrSymbol() { + override fun getLocationString(ftw: FileTrapWriter) = "file://${ftw.filePath}" + override fun getName() = when (e) { + is KaNamedSymbol -> e.name.asString() + else -> "" + } +} + data class ExtractorContext( val kind: String, - val element: PsiElement?, + val element: PsiElementOrSymbol, val name: String, val loc: String ) From 97ecd186786ad203d01791544967b1944e70e79b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 16:51:28 +0000 Subject: [PATCH 05/11] Merge duplicate functions --- java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt | 4 ---- java/kotlin-extractor2/src/main/kotlin/entities/Class.kt | 2 +- java/kotlin-extractor2/src/main/kotlin/entities/Function.kt | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt b/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt index a2449d0552d..eb066f5fb4e 100644 --- a/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt +++ b/java/kotlin-extractor2/src/main/kotlin/TrapWriter.kt @@ -449,10 +449,6 @@ open class FileTrapWriter( return getLocation(file, range) } - fun getFileOnlyLocation(): Label { - return getLocation(fileId, 0, 0, 0, 0) - } - /* OLD: KE1 /** Gets a label for the location of `e`. */ diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index 9c98f4cba1b..e86046b16bd 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -62,7 +62,7 @@ fun KotlinFileExtractor.extractClassSource( } } - val locId = c.psiSafe()?.let { tw.getLocation(it) } ?: tw.getFileOnlyLocation() + val locId = c.psiSafe()?.let { tw.getLocation(it) } ?: tw.getWholeFileLocation() tw.writeHasLocation(id, locId) // OLD: KE1 diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt index 08112355d06..af55a02df2a 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt @@ -510,7 +510,7 @@ OLD: KE1 val functionSyntax = f.psi as? KtDeclarationWithBody val locId = functionSyntax?.let { tw.getLocation(functionSyntax ?: TODO()) - } ?: tw.getFileOnlyLocation() + } ?: tw.getWholeFileLocation() /* OLD: KE1 overriddenAttributes?.sourceLoc From cc0a112ea6f08c084b83ce634bf45cb1fefb5f86 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 17:02:03 +0000 Subject: [PATCH 06/11] Generalise warnElement and errorElement --- .../src/main/kotlin/KotlinFileExtractor.kt | 8 ++---- .../src/main/kotlin/entities/Class.kt | 7 +---- .../src/main/kotlin/utils/Logger.kt | 26 ++++++++++++++----- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt index bc6346a3b9c..2a3f9637df1 100644 --- a/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt @@ -117,12 +117,8 @@ open class KotlinFileExtractor( val metaAnnotationSupport = MetaAnnotationSupport(logger, pluginContext, this) */ - inline fun with(kind: String, element: PsiElement, f: () -> T) = with(kind, PsiElementWrapper(element), f) - inline fun with(kind: String, element: KaSymbol, f: () -> T) = - with(kind, - element.psiSafe()?.let { PsiElementWrapper(it) } ?: SymbolWrapper(element), - f) - + inline fun with(kind: String, element: PsiElement, f: () -> T) = with(kind, PsiElementOrSymbol.of(element), f) + inline fun with(kind: String, element: KaSymbol, f: () -> T) = with(kind, PsiElementOrSymbol.of(element), f) inline fun with(kind: String, element: PsiElementOrSymbol, f: () -> T): T { val name = element.getName() val loc = element.getLocationString(tw) diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index e86046b16bd..ee3ebaecdd7 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -42,12 +42,7 @@ fun KotlinFileExtractor.extractClassSource( kind != KaClassKind.OBJECT //&& //OLD KE1: kind != ClassKind.ENUM_ENTRY ) else { - c.psiSafe().let { e -> - if (e != null) - logger.warnElement("Unrecognised class kind $kind", e) - else - logger.warn("Unrecognised class kind $kind") - } + logger.warnElement("Unrecognised class kind $kind", c) } /* diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt index a3c0e0af9d6..5118b3aff08 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt @@ -3,6 +3,7 @@ package com.github.codeql import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol +import org.jetbrains.kotlin.analysis.api.symbols.psiSafe import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamed import java.io.BufferedWriter @@ -105,11 +106,17 @@ class LogMessage(private val kind: String, private val message: String) { sealed class PsiElementOrSymbol { abstract fun getLocationString(ftw: FileTrapWriter): String + abstract fun getLocation(ftw: FileTrapWriter): Label abstract fun getName(): String + companion object { + fun of(e: PsiElement) = PsiElementWrapper(e) + fun of(e: KaSymbol) = e.psiSafe()?.let { of(it) } ?: SymbolWrapper(e) + } } data class PsiElementWrapper(val e: PsiElement) : PsiElementOrSymbol() { override fun getLocationString(ftw: FileTrapWriter) = ftw.getLocationString(e) + override fun getLocation(ftw: FileTrapWriter) = ftw.getLocation(e) override fun getName() = when (e) { is KtFile -> e.virtualFilePath is KtNamed -> e.nameAsName?.asString() ?: "" @@ -119,6 +126,7 @@ data class PsiElementWrapper(val e: PsiElement) : PsiElementOrSymbol() { data class SymbolWrapper(val e: KaSymbol) : PsiElementOrSymbol() { override fun getLocationString(ftw: FileTrapWriter) = "file://${ftw.filePath}" + override fun getLocation(ftw: FileTrapWriter) = ftw.getWholeFileLocation() override fun getName() = when (e) { is KaNamedSymbol -> e.name.asString() else -> "" @@ -434,9 +442,9 @@ class FileLogger(loggerBase: LoggerBase, val ftw: FileTrapWriter, fileNumber: In loggerBase.warn(dtw, msg, extraInfo, loggerState) } - fun warnElement(msg: String, element: PsiElement/* TODO , exn: Throwable? = null */) { - val locationString = ftw.getLocationString(element) - val mkLocationId = { ftw.getLocation(element) } + fun warnElement(msg: String, element: PsiElementOrSymbol /* TODO , exn: Throwable? = null */) { + val locationString = element.getLocationString(ftw) + val mkLocationId = { element.getLocation(ftw) } loggerBase.diagnostic( ftw.getDiagnosticTrapWriter(), Severity.Warn, @@ -448,13 +456,16 @@ class FileLogger(loggerBase: LoggerBase, val ftw: FileTrapWriter, fileNumber: In ) } + fun warnElement(msg: String, element: PsiElement /* TODO , exn: Throwable? = null */) = warnElement(msg, PsiElementOrSymbol.of(element)) + fun warnElement(msg: String, element: KaSymbol /* TODO , exn: Throwable? = null */) = warnElement(msg, PsiElementOrSymbol.of(element)) + override fun error(dtw: DiagnosticTrapWriter, msg: String, extraInfo: String?) { loggerBase.error(dtw, msg, extraInfo, loggerState) } - fun errorElement(msg: String, element: PsiElement /* TODO , exn: Throwable? = null */) { - val locationString = ftw.getLocationString(element) - val mkLocationId = { ftw.getLocation(element) } + fun errorElement(msg: String, element: PsiElementOrSymbol /* TODO , exn: Throwable? = null */) { + val locationString = element.getLocationString(ftw) + val mkLocationId = { element.getLocation(ftw) } loggerBase.diagnostic( ftw.getDiagnosticTrapWriter(), Severity.Error, @@ -465,4 +476,7 @@ class FileLogger(loggerBase: LoggerBase, val ftw: FileTrapWriter, fileNumber: In mkLocationId ) } + + fun errorElement(msg: String, element: PsiElement /* TODO , exn: Throwable? = null */) = errorElement(msg, PsiElementOrSymbol.of(element)) + fun errorElement(msg: String, element: KaSymbol /* TODO , exn: Throwable? = null */) = errorElement(msg, PsiElementOrSymbol.of(element)) } From a3d78f1bad782c00218eec82458f5cf9ed10f0f1 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 17:10:26 +0000 Subject: [PATCH 07/11] Neaten symbol-to-location --- java/kotlin-extractor2/src/main/kotlin/entities/Class.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index ee3ebaecdd7..1a9fbbaae8c 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -57,7 +57,7 @@ fun KotlinFileExtractor.extractClassSource( } } - val locId = c.psiSafe()?.let { tw.getLocation(it) } ?: tw.getWholeFileLocation() + val locId = PsiElementOrSymbol.of(c).getLocation(tw) tw.writeHasLocation(id, locId) // OLD: KE1 From dd9d8720b07a931b1e29ddb86492ed1051f70d30 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 17:10:40 +0000 Subject: [PATCH 08/11] Add doc comment --- java/kotlin-extractor2/src/main/kotlin/entities/Class.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index 1a9fbbaae8c..423aa515cae 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -204,6 +204,14 @@ fun KotlinUsesExtractor.useClassSource(c: KaClassSymbol): Label + * + * These could include replacing Android synthetic classes or Parcelize raw types that shouldn't appear in the database + * as they appear to the Kotlin compiler. + * + * TODO: verify how these sorts of classes appear via the analysis API + */ private fun tryReplaceType( cBeforeReplacement: KaClassSymbol, argsIncludingOuterClassesBeforeReplacement: List? From d27b5ed96ec2ca98ef906d1bfc4fe30ec211dfa6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 17:11:08 +0000 Subject: [PATCH 09/11] Remove redundant comment --- java/kotlin-extractor2/src/main/kotlin/entities/Class.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index 423aa515cae..642164fd0ce 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -275,7 +275,6 @@ OLD: KE1 */ extractClassLaterIfExternal(replacedClass) - // TODO: This shouldn't be done here, but keeping it simple for now } /* From 54961ddc88a279dd566f105c35ef3e8afa672aa6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 17:54:45 +0000 Subject: [PATCH 10/11] Fixups --- java/kotlin-extractor2/src/main/kotlin/entities/Class.kt | 2 +- java/kotlin-extractor2/src/main/kotlin/entities/Function.kt | 1 + .../src/main/kotlin/entities/FunctionalInterface.kt | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt index 642164fd0ce..b66289a6d20 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Class.kt @@ -74,7 +74,7 @@ fun KotlinFileExtractor.extractClassSource( if (getter == null) { logger.warnElement( "Expected an annotation property to have a getter", - it.psiSafe() ?: TODO() + it ) } else { extractFunction( diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt index af55a02df2a..5edae548dc7 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Function.kt @@ -641,6 +641,7 @@ OLD: KE1 } } +context(KaSession) fun KotlinFileExtractor.extractValueParameter( id: Label, t: KaType, diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/FunctionalInterface.kt b/java/kotlin-extractor2/src/main/kotlin/entities/FunctionalInterface.kt index c3d3f8b4975..c37068e5680 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/FunctionalInterface.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/FunctionalInterface.kt @@ -216,6 +216,7 @@ private val nullableAnyArrayType: KaType * Adds a function named `invoke` with the specified parameter types and return type to the * class identified by `parentId`. */ +context(KaSession) private fun KotlinFileExtractor.addFunctionInvoke( methodId: Label, parameterTypes: List, @@ -237,6 +238,7 @@ private fun KotlinFileExtractor.addFunctionInvoke( * Extracts a function with the given name, parameter types, return type, containing type, and * location. */ +context(KaSession) private fun KotlinFileExtractor.addFunctionManual( methodId: Label, name: String, From fe4dc296f587df1e9d2f862f4e3b7bd0a3c8ec58 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 27 Nov 2024 18:04:40 +0000 Subject: [PATCH 11/11] Don't query non-Kt source elements for locations etc --- java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt index 5118b3aff08..f3531cd5362 100644 --- a/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor2/src/main/kotlin/utils/Logger.kt @@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.psiSafe +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamed import java.io.BufferedWriter @@ -110,7 +111,7 @@ sealed class PsiElementOrSymbol { abstract fun getName(): String companion object { fun of(e: PsiElement) = PsiElementWrapper(e) - fun of(e: KaSymbol) = e.psiSafe()?.let { of(it) } ?: SymbolWrapper(e) + fun of(e: KaSymbol) = e.psiSafe()?.let { of(it) } ?: SymbolWrapper(e) } }