mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #11510 from smowton/smowton/fix/kotlin-populate-source-class-files
Kotlin: stub trap .class files when extracting a class from Kotlin source
This commit is contained in:
@@ -19,9 +19,10 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.github.codeql.Logger;
|
||||
import static com.github.codeql.ClassNamesKt.getIrDeclBinaryName;
|
||||
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 com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -212,20 +213,19 @@ public class OdasaOutput {
|
||||
PathTransformer.std().fileAsDatabaseString(file) + ".trap.gz");
|
||||
}
|
||||
|
||||
private File getTrapFileForDecl(IrDeclaration sym, String signature) {
|
||||
private File getTrapFileForDecl(IrElement sym, String signature) {
|
||||
if (currentSpecFileEntry == null)
|
||||
return null;
|
||||
return trapFileForDecl(sym, signature);
|
||||
}
|
||||
|
||||
private File trapFileForDecl(IrDeclaration sym, String signature) {
|
||||
private File trapFileForDecl(IrElement sym, String signature) {
|
||||
return FileUtil.fileRelativeTo(currentSpecFileEntry.getTrapFolder(),
|
||||
trapFilePathForDecl(sym, signature));
|
||||
}
|
||||
|
||||
private String trapFilePathForDecl(IrDeclaration sym, String signature) {
|
||||
String binaryName = getIrDeclBinaryName(sym);
|
||||
String binaryNameWithSignature = binaryName + signature;
|
||||
private String trapFilePathForDecl(IrElement sym, String signature) {
|
||||
String binaryName = getIrElementBinaryName(sym);
|
||||
// TODO: Reinstate this?
|
||||
//if (getTrackClassOrigins())
|
||||
// classId += "-" + StringDigestor.digest(sym.getSourceFileId());
|
||||
@@ -241,7 +241,7 @@ public class OdasaOutput {
|
||||
* Deletion of existing trap files.
|
||||
*/
|
||||
|
||||
private void deleteTrapFileAndDependencies(IrDeclaration sym, String signature) {
|
||||
private void deleteTrapFileAndDependencies(IrElement sym, String signature) {
|
||||
File trap = trapFileForDecl(sym, signature);
|
||||
if (trap.exists()) {
|
||||
trap.delete();
|
||||
@@ -269,7 +269,7 @@ public class OdasaOutput {
|
||||
* Any unique suffix needed to distinguish `sym` from other declarations with the same name.
|
||||
* For functions for example, this means its parameter signature.
|
||||
*/
|
||||
private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, TrapClassVersion trapFileVersion, IrDeclaration sym, String signature) {
|
||||
private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, TrapClassVersion trapFileVersion, IrElement sym, String signature) {
|
||||
if (use_trap_locking) {
|
||||
TrapClassVersion currVersion = TrapClassVersion.fromSymbol(sym, log);
|
||||
String shortName = sym instanceof IrDeclarationWithName ? ((IrDeclarationWithName)sym).getName().asString() : "(name unknown)";
|
||||
@@ -326,7 +326,7 @@ public class OdasaOutput {
|
||||
return trapWriter(trap, sym, signature);
|
||||
}
|
||||
|
||||
private TrapFileManager trapWriter(File trapFile, IrDeclaration sym, String signature) {
|
||||
private TrapFileManager trapWriter(File trapFile, IrElement sym, String signature) {
|
||||
if (!trapFile.getName().endsWith(".trap.gz"))
|
||||
throw new CatastrophicError("OdasaOutput only supports writing to compressed trap files");
|
||||
String relative = FileUtil.relativePath(trapFile, currentSpecFileEntry.getTrapFolder());
|
||||
@@ -335,7 +335,7 @@ public class OdasaOutput {
|
||||
return concurrentWriter(trapFile, relative, log, sym, signature);
|
||||
}
|
||||
|
||||
private TrapFileManager concurrentWriter(File trapFile, String relative, Logger log, IrDeclaration sym, String signature) {
|
||||
private TrapFileManager concurrentWriter(File trapFile, String relative, Logger log, IrElement sym, String signature) {
|
||||
if (trapFile.exists())
|
||||
return null;
|
||||
return new TrapFileManager(trapFile, relative, true, log, sym, signature);
|
||||
@@ -345,11 +345,11 @@ public class OdasaOutput {
|
||||
|
||||
private TrapDependencies trapDependenciesForClass;
|
||||
private File trapFile;
|
||||
private IrDeclaration sym;
|
||||
private IrElement sym;
|
||||
private String signature;
|
||||
private boolean hasError = false;
|
||||
|
||||
private TrapFileManager(File trapFile, String relative, boolean concurrentCreation, Logger log, IrDeclaration sym, String signature) {
|
||||
private TrapFileManager(File trapFile, String relative, boolean concurrentCreation, Logger log, IrElement sym, String signature) {
|
||||
trapDependenciesForClass = new TrapDependencies(relative);
|
||||
this.trapFile = trapFile;
|
||||
this.sym = sym;
|
||||
@@ -360,7 +360,7 @@ public class OdasaOutput {
|
||||
return trapFile;
|
||||
}
|
||||
|
||||
public void addDependency(IrDeclaration dep, String signature) {
|
||||
public void addDependency(IrElement dep, String signature) {
|
||||
trapDependenciesForClass.addDependency(trapFilePathForDecl(dep, signature));
|
||||
}
|
||||
|
||||
@@ -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,19 +460,19 @@ 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(IrElement sym, String signature, boolean fromSource) {
|
||||
return new TrapLocker(sym, signature, fromSource);
|
||||
}
|
||||
|
||||
public class TrapLocker implements AutoCloseable {
|
||||
private final IrDeclaration sym;
|
||||
private final IrElement sym;
|
||||
private final File trapFile;
|
||||
// trapFileBase is used when doing lockless TRAP file writing.
|
||||
// It is trapFile without the #metadata.trap.gz suffix.
|
||||
private File trapFileBase = null;
|
||||
private TrapClassVersion trapFileVersion = null;
|
||||
private final String signature;
|
||||
private TrapLocker(IrDeclaration decl, String signature) {
|
||||
private TrapLocker(IrElement 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.
|
||||
@@ -717,11 +720,18 @@ public class OdasaOutput {
|
||||
return vf.getTimeStamp();
|
||||
}
|
||||
|
||||
private static TrapClassVersion fromSymbol(IrDeclaration sym, Logger log) {
|
||||
VirtualFile vf = sym instanceof IrClass ? getIrClassVirtualFile((IrClass)sym) :
|
||||
sym.getParent() instanceof IrClass ? getIrClassVirtualFile((IrClass)sym.getParent()) :
|
||||
null;
|
||||
if(vf == null)
|
||||
private static VirtualFile getVirtualFileIfClass(IrElement e) {
|
||||
if (e instanceof IrClass)
|
||||
return getIrClassVirtualFile((IrClass)e);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TrapClassVersion fromSymbol(IrElement sym, Logger log) {
|
||||
VirtualFile vf = getVirtualFileIfClass(sym);
|
||||
if (vf == null && sym instanceof IrDeclaration)
|
||||
vf = getVirtualFileIfClass(((IrDeclaration)sym).getParent());
|
||||
if (vf == null)
|
||||
return new TrapClassVersion(-1, 0, 0, null);
|
||||
|
||||
final int[] versionStore = new int[1];
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package com.github.codeql
|
||||
|
||||
import com.github.codeql.utils.isExternalDeclaration
|
||||
import com.github.codeql.utils.isExternalFileClassMember
|
||||
import com.semmle.extractor.java.OdasaOutput
|
||||
import com.semmle.util.data.StringDigestor
|
||||
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.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isFileClass
|
||||
import org.jetbrains.kotlin.ir.util.packageFqName
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
@@ -25,87 +23,103 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
|
||||
val propertySignature = ";property"
|
||||
val fieldSignature = ";field"
|
||||
|
||||
val output = OdasaOutput(false, logger).also {
|
||||
it.setCurrentSourceFile(File(sourceFilePath))
|
||||
}
|
||||
|
||||
fun extractLater(d: IrDeclarationWithName, signature: String): Boolean {
|
||||
if (d !is IrClass && !isExternalFileClassMember(d)) {
|
||||
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
|
||||
return false
|
||||
}
|
||||
val declBinaryName = declBinaryNames.getOrPut(d) { getIrDeclBinaryName(d) }
|
||||
val declBinaryName = declBinaryNames.getOrPut(d) { getIrElementBinaryName(d) }
|
||||
val ret = externalDeclsDone.add(Pair(declBinaryName, signature))
|
||||
if (ret) externalDeclWorkList.add(Pair(d, signature))
|
||||
return ret
|
||||
}
|
||||
fun extractLater(c: IrClass) = extractLater(c, "")
|
||||
|
||||
fun writeStubTrapFile(e: IrElement, signature: String = "") {
|
||||
extractElement(e, signature, true) { trapFileBW, _, _ ->
|
||||
trapFileBW.write("// Trap file stubbed because this declaration was extracted from source in $sourceFilePath\n")
|
||||
trapFileBW.write("// Part of invocation $invocationTrapFile\n")
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractElement(element: IrElement, 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(element, signature, fromSource).useAC { locker ->
|
||||
locker.trapFileManager.useAC { manager ->
|
||||
val shortName = when(element) {
|
||||
is IrDeclarationWithName -> element.name.asString()
|
||||
is IrFile -> element.name
|
||||
else -> "(unknown name)"
|
||||
}
|
||||
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)
|
||||
try {
|
||||
GZIPOutputStream(trapTmpFile.outputStream()).bufferedWriter().use {
|
||||
extractorFn(it, signature, manager)
|
||||
}
|
||||
|
||||
if (!trapTmpFile.renameTo(trapFile)) {
|
||||
logger.error("Failed to rename $trapTmpFile to $trapFile")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
manager.setHasError()
|
||||
logger.error("Failed to extract '$shortName'. Partial TRAP file location is $trapTmpFile", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun extractExternalClasses() {
|
||||
val output = OdasaOutput(false, logger)
|
||||
output.setCurrentSourceFile(File(sourceFilePath))
|
||||
do {
|
||||
val nextBatch = ArrayList(externalDeclWorkList)
|
||||
externalDeclWorkList.clear()
|
||||
nextBatch.forEach { workPair ->
|
||||
val (irDecl, possiblyLongSignature) = workPair
|
||||
// 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 ->
|
||||
locker.trapFileManager.useAC { manager ->
|
||||
val shortName = when(irDecl) {
|
||||
is IrDeclarationWithName -> irDecl.name.asString()
|
||||
else -> "(unknown name)"
|
||||
extractElement(irDecl, possiblyLongSignature, false) { trapFileBW, signature, manager ->
|
||||
val containingClass = getContainingClassOrSelf(irDecl)
|
||||
if (containingClass == null) {
|
||||
logger.errorElement("Unable to get containing class", irDecl)
|
||||
} else {
|
||||
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")
|
||||
}
|
||||
if(manager == null) {
|
||||
logger.info("Skipping extracting external decl $shortName")
|
||||
// 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 {
|
||||
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 { trapFileBW ->
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
if (!trapTmpFile.renameTo(trapFile)) {
|
||||
logger.error("Failed to rename $trapTmpFile to $trapFile")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
manager.setHasError()
|
||||
logger.error("Failed to extract '$shortName'. Partial TRAP file location is $trapTmpFile", e)
|
||||
}
|
||||
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,12 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
file.declarations.forEach { extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) }
|
||||
file.declarations.forEach {
|
||||
extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true)
|
||||
if (it is IrProperty || it is IrField || it is IrFunction) {
|
||||
externalClassExtractor.writeStubTrapFile(it, getTrapFileSignature(it))
|
||||
}
|
||||
}
|
||||
extractStaticInitializer(file, { extractFileClass(file) })
|
||||
CommentExtractor(this, file, tw.fileId).extract()
|
||||
|
||||
@@ -99,6 +104,8 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
|
||||
linesOfCode?.linesOfCodeInFile(id)
|
||||
|
||||
externalClassExtractor.writeStubTrapFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,6 +514,9 @@ open class KotlinFileExtractor(
|
||||
addModifiers(instance.id, "public", "static", "final")
|
||||
tw.writeClass_object(id.cast<DbClass>(), instance.id)
|
||||
}
|
||||
if (c.isObject) {
|
||||
addModifiers(id, "static")
|
||||
}
|
||||
if (extractFunctionBodies && needsObinitFunction(c)) {
|
||||
extractObinitFunction(c, id)
|
||||
}
|
||||
@@ -516,6 +526,9 @@ open class KotlinFileExtractor(
|
||||
|
||||
linesOfCode?.linesOfCodeInDeclaration(c, id)
|
||||
|
||||
if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal)
|
||||
externalClassExtractor.writeStubTrapFile(c)
|
||||
|
||||
return id
|
||||
}
|
||||
}
|
||||
@@ -1249,13 +1262,13 @@ open class KotlinFileExtractor(
|
||||
DeclarationStackAdjuster(f).use {
|
||||
val fNameSuffix = getExtensionReceiverType(f)?.let { it.classFqName?.asString()?.replace(".", "$$") } ?: ""
|
||||
val extractType = if (isAnnotationClassField(f)) kClassToJavaClass(f.type) else f.type
|
||||
return extractField(useField(f), "${f.name.asString()}$fNameSuffix", extractType, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
|
||||
return extractField(useField(f), "${f.name.asString()}$fNameSuffix", extractType, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal, isDirectlyExposedCompanionObjectField(f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun extractField(id: Label<out DbField>, name: String, type: IrType, parentId: Label<out DbReftype>, locId: Label<DbLocation>, visibility: DescriptorVisibility, errorElement: IrElement, isExternalDeclaration: Boolean, isFinal: Boolean): Label<out DbField> {
|
||||
private fun extractField(id: Label<out DbField>, name: String, type: IrType, parentId: Label<out DbReftype>, locId: Label<DbLocation>, visibility: DescriptorVisibility, errorElement: IrElement, isExternalDeclaration: Boolean, isFinal: Boolean, isStatic: Boolean): Label<out DbField> {
|
||||
val t = useType(type)
|
||||
tw.writeFields(id, name, t.javaResult.id, parentId, id)
|
||||
tw.writeFieldsKotlinType(id, t.kotlinResult.id)
|
||||
@@ -1265,6 +1278,9 @@ open class KotlinFileExtractor(
|
||||
if (isFinal) {
|
||||
addModifiers(id, "final")
|
||||
}
|
||||
if (isStatic) {
|
||||
addModifiers(id, "static")
|
||||
}
|
||||
|
||||
if (!isExternalDeclaration) {
|
||||
val fieldDeclarationId = tw.getFreshIdLabel<DbFielddecl>()
|
||||
@@ -4196,12 +4212,12 @@ open class KotlinFileExtractor(
|
||||
val firstAssignmentStmtIdx = 1
|
||||
|
||||
if (dispatchReceiverInfo != null) {
|
||||
extractField(dispatchReceiverInfo.field, "<dispatchReceiver>", dispatchReceiverInfo.type, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
|
||||
extractField(dispatchReceiverInfo.field, "<dispatchReceiver>", dispatchReceiverInfo.type, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true, isStatic = false)
|
||||
extractParameterToFieldAssignmentInConstructor("<dispatchReceiver>", dispatchReceiverInfo.type, dispatchReceiverInfo.field, 0 + dispatchReceiverInfo.indexOffset, firstAssignmentStmtIdx + dispatchReceiverInfo.indexOffset)
|
||||
}
|
||||
|
||||
if (extensionReceiverInfo != null) {
|
||||
extractField(extensionReceiverInfo.field, "<extensionReceiver>", extensionReceiverInfo.type, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
|
||||
extractField(extensionReceiverInfo.field, "<extensionReceiver>", extensionReceiverInfo.type, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true, isStatic = false)
|
||||
extractParameterToFieldAssignmentInConstructor( "<extensionReceiver>", extensionReceiverInfo.type, extensionReceiverInfo.field, 0 + extensionReceiverInfo.indexOffset, firstAssignmentStmtIdx + extensionReceiverInfo.indexOffset)
|
||||
}
|
||||
}
|
||||
@@ -5269,7 +5285,7 @@ open class KotlinFileExtractor(
|
||||
|
||||
// add field
|
||||
val fieldId = tw.getFreshIdLabel<DbField>()
|
||||
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, isExternalDeclaration = false, isFinal = true)
|
||||
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, isExternalDeclaration = false, isFinal = true, isStatic = false)
|
||||
|
||||
// adjust constructor
|
||||
helper.extractParameterToFieldAssignmentInConstructor("<fn>", functionType, fieldId, 0, 1)
|
||||
|
||||
@@ -67,15 +67,12 @@ open class KotlinUsesExtractor(
|
||||
TypeResult(fakeKotlinType(), "", "")
|
||||
)
|
||||
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
|
||||
fun extractFileClass(f: IrFile): Label<out DbClass> {
|
||||
val fileName = f.fileEntry.name
|
||||
val pkg = f.fqName.asString()
|
||||
val defaultName = fileName.replaceFirst(Regex(""".*[/\\]"""), "").replaceFirst(Regex("""\.kt$"""), "").replaceFirstChar({ it.uppercase() }) + "Kt"
|
||||
var jvmName = getJvmName(f) ?: defaultName
|
||||
val jvmName = getFileClassName(f)
|
||||
val qualClassName = if (pkg.isEmpty()) jvmName else "$pkg.$jvmName"
|
||||
val label = "@\"class;$qualClassName\""
|
||||
val id: Label<DbClass> = tw.getLabelFor(label, {
|
||||
val id: Label<DbClass> = tw.getLabelFor(label) {
|
||||
val fileId = tw.mkFileId(f.path, false)
|
||||
val locId = tw.getWholeFileLocation(fileId)
|
||||
val pkgId = extractPackage(pkg)
|
||||
@@ -84,7 +81,7 @@ open class KotlinUsesExtractor(
|
||||
tw.writeHasLocation(it, locId)
|
||||
|
||||
addModifiers(it, "public", "final")
|
||||
})
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -258,10 +255,26 @@ open class KotlinUsesExtractor(
|
||||
private fun propertySignature(p: IrProperty) =
|
||||
((p.getter ?: p.setter)?.extensionReceiverParameter?.let { useType(erase(it.type)).javaResult.signature } ?: "")
|
||||
|
||||
fun getTrapFileSignature(d: IrDeclaration) =
|
||||
when(d) {
|
||||
is IrFunction ->
|
||||
// Note we erase the parameter types before calling useType even though the signature should be the same
|
||||
// in order to prevent an infinite loop through useTypeParameter -> useDeclarationParent -> useFunction
|
||||
// -> extractFunctionLaterIfExternalFileMember, which would result for `fun <T> f(t: T) { ... }` for example.
|
||||
(listOfNotNull(d.extensionReceiverParameter) + d.valueParameters)
|
||||
.map { useType(erase(it.type)).javaResult.signature }
|
||||
.joinToString(separator = ",", prefix = "(", postfix = ")")
|
||||
is IrProperty -> propertySignature(d) + externalClassExtractor.propertySignature
|
||||
is IrField -> (d.correspondingPropertySymbol?.let { propertySignature(it.owner) } ?: "") + externalClassExtractor.fieldSignature
|
||||
else -> "unknown signature".also {
|
||||
logger.warn("Trap file signature requested for unexpected element $d")
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractPropertyLaterIfExternalFileMember(p: IrProperty) {
|
||||
if (isExternalFileClassMember(p)) {
|
||||
extractExternalClassLater(p.parentAsClass)
|
||||
val signature = propertySignature(p) + externalClassExtractor.propertySignature
|
||||
val signature = getTrapFileSignature(p)
|
||||
dependencyCollector?.addDependency(p, signature)
|
||||
externalClassExtractor.extractLater(p, signature)
|
||||
}
|
||||
@@ -270,7 +283,7 @@ open class KotlinUsesExtractor(
|
||||
private fun extractFieldLaterIfExternalFileMember(f: IrField) {
|
||||
if (isExternalFileClassMember(f)) {
|
||||
extractExternalClassLater(f.parentAsClass)
|
||||
val signature = (f.correspondingPropertySymbol?.let { propertySignature(it.owner) } ?: "") + externalClassExtractor.fieldSignature
|
||||
val signature = getTrapFileSignature(f)
|
||||
dependencyCollector?.addDependency(f, signature)
|
||||
externalClassExtractor.extractLater(f, signature)
|
||||
}
|
||||
@@ -285,18 +298,7 @@ open class KotlinUsesExtractor(
|
||||
// getters and setters are extracted alongside it
|
||||
return
|
||||
}
|
||||
// Note we erase the parameter types before calling useType even though the signature should be the same
|
||||
// in order to prevent an infinite loop through useTypeParameter -> useDeclarationParent -> useFunction
|
||||
// -> extractFunctionLaterIfExternalFileMember, which would result for `fun <T> f(t: T) { ... }` for example.
|
||||
val ext = f.extensionReceiverParameter
|
||||
val parameters = if (ext != null) {
|
||||
listOf(ext) + f.valueParameters
|
||||
} else {
|
||||
f.valueParameters
|
||||
}
|
||||
|
||||
val paramSigs = parameters.map { useType(erase(it.type)).javaResult.signature }
|
||||
val signature = paramSigs.joinToString(separator = ",", prefix = "(", postfix = ")")
|
||||
val signature = getTrapFileSignature(f)
|
||||
dependencyCollector?.addDependency(f, signature)
|
||||
externalClassExtractor.extractLater(f, signature)
|
||||
}
|
||||
@@ -1647,7 +1649,7 @@ open class KotlinUsesExtractor(
|
||||
fun useValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>?): Label<out DbParam> =
|
||||
tw.getLabelFor(getValueParameterLabel(vp, parent))
|
||||
|
||||
private fun isDirectlyExposedCompanionObjectField(f: IrField) =
|
||||
private fun isDirectlyExposableCompanionObjectField(f: IrField) =
|
||||
f.hasAnnotation(FqName("kotlin.jvm.JvmField")) ||
|
||||
f.correspondingPropertySymbol?.owner?.let {
|
||||
it.isConst || it.isLateinit
|
||||
@@ -1655,12 +1657,14 @@ open class KotlinUsesExtractor(
|
||||
|
||||
fun getFieldParent(f: IrField) =
|
||||
f.parentClassOrNull?.let {
|
||||
if (it.isCompanion && isDirectlyExposedCompanionObjectField(f))
|
||||
if (it.isCompanion && isDirectlyExposableCompanionObjectField(f))
|
||||
it.parent
|
||||
else
|
||||
null
|
||||
} ?: f.parent
|
||||
|
||||
fun isDirectlyExposedCompanionObjectField(f: IrField) = getFieldParent(f) != f.parent
|
||||
|
||||
// Gets a field's corresponding property's extension receiver type, if any
|
||||
fun getExtensionReceiverType(f: IrField) =
|
||||
f.correspondingPropertySymbol?.owner?.let {
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
@@ -21,20 +22,46 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
// for `that`.
|
||||
private fun getName(d: IrDeclarationWithName) = (d as? IrAnnotationContainer)?.let { getJvmName(it) } ?: d.name.asString()
|
||||
|
||||
fun getIrDeclBinaryName(that: IrDeclaration): String {
|
||||
val shortName = when(that) {
|
||||
is IrDeclarationWithName -> getName(that)
|
||||
else -> "(unknown-name)"
|
||||
}
|
||||
val internalName = StringBuilder(shortName);
|
||||
generateSequence(that.parent) { (it as? IrDeclaration)?.parent }
|
||||
.forEach {
|
||||
when (it) {
|
||||
is IrClass -> internalName.insert(0, getName(it) + "$")
|
||||
is IrPackageFragment -> it.fqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
|
||||
}
|
||||
}
|
||||
return internalName.toString()
|
||||
@OptIn(ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
|
||||
fun getFileClassName(f: IrFile) =
|
||||
getJvmName(f) ?:
|
||||
((f.fileEntry.name.replaceFirst(Regex(""".*[/\\]"""), "")
|
||||
.replaceFirst(Regex("""\.kt$"""), "")
|
||||
.replaceFirstChar { it.uppercase() }) + "Kt")
|
||||
|
||||
fun getIrElementBinaryName(that: IrElement): String {
|
||||
if (that is IrFile) {
|
||||
val shortName = getFileClassName(that)
|
||||
val pkg = that.fqName.asString()
|
||||
return if (pkg.isEmpty()) shortName else "$pkg.$shortName"
|
||||
}
|
||||
|
||||
if (that !is IrDeclaration) {
|
||||
return "(unknown-name)"
|
||||
}
|
||||
|
||||
val shortName = when(that) {
|
||||
is IrDeclarationWithName -> getName(that)
|
||||
else -> "(unknown-name)"
|
||||
}
|
||||
|
||||
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 <: IrPackageFragment
|
||||
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.fqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
|
||||
}
|
||||
}
|
||||
return internalName.toString()
|
||||
}
|
||||
|
||||
fun getIrClassVirtualFile(irClass: IrClass): VirtualFile? {
|
||||
@@ -81,7 +108,7 @@ private fun getRawIrClassBinaryPath(irClass: IrClass) =
|
||||
fun getIrClassBinaryPath(irClass: IrClass): String {
|
||||
return getRawIrClassBinaryPath(irClass)
|
||||
// Otherwise, make up a fake location:
|
||||
?: "/!unknown-binary-location/${getIrDeclBinaryName(irClass).replace(".", "/")}.class"
|
||||
?: "/!unknown-binary-location/${getIrElementBinaryName(irClass).replace(".", "/")}.class"
|
||||
}
|
||||
|
||||
fun getContainingClassOrSelf(decl: IrDeclaration): IrClass? {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| J.java:1:14:1:14 | J |
|
||||
| build/J.class:0:0:0:0 | J<String> |
|
||||
| file:///!unknown-binary-location/J.class:0:0:0:0 | J<> |
|
||||
| file:///!unknown-binary-location/J.class:0:0:0:0 | J<Integer> |
|
||||
|
||||
@@ -16,9 +16,3 @@ class X {
|
||||
annotation class Ann(
|
||||
val p: Int,
|
||||
@get:JvmName("w") val q: Int)
|
||||
|
||||
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="changeY")
|
||||
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="getX_prop")
|
||||
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="method")
|
||||
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="y")
|
||||
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmName
|
||||
|
||||
@@ -110,6 +110,3 @@ public class TakesArrayList {
|
||||
fun inInArrayComparableAny(c: Comparable<Array<in Array<in Any>>>) { }
|
||||
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull
|
||||
|
||||
@@ -30,6 +30,3 @@ fun foo() {
|
||||
fun String.baz(p1: String): String { return "Baz" }
|
||||
"someString".baz("bazParam")
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull
|
||||
|
||||
@@ -5,7 +5,6 @@ classLocations
|
||||
| main.A<Object> | file:///!unknown-binary-location/main/A.class:0:0:0:0 | file:///!unknown-binary-location/main/A.class:0:0:0:0 |
|
||||
| main.A<String> | A.class:0:0:0:0 | A.class:0:0:0:0 |
|
||||
| main.A<String> | file:///!unknown-binary-location/main/A.class:0:0:0:0 | file:///!unknown-binary-location/main/A.class:0:0:0:0 |
|
||||
| main.B | generics-location.testproj/test.class.files/main/B.class:0:0:0:0 | generics-location.testproj/test.class.files/main/B.class:0:0:0:0 |
|
||||
| main.B | generics.kt:3:1:11:1 | generics.kt:3:1:11:1 |
|
||||
| main.B<Integer> | generics-location.testproj/test.class.files/main/B.class:0:0:0:0 | generics-location.testproj/test.class.files/main/B.class:0:0:0:0 |
|
||||
| main.B<Object> | file:///!unknown-binary-location/main/B.class:0:0:0:0 | file:///!unknown-binary-location/main/B.class:0:0:0:0 |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| TestClassA.kt:2:1:3:1 | TestClassA |
|
||||
| TestClassA.kt:2:1:3:1 | TestClassA<> |
|
||||
| TestClassAUser.kt:0:0:0:0 | TestClassAUserKt |
|
||||
| TestClassAUser.kt:15:1:15:24 | TestClassAUser |
|
||||
| file:///!unknown-binary-location/TestClassA.class:0:0:0:0 | TestClassA<TestClassAUser> |
|
||||
|
||||
@@ -11,9 +11,13 @@ public class Java {
|
||||
return super.fn0(x);
|
||||
}
|
||||
|
||||
/*
|
||||
// Java interop disabled as it currently doesn't work (no symbol fn1(int, Completion<...>) gets created)
|
||||
// TODO: re-enable this test once a correct function signature is extracted
|
||||
@Override
|
||||
public Object fn1(int x, Continuation<? super String> $completion) {
|
||||
return super.fn1(x, $completion);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,3 @@ class Dkotlin : Base() {
|
||||
override fun fn0(x: Int): String = super.fn0(x)
|
||||
override suspend fun fn1(x: Int): String = super.fn1(x)
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.Nullable
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.Nullable
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
methods
|
||||
| Java.java:4:7:4:13 | javaFun | javaFun() |
|
||||
| Java.java:10:17:10:19 | fn0 | fn0(int) |
|
||||
| Java.java:15:17:15:19 | fn1 | fn1(int,kotlin.coroutines.Continuation) |
|
||||
| Kotlin.kt:2:2:4:2 | kotlinFun | kotlinFun() |
|
||||
| Kotlin.kt:8:10:8:38 | fn0 | fn0(int) |
|
||||
| Kotlin.kt:9:18:9:46 | fn1 | fn1(int) |
|
||||
@@ -9,15 +8,12 @@ methods
|
||||
| Kotlin.kt:14:22:14:59 | fn1 | fn1(int) |
|
||||
overrides
|
||||
| Java.java:10:17:10:19 | fn0 | Kotlin.kt:8:10:8:38 | fn0 |
|
||||
| Java.java:15:17:15:19 | fn1 | java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 |
|
||||
| Kotlin.kt:13:14:13:51 | fn0 | Kotlin.kt:8:10:8:38 | fn0 |
|
||||
| Kotlin.kt:14:22:14:59 | fn1 | Kotlin.kt:9:18:9:46 | fn1 |
|
||||
signature_mismatch
|
||||
| Kotlin.kt:9:18:9:46 | fn1 | fn1(int) |
|
||||
| java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 | fn1(int,kotlin.coroutines.Continuation) |
|
||||
#select
|
||||
| Java.java:5:3:5:26 | kotlinFun(...) | Kotlin.kt:2:2:4:2 | kotlinFun |
|
||||
| Java.java:11:11:11:22 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 |
|
||||
| Java.java:16:11:16:35 | fn1(...) | java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 |
|
||||
| Kotlin.kt:13:40:13:51 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 |
|
||||
| Kotlin.kt:14:48:14:59 | fn1(...) | Kotlin.kt:9:18:9:46 | fn1 |
|
||||
|
||||
@@ -3,14 +3,10 @@ isInternal
|
||||
| Kotlin.kt:2:11:3:2 | kotlinFun$main |
|
||||
| Kotlin.kt:6:10:6:36 | topLevelKotlinFun |
|
||||
modifiers_methods
|
||||
| file://:0:0:0:0 | final | Kotlin.kt:2:11:3:2 | kotlinFun$main |
|
||||
| file://:0:0:0:0 | final | Kotlin.kt:6:10:6:36 | topLevelKotlinFun |
|
||||
| file://:0:0:0:0 | internal | Kotlin.kt:2:11:3:2 | kotlinFun$main |
|
||||
| file://:0:0:0:0 | internal | Kotlin.kt:6:10:6:36 | topLevelKotlinFun |
|
||||
| file://:0:0:0:0 | static | Kotlin.kt:6:10:6:36 | topLevelKotlinFun |
|
||||
#select
|
||||
| Kotlin.kt:2:11:3:2 | kotlinFun$main | final |
|
||||
| Kotlin.kt:2:11:3:2 | kotlinFun$main | internal |
|
||||
| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | final |
|
||||
| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | internal |
|
||||
| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | static |
|
||||
|
||||
@@ -85,12 +85,3 @@ public class TestDefaultParameterReference {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Completion failure for type: kotlin.jvm.JvmOverloads
|
||||
// Diagnostic Matches: Completion failure for type: kotlin.jvm.JvmStatic
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.Nullable
|
||||
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmOverloads
|
||||
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmStatic
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.Nullable
|
||||
|
||||
@@ -4,8 +4,3 @@ public class A {
|
||||
fun <T> genericFunctionWithOverloads(x: T? = null, y: List<T>? = null, z: T? = null): T? = z
|
||||
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: kotlin.jvm.JvmOverloads
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.Nullable
|
||||
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmOverloads
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.Nullable
|
||||
|
||||
@@ -141,11 +141,11 @@ test.kt:
|
||||
# 65| 0: [MethodAccess] getPropWithStaticGetter(...)
|
||||
# 65| -1: [TypeAccess] NonCompanion
|
||||
# 9| 2: [Class] HasCompanion
|
||||
# 9| 2: [Constructor] HasCompanion
|
||||
# 9| 1: [Constructor] HasCompanion
|
||||
# 9| 5: [BlockStmt] { ... }
|
||||
# 9| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 9| 1: [BlockStmt] { ... }
|
||||
# 11| 3: [Class] Companion
|
||||
# 11| 2: [Class] Companion
|
||||
# 11| 1: [Constructor] Companion
|
||||
# 11| 5: [BlockStmt] { ... }
|
||||
# 11| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
@@ -157,11 +157,9 @@ test.kt:
|
||||
# 17| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 17| 0: [VarAccess] nonStaticProp
|
||||
# 13| 2: [Method] staticMethod
|
||||
#-----| 1: (Annotations)
|
||||
# 13| 3: [TypeAccess] String
|
||||
#-----| 4: (Parameters)
|
||||
# 13| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 13| 0: [TypeAccess] String
|
||||
# 13| 5: [BlockStmt] { ... }
|
||||
# 13| 0: [ReturnStmt] return ...
|
||||
@@ -169,11 +167,9 @@ test.kt:
|
||||
# 13| -1: [ThisAccess] this
|
||||
# 13| 0: [VarAccess] s
|
||||
# 14| 3: [Method] nonStaticMethod
|
||||
#-----| 1: (Annotations)
|
||||
# 14| 3: [TypeAccess] String
|
||||
#-----| 4: (Parameters)
|
||||
# 14| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 14| 0: [TypeAccess] String
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [ReturnStmt] return ...
|
||||
@@ -184,7 +180,6 @@ test.kt:
|
||||
# 16| -1: [TypeAccess] String
|
||||
# 16| 0: [StringLiteral] "a"
|
||||
# 16| 5: [Method] getStaticProp
|
||||
#-----| 1: (Annotations)
|
||||
# 16| 3: [TypeAccess] String
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ReturnStmt] return ...
|
||||
@@ -194,7 +189,6 @@ test.kt:
|
||||
# 16| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 16| 0: [Parameter] <set-?>
|
||||
#-----| -1: (Annotations)
|
||||
# 16| 0: [TypeAccess] String
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ExprStmt] <Expr>;
|
||||
@@ -206,7 +200,6 @@ test.kt:
|
||||
# 17| -1: [TypeAccess] String
|
||||
# 17| 0: [StringLiteral] "b"
|
||||
# 17| 8: [Method] getNonStaticProp
|
||||
#-----| 1: (Annotations)
|
||||
# 17| 3: [TypeAccess] String
|
||||
# 17| 5: [BlockStmt] { ... }
|
||||
# 17| 0: [ReturnStmt] return ...
|
||||
@@ -216,7 +209,6 @@ test.kt:
|
||||
# 17| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 17| 0: [Parameter] <set-?>
|
||||
#-----| -1: (Annotations)
|
||||
# 17| 0: [TypeAccess] String
|
||||
# 17| 5: [BlockStmt] { ... }
|
||||
# 17| 0: [ExprStmt] <Expr>;
|
||||
@@ -225,7 +217,6 @@ test.kt:
|
||||
# 17| -1: [ThisAccess] this
|
||||
# 17| 1: [VarAccess] <set-?>
|
||||
# 20| 10: [Method] getPropWithStaticGetter
|
||||
#-----| 1: (Annotations)
|
||||
# 20| 3: [TypeAccess] String
|
||||
# 20| 5: [BlockStmt] { ... }
|
||||
# 20| 0: [ReturnStmt] return ...
|
||||
@@ -235,7 +226,6 @@ test.kt:
|
||||
# 21| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 21| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 21| 0: [TypeAccess] String
|
||||
# 21| 5: [BlockStmt] { ... }
|
||||
# 21| 0: [ExprStmt] <Expr>;
|
||||
@@ -243,30 +233,25 @@ test.kt:
|
||||
# 21| -1: [ThisAccess] this
|
||||
# 21| 0: [VarAccess] s
|
||||
# 24| 12: [Method] getPropWithStaticSetter
|
||||
#-----| 1: (Annotations)
|
||||
# 24| 3: [TypeAccess] String
|
||||
# 24| 5: [BlockStmt] { ... }
|
||||
# 24| 0: [ReturnStmt] return ...
|
||||
# 24| 0: [MethodAccess] getPropWithStaticGetter(...)
|
||||
# 24| -1: [ThisAccess] this
|
||||
# 25| 13: [Method] setPropWithStaticSetter
|
||||
#-----| 1: (Annotations)
|
||||
# 25| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 25| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 25| 0: [TypeAccess] String
|
||||
# 25| 5: [BlockStmt] { ... }
|
||||
# 25| 0: [ExprStmt] <Expr>;
|
||||
# 25| 0: [MethodAccess] setPropWithStaticGetter(...)
|
||||
# 25| -1: [ThisAccess] this
|
||||
# 25| 0: [VarAccess] s
|
||||
# 13| 4: [Method] staticMethod
|
||||
#-----| 1: (Annotations)
|
||||
# 13| 3: [Method] staticMethod
|
||||
# 13| 3: [TypeAccess] String
|
||||
#-----| 4: (Parameters)
|
||||
# 13| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 13| 0: [TypeAccess] String
|
||||
# 13| 5: [BlockStmt] { ... }
|
||||
# 13| 0: [ReturnStmt] return ...
|
||||
@@ -274,19 +259,17 @@ test.kt:
|
||||
# 13| -1: [VarAccess] HasCompanion.Companion
|
||||
# 13| -1: [TypeAccess] HasCompanion
|
||||
# 13| 0: [VarAccess] s
|
||||
# 16| 5: [Method] getStaticProp
|
||||
#-----| 1: (Annotations)
|
||||
# 16| 4: [Method] getStaticProp
|
||||
# 16| 3: [TypeAccess] String
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ReturnStmt] return ...
|
||||
# 16| 0: [MethodAccess] getStaticProp(...)
|
||||
# 16| -1: [VarAccess] HasCompanion.Companion
|
||||
# 16| -1: [TypeAccess] HasCompanion
|
||||
# 16| 6: [Method] setStaticProp
|
||||
# 16| 5: [Method] setStaticProp
|
||||
# 16| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 16| 0: [Parameter] <set-?>
|
||||
#-----| -1: (Annotations)
|
||||
# 16| 0: [TypeAccess] String
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ReturnStmt] return ...
|
||||
@@ -294,20 +277,17 @@ test.kt:
|
||||
# 16| -1: [VarAccess] HasCompanion.Companion
|
||||
# 16| -1: [TypeAccess] HasCompanion
|
||||
# 16| 0: [VarAccess] <set-?>
|
||||
# 20| 7: [Method] getPropWithStaticGetter
|
||||
#-----| 1: (Annotations)
|
||||
# 20| 6: [Method] getPropWithStaticGetter
|
||||
# 20| 3: [TypeAccess] String
|
||||
# 20| 5: [BlockStmt] { ... }
|
||||
# 20| 0: [ReturnStmt] return ...
|
||||
# 20| 0: [MethodAccess] getPropWithStaticGetter(...)
|
||||
# 20| -1: [VarAccess] HasCompanion.Companion
|
||||
# 20| -1: [TypeAccess] HasCompanion
|
||||
# 25| 8: [Method] setPropWithStaticSetter
|
||||
#-----| 1: (Annotations)
|
||||
# 25| 7: [Method] setPropWithStaticSetter
|
||||
# 25| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 25| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 25| 0: [TypeAccess] String
|
||||
# 25| 5: [BlockStmt] { ... }
|
||||
# 25| 0: [ReturnStmt] return ...
|
||||
@@ -316,7 +296,7 @@ test.kt:
|
||||
# 25| -1: [TypeAccess] HasCompanion
|
||||
# 25| 0: [VarAccess] s
|
||||
# 31| 3: [Class] NonCompanion
|
||||
# 31| 2: [Constructor] NonCompanion
|
||||
# 31| 1: [Constructor] NonCompanion
|
||||
# 31| 5: [BlockStmt] { ... }
|
||||
# 31| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 31| 1: [BlockStmt] { ... }
|
||||
@@ -326,12 +306,10 @@ test.kt:
|
||||
# 37| 1: [ExprStmt] <Expr>;
|
||||
# 37| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 37| 0: [VarAccess] nonStaticProp
|
||||
# 33| 3: [Method] staticMethod
|
||||
#-----| 1: (Annotations)
|
||||
# 33| 2: [Method] staticMethod
|
||||
# 33| 3: [TypeAccess] String
|
||||
#-----| 4: (Parameters)
|
||||
# 33| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 33| 0: [TypeAccess] String
|
||||
# 33| 5: [BlockStmt] { ... }
|
||||
# 33| 0: [ReturnStmt] return ...
|
||||
@@ -339,34 +317,30 @@ test.kt:
|
||||
# 33| -1: [VarAccess] NonCompanion.INSTANCE
|
||||
# 33| -1: [TypeAccess] NonCompanion
|
||||
# 33| 0: [VarAccess] s
|
||||
# 34| 4: [Method] nonStaticMethod
|
||||
#-----| 1: (Annotations)
|
||||
# 34| 3: [Method] nonStaticMethod
|
||||
# 34| 3: [TypeAccess] String
|
||||
#-----| 4: (Parameters)
|
||||
# 34| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 34| 0: [TypeAccess] String
|
||||
# 34| 5: [BlockStmt] { ... }
|
||||
# 34| 0: [ReturnStmt] return ...
|
||||
# 34| 0: [MethodAccess] staticMethod(...)
|
||||
# 34| -1: [TypeAccess] NonCompanion
|
||||
# 34| 0: [VarAccess] s
|
||||
# 36| 5: [FieldDeclaration] String staticProp;
|
||||
# 36| 4: [FieldDeclaration] String staticProp;
|
||||
# 36| -1: [TypeAccess] String
|
||||
# 36| 0: [StringLiteral] "a"
|
||||
# 36| 6: [Method] getStaticProp
|
||||
#-----| 1: (Annotations)
|
||||
# 36| 5: [Method] getStaticProp
|
||||
# 36| 3: [TypeAccess] String
|
||||
# 36| 5: [BlockStmt] { ... }
|
||||
# 36| 0: [ReturnStmt] return ...
|
||||
# 36| 0: [VarAccess] NonCompanion.INSTANCE.staticProp
|
||||
# 36| -1: [VarAccess] NonCompanion.INSTANCE
|
||||
# 36| -1: [TypeAccess] NonCompanion
|
||||
# 36| 7: [Method] setStaticProp
|
||||
# 36| 6: [Method] setStaticProp
|
||||
# 36| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 36| 0: [Parameter] <set-?>
|
||||
#-----| -1: (Annotations)
|
||||
# 36| 0: [TypeAccess] String
|
||||
# 36| 5: [BlockStmt] { ... }
|
||||
# 36| 0: [ExprStmt] <Expr>;
|
||||
@@ -375,21 +349,19 @@ test.kt:
|
||||
# 36| -1: [VarAccess] NonCompanion.INSTANCE
|
||||
# 36| -1: [TypeAccess] NonCompanion
|
||||
# 36| 1: [VarAccess] <set-?>
|
||||
# 37| 8: [FieldDeclaration] String nonStaticProp;
|
||||
# 37| 7: [FieldDeclaration] String nonStaticProp;
|
||||
# 37| -1: [TypeAccess] String
|
||||
# 37| 0: [StringLiteral] "b"
|
||||
# 37| 9: [Method] getNonStaticProp
|
||||
#-----| 1: (Annotations)
|
||||
# 37| 8: [Method] getNonStaticProp
|
||||
# 37| 3: [TypeAccess] String
|
||||
# 37| 5: [BlockStmt] { ... }
|
||||
# 37| 0: [ReturnStmt] return ...
|
||||
# 37| 0: [VarAccess] this.nonStaticProp
|
||||
# 37| -1: [ThisAccess] this
|
||||
# 37| 10: [Method] setNonStaticProp
|
||||
# 37| 9: [Method] setNonStaticProp
|
||||
# 37| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 37| 0: [Parameter] <set-?>
|
||||
#-----| -1: (Annotations)
|
||||
# 37| 0: [TypeAccess] String
|
||||
# 37| 5: [BlockStmt] { ... }
|
||||
# 37| 0: [ExprStmt] <Expr>;
|
||||
@@ -397,38 +369,33 @@ test.kt:
|
||||
# 37| 0: [VarAccess] this.nonStaticProp
|
||||
# 37| -1: [ThisAccess] this
|
||||
# 37| 1: [VarAccess] <set-?>
|
||||
# 40| 11: [Method] getPropWithStaticGetter
|
||||
#-----| 1: (Annotations)
|
||||
# 40| 10: [Method] getPropWithStaticGetter
|
||||
# 40| 3: [TypeAccess] String
|
||||
# 40| 5: [BlockStmt] { ... }
|
||||
# 40| 0: [ReturnStmt] return ...
|
||||
# 40| 0: [MethodAccess] getPropWithStaticSetter(...)
|
||||
# 40| -1: [VarAccess] NonCompanion.INSTANCE
|
||||
# 40| -1: [TypeAccess] NonCompanion
|
||||
# 41| 12: [Method] setPropWithStaticGetter
|
||||
# 41| 11: [Method] setPropWithStaticGetter
|
||||
# 41| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 41| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 41| 0: [TypeAccess] String
|
||||
# 41| 5: [BlockStmt] { ... }
|
||||
# 41| 0: [ExprStmt] <Expr>;
|
||||
# 41| 0: [MethodAccess] setPropWithStaticSetter(...)
|
||||
# 41| -1: [TypeAccess] NonCompanion
|
||||
# 41| 0: [VarAccess] s
|
||||
# 44| 13: [Method] getPropWithStaticSetter
|
||||
#-----| 1: (Annotations)
|
||||
# 44| 12: [Method] getPropWithStaticSetter
|
||||
# 44| 3: [TypeAccess] String
|
||||
# 44| 5: [BlockStmt] { ... }
|
||||
# 44| 0: [ReturnStmt] return ...
|
||||
# 44| 0: [MethodAccess] getPropWithStaticGetter(...)
|
||||
# 44| -1: [TypeAccess] NonCompanion
|
||||
# 45| 14: [Method] setPropWithStaticSetter
|
||||
#-----| 1: (Annotations)
|
||||
# 45| 13: [Method] setPropWithStaticSetter
|
||||
# 45| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 45| 0: [Parameter] s
|
||||
#-----| -1: (Annotations)
|
||||
# 45| 0: [TypeAccess] String
|
||||
# 45| 5: [BlockStmt] { ... }
|
||||
# 45| 0: [ExprStmt] <Expr>;
|
||||
|
||||
@@ -65,8 +65,3 @@ fun externalUser() {
|
||||
NonCompanion.propWithStaticSetter = NonCompanion.propWithStaticGetter
|
||||
|
||||
}
|
||||
|
||||
// Diagnostic Matches: Completion failure for type: kotlin.jvm.JvmStatic
|
||||
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
|
||||
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmStatic
|
||||
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull
|
||||
|
||||
Reference in New Issue
Block a user