JVM_IR: fix source file name for mutlifile class facades
This commit is contained in:
@@ -726,7 +726,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
public SourceMapper getOrCreateSourceMapper() {
|
public SourceMapper getOrCreateSourceMapper() {
|
||||||
if (sourceMapper == null) {
|
if (sourceMapper == null) {
|
||||||
// note: this is used in InlineCodegen and the element is always physical (KtElement) there
|
// note: this is used in InlineCodegen and the element is always physical (KtElement) there
|
||||||
sourceMapper = new SourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
|
sourceMapper = new SourceMapper(SourceInfo.Companion.createFromPsi((KtElement)element, getClassName()));
|
||||||
}
|
}
|
||||||
return sourceMapper;
|
return sourceMapper;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,28 +21,26 @@ import org.jetbrains.kotlin.psi.KtElement
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
|
||||||
data class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesInFile: Int) {
|
data class SourceInfo(
|
||||||
|
val sourceFileName: String?,
|
||||||
|
val pathOrCleanFQN: String,
|
||||||
|
val linesInFile: Int
|
||||||
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
fun createFromPsi(element: KtElement?, internalClassName: String): SourceInfo {
|
||||||
assert(element != null) { "Couldn't create source mapper for null element $internalClassName" }
|
assert(element != null) { "Couldn't create source mapper for null element $internalClassName" }
|
||||||
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
||||||
?: error("Couldn't extract line count in ${element.containingFile}")
|
?: error("Couldn't extract line count in ${element.containingFile}")
|
||||||
|
|
||||||
//TODO hack condition for package parts cleaning
|
//TODO hack condition for package parts cleaning
|
||||||
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||||
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||||
|
|
||||||
return SourceInfo(element.containingKtFile.name, cleanedClassFqName, lineNumbers)
|
val fileName = element.containingKtFile.name
|
||||||
|
return SourceInfo(fileName, cleanedClassFqName, lineNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createInfoForIr(lineNumbers: Int, internalClassName: String, containingFileName: String): SourceInfo {
|
|
||||||
//TODO cut topLevel names
|
|
||||||
// val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
|
||||||
// val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
|
||||||
|
|
||||||
return SourceInfo(containingFileName, internalClassName, lineNumbers)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.incremental.components.Position
|
import org.jetbrains.kotlin.incremental.components.Position
|
||||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -28,10 +27,8 @@ import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
@@ -233,7 +230,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val sourceInfo = sourceMapper.sourceInfo!!
|
val sourceInfo = sourceMapper.sourceInfo!!
|
||||||
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.source, sourceInfo.pathOrCleanFQN)
|
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.sourceFileName!!, sourceInfo.pathOrCleanFQN)
|
||||||
val inliner = MethodInliner(
|
val inliner = MethodInliner(
|
||||||
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
|
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
|
||||||
"Method inlining " + sourceCompiler.callElementText,
|
"Method inlining " + sourceCompiler.callElementText,
|
||||||
|
|||||||
@@ -85,9 +85,14 @@ class SourceMapper(val sourceInfo: SourceInfo?) {
|
|||||||
get() = fileMappings.values.toList()
|
get() = fileMappings.values.toList()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sourceInfo?.let {
|
sourceInfo?.let { sourceInfo ->
|
||||||
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges.
|
// If 'sourceFileName' is null, this class doesn't have debug information
|
||||||
getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile)
|
// (e.g., multi-file class facade with multiple parts).
|
||||||
|
sourceInfo.sourceFileName?.let { sourceFileName ->
|
||||||
|
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges.
|
||||||
|
getOrRegisterNewSource(sourceFileName, sourceInfo.pathOrCleanFQN)
|
||||||
|
.mapNewInterval(1, 1, sourceInfo.linesInFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -153,7 +153,9 @@ abstract class ClassCodegen protected constructor(
|
|||||||
if (withinInline || !smap.isTrivial) {
|
if (withinInline || !smap.isTrivial) {
|
||||||
visitor.visitSMAP(smap, !context.state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
|
visitor.visitSMAP(smap, !context.state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
|
||||||
} else {
|
} else {
|
||||||
visitor.visitSource(smap.sourceInfo!!.source, null)
|
smap.sourceInfo!!.sourceFileName?.let {
|
||||||
|
visitor.visitSource(it, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.done()
|
visitor.done()
|
||||||
|
|||||||
+9
-5
@@ -87,15 +87,19 @@ fun JvmBackendContext.getSourceMapper(declaration: IrClass): SourceMapper {
|
|||||||
// NOTE: apparently inliner requires the source range to cover the
|
// NOTE: apparently inliner requires the source range to cover the
|
||||||
// whole file the class is declared in rather than the class only.
|
// whole file the class is declared in rather than the class only.
|
||||||
// TODO: revise
|
// TODO: revise
|
||||||
val endLineNumber = when {
|
val endLineNumber = when (fileEntry) {
|
||||||
fileEntry is MultifileFacadeFileEntry -> 0
|
is MultifileFacadeFileEntry -> 0
|
||||||
else -> fileEntry?.getSourceRangeInfo(0, fileEntry.maxOffset)?.endLineNumber ?: 0
|
else -> fileEntry?.getSourceRangeInfo(0, fileEntry.maxOffset)?.endLineNumber ?: 0
|
||||||
}
|
}
|
||||||
|
val sourceFileName = when (fileEntry) {
|
||||||
|
is MultifileFacadeFileEntry -> fileEntry.partFiles.singleOrNull()?.name
|
||||||
|
else -> declaration.fileParent.name
|
||||||
|
}
|
||||||
return SourceMapper(
|
return SourceMapper(
|
||||||
SourceInfo.createInfoForIr(
|
SourceInfo(
|
||||||
endLineNumber + 1,
|
sourceFileName,
|
||||||
typeMapper.mapClass(declaration).internalName,
|
typeMapper.mapClass(declaration).internalName,
|
||||||
declaration.fileParent.name
|
endLineNumber + 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class Hello/Foo {
|
public final class Hello/Foo {
|
||||||
// source: 'Foo>'
|
// source: 'multifileSuspend.kt'
|
||||||
public final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void
|
public final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void
|
||||||
public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: part1.kt
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
@file:JvmName("MultiFileClass")
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
|
||||||
|
// FILE: part2.kt
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
@file:JvmName("MultiFileClass")
|
||||||
|
|
||||||
|
fun bar() {}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiFileClass {
|
||||||
|
public final static method bar(): void
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class MultiFileClass__Part1Kt {
|
||||||
|
// source: 'part1.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class MultiFileClass__Part2Kt {
|
||||||
|
// source: 'part2.kt'
|
||||||
|
public final static method bar(): void
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiFileClass {
|
||||||
|
public final static method bar(): void
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.JvmName
|
||||||
|
synthetic final class MultiFileClass__Part1Kt {
|
||||||
|
// source: 'part1.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.JvmName
|
||||||
|
synthetic final class MultiFileClass__Part2Kt {
|
||||||
|
// source: 'part2.kt'
|
||||||
|
public final static method bar(): void
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
@file:JvmName("MultiFileClass")
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiFileClass {
|
||||||
|
// source: 'multiClassPartSourceSinglePart.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class MultiFileClass__MultiClassPartSourceSinglePartKt {
|
||||||
|
// source: 'multiClassPartSourceSinglePart.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiFileClass {
|
||||||
|
// source: 'multiClassPartSourceSinglePart.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.JvmName
|
||||||
|
synthetic final class MultiFileClass__MultiClassPartSourceSinglePartKt {
|
||||||
|
// source: 'multiClassPartSourceSinglePart.kt'
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
+10
@@ -104,6 +104,16 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multiClassPartSourceMultipleParts.kt")
|
||||||
|
public void testMultiClassPartSourceMultipleParts() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/multiClassPartSourceMultipleParts.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multiClassPartSourceSinglePart.kt")
|
||||||
|
public void testMultiClassPartSourceSinglePart() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/multiClassPartSourceSinglePart.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
||||||
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
||||||
|
|||||||
+10
@@ -104,6 +104,16 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multiClassPartSourceMultipleParts.kt")
|
||||||
|
public void testMultiClassPartSourceMultipleParts() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/multiClassPartSourceMultipleParts.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multiClassPartSourceSinglePart.kt")
|
||||||
|
public void testMultiClassPartSourceSinglePart() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/multiClassPartSourceSinglePart.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
||||||
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user