Old SourceMappers replaced with new ones
This commit is contained in:
@@ -24,8 +24,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.inline.*;
|
import org.jetbrains.kotlin.codegen.inline.*;
|
||||||
import org.jetbrains.kotlin.codegen.inline2.*;
|
|
||||||
import org.jetbrains.kotlin.codegen.inline2.DefaultSourceMapper;
|
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
|||||||
@@ -27,9 +27,6 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
|||||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
|
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.inline2.*;
|
|
||||||
import org.jetbrains.kotlin.codegen.inline2.DefaultSourceMapper;
|
|
||||||
import org.jetbrains.kotlin.codegen.inline2.NestedSourceMapper;
|
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.codegen.ClosureCodegen;
|
import org.jetbrains.kotlin.codegen.ClosureCodegen;
|
||||||
import org.jetbrains.kotlin.codegen.StackValue;
|
import org.jetbrains.kotlin.codegen.StackValue;
|
||||||
import org.jetbrains.kotlin.codegen.inline2.*;
|
|
||||||
import org.jetbrains.kotlin.codegen.inline2.InlineLambdaSourceMapper;
|
|
||||||
import org.jetbrains.kotlin.codegen.inline2.NestedSourceMapper;
|
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||||
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer;
|
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
import gnu.trove.TIntIntHashMap
|
import gnu.trove.TIntIntHashMap
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
import org.jetbrains.kotlin.codegen.SourceInfo
|
||||||
import org.jetbrains.kotlin.codegen.inline2.CallSiteMarker
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -86,58 +85,56 @@ class SMAPBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class NestedSourceMapper(
|
open class NestedSourceMapper(
|
||||||
parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
|
override val parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
|
||||||
) : DefaultSourceMapper(sourceInfo, parent) {
|
) : DefaultSourceMapper(sourceInfo) {
|
||||||
|
|
||||||
|
val visitedLines = TIntIntHashMap()
|
||||||
|
|
||||||
|
var lastVisitedRange: RangeMapping? = null
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
||||||
|
val mappedLineNumber = visitedLines.get(lineNumber)
|
||||||
|
|
||||||
|
if (mappedLineNumber > 0) {
|
||||||
|
iv.visitLineNumber(mappedLineNumber, start)
|
||||||
|
} else {
|
||||||
|
val rangeForMapping = if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber)!!
|
||||||
|
val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber)
|
||||||
|
val visitLineNumber = parent.visitLineNumber(iv, start, sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path)
|
||||||
|
if (visitLineNumber > 0) {
|
||||||
|
visitedLines.put(lineNumber, visitLineNumber)
|
||||||
|
}
|
||||||
|
lastVisitedRange = rangeForMapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findMappingIfExists(lineNumber: Int): RangeMapping? {
|
||||||
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
||||||
value, key ->
|
value, key ->
|
||||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
||||||
})
|
})
|
||||||
if (index < 0) {
|
return if (index < 0) null else ranges[index];
|
||||||
parent!!.visitSource(sourceInfo.source, sourceInfo.pathOrCleanFQN)
|
|
||||||
parent!!.visitLineNumber(iv, lineNumber, start)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val rangeMapping = ranges[index]
|
|
||||||
parent!!.visitSource(rangeMapping.parent!!.name, rangeMapping.parent!!.path)
|
|
||||||
parent!!.visitLineNumber(iv, rangeMapping.mapDestToSource(lineNumber), start)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class InlineLambdaSourceMapper(
|
open class InlineLambdaSourceMapper(
|
||||||
parent: SourceMapper, smap: SMAPAndMethodNode
|
parent: SourceMapper, smap: SMAPAndMethodNode
|
||||||
) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
||||||
override fun visitSource(name: String, path: String) {
|
|
||||||
super.visitSource(name, path)
|
init {
|
||||||
if (isOriginalVisited()) {
|
assert(smap.ranges.isNotEmpty()) {
|
||||||
parent!!.visitOrigin()
|
"Mapping ranges should be presented in inline lambda: ${smap.node}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitOrigin() {
|
|
||||||
super.visitOrigin()
|
|
||||||
parent!!.visitOrigin()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isOriginalVisited(): Boolean {
|
|
||||||
return lastVisited == origin
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
||||||
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
if (ranges.firstOrNull()?.contains(lineNumber) ?: false) {
|
||||||
value, key ->
|
//don't remap origin lambda line numbers
|
||||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
iv.visitLineNumber(lineNumber, start)
|
||||||
})
|
}
|
||||||
if (index >= 0) {
|
else {
|
||||||
val mapping = ranges[index].parent!!
|
super.visitLineNumber(iv, lineNumber, start)
|
||||||
if (mapping.path == origin.path && mapping.name == origin.name) {
|
|
||||||
parent!!.visitOrigin()
|
|
||||||
parent!!.visitLineNumber(iv, lineNumber, start)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.visitLineNumber(iv, lineNumber, start)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +170,7 @@ interface SourceMapper {
|
|||||||
|
|
||||||
fun createFromSmap(smap: SMAP): SourceMapper {
|
fun createFromSmap(smap: SMAP): SourceMapper {
|
||||||
val maxUsedIndex = smap.fileMappings.maxBy { it.lineMappings.maxBy { it.maxDest }!!.maxDest }!!.lineMappings.maxBy { it.maxDest }!!.maxDest
|
val maxUsedIndex = smap.fileMappings.maxBy { it.lineMappings.maxBy { it.maxDest }!!.maxDest }!!.lineMappings.maxBy { it.maxDest }!!.maxDest
|
||||||
val sourceMapper = org.jetbrains.kotlin.codegen.inline2.DefaultSourceMapper(smap.sourceInfo, maxUsedIndex)
|
val sourceMapper = DefaultSourceMapper(smap.sourceInfo, maxUsedIndex)
|
||||||
smap.fileMappings.asSequence()
|
smap.fileMappings.asSequence()
|
||||||
//default one mapped through sourceInfo
|
//default one mapped through sourceInfo
|
||||||
.filterNot { it == smap.default }
|
.filterNot { it == smap.default }
|
||||||
@@ -205,8 +202,19 @@ object IdenticalSourceMapper : SourceMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper {
|
class CallSiteMarker(val lineNumber: Int)
|
||||||
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
|
||||||
|
open class DefaultSourceMapper @JvmOverloads constructor(
|
||||||
|
val sourceInfo: SourceInfo,
|
||||||
|
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
||||||
|
) : SourceMapper {
|
||||||
|
|
||||||
|
var callSiteMarker: CallSiteMarker? = null;
|
||||||
|
set(value) {
|
||||||
|
lastMappedWithChanges = null
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
var lastVisited: RawFileMapping? = null
|
var lastVisited: RawFileMapping? = null
|
||||||
private var lastMappedWithChanges: RawFileMapping? = null
|
private var lastMappedWithChanges: RawFileMapping? = null
|
||||||
private var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
|
private var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
|
||||||
@@ -216,7 +224,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
|
|||||||
val name = sourceInfo.source
|
val name = sourceInfo.source
|
||||||
val path = sourceInfo.pathOrCleanFQN
|
val path = sourceInfo.pathOrCleanFQN
|
||||||
origin = RawFileMapping(name, path)
|
origin = RawFileMapping(name, path)
|
||||||
origin.initRange(1, maxUsedValue)
|
origin.initRange(1, sourceInfo.linesInFile)
|
||||||
fileMappings.put(createKey(name, path), origin)
|
fileMappings.put(createKey(name, path), origin)
|
||||||
lastVisited = origin
|
lastVisited = origin
|
||||||
}
|
}
|
||||||
@@ -239,13 +247,28 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
|
|||||||
//no source information, so just skip this linenumber
|
//no source information, so just skip this linenumber
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val mappedLineIndex = createMapping(lineNumber)
|
//TODO add assertion that mapping exists
|
||||||
|
//val sourceLineNumber = createMapping(lineNumberToMap)
|
||||||
|
val sourceLineNumber = lineNumber
|
||||||
|
assert(lineNumber == sourceLineNumber)
|
||||||
|
iv.visitLineNumber(lineNumber, start)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLineNumber(iv: MethodVisitor, start: Label, source: Int, sourceName: String, sourcePath: String): Int {
|
||||||
|
if (source < 0) {
|
||||||
|
//no source information, so just skip this linenumber
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
visitSource(sourceName, sourcePath)
|
||||||
|
val mappedLineIndex = createMapping(source)
|
||||||
iv.visitLineNumber(mappedLineIndex, start)
|
iv.visitLineNumber(mappedLineIndex, start)
|
||||||
|
return mappedLineIndex
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun createMapping(lineNumber: Int): Int {
|
protected fun createMapping(lineNumber: Int): Int {
|
||||||
val fileMapping = lastVisited!!
|
val fileMapping = lastVisited!!
|
||||||
val mappedLineIndex = fileMapping.mapLine(lineNumber, maxUsedValue, lastMappedWithChanges == lastVisited)
|
val mappedLineIndex = fileMapping.mapNewLineNumber(lineNumber, maxUsedValue, lastMappedWithChanges == lastVisited, callSiteMarker)
|
||||||
if (mappedLineIndex > maxUsedValue) {
|
if (mappedLineIndex > maxUsedValue) {
|
||||||
lastMappedWithChanges = fileMapping
|
lastMappedWithChanges = fileMapping
|
||||||
maxUsedValue = mappedLineIndex
|
maxUsedValue = mappedLineIndex
|
||||||
@@ -277,8 +300,8 @@ class SMAP(val fileMappings: List<FileMapping>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RawFileMapping(val name: String, val path: String) {
|
class RawFileMapping(val name: String, val path: String) {
|
||||||
private val lineMappings = TIntIntHashMap()
|
|
||||||
private val rangeMappings = arrayListOf<RangeMapping>()
|
private val rangeMappings = arrayListOf<RangeMapping>()
|
||||||
|
|
||||||
private var lastMappedWithNewIndex = -1000
|
private var lastMappedWithNewIndex = -1000
|
||||||
@@ -291,43 +314,32 @@ class RawFileMapping(val name: String, val path: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun initRange(start: Int, end: Int) {
|
fun initRange(start: Int, end: Int) {
|
||||||
assert(lineMappings.isEmpty) { "initRange should only be called for empty mapping" }
|
assert(rangeMappings.isEmpty()) { "initRange should only be called for empty mapping" }
|
||||||
for (index in start..end) {
|
|
||||||
lineMappings.put(index, index)
|
|
||||||
}
|
|
||||||
rangeMappings.add(RangeMapping(start, start, end - start + 1))
|
rangeMappings.add(RangeMapping(start, start, end - start + 1))
|
||||||
lastMappedWithNewIndex = end
|
lastMappedWithNewIndex = end
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mapLine(source: Int, currentIndex: Int, isLastMapped: Boolean): Int {
|
fun mapNewLineNumber(source: Int, currentIndex: Int, isLastMapped: Boolean, callSiteMarker: CallSiteMarker?): Int {
|
||||||
var dest = lineMappings[source]
|
val dest: Int
|
||||||
if (dest == 0) { // line numbers are 1-based, so 0 is ok to indicate missing value
|
val rangeMapping: RangeMapping
|
||||||
val rangeMapping: RangeMapping
|
if (rangeMappings.isNotEmpty() && isLastMapped && couldFoldInRange(lastMappedWithNewIndex, source)) {
|
||||||
if (rangeMappings.isNotEmpty() && isLastMapped && couldFoldInRange(lastMappedWithNewIndex, source)) {
|
rangeMapping = rangeMappings.last()
|
||||||
rangeMapping = rangeMappings.last()
|
rangeMapping.range += source - lastMappedWithNewIndex
|
||||||
rangeMapping.range += source - lastMappedWithNewIndex
|
dest = rangeMapping.mapSourceToDest(source)
|
||||||
dest = lineMappings[lastMappedWithNewIndex] + source - lastMappedWithNewIndex
|
}
|
||||||
}
|
else {
|
||||||
else {
|
dest = currentIndex + 1
|
||||||
dest = currentIndex + 1
|
rangeMapping = RangeMapping(source, dest, callSiteMarker = callSiteMarker)
|
||||||
rangeMapping = RangeMapping(source, dest)
|
rangeMappings.add(rangeMapping)
|
||||||
rangeMappings.add(rangeMapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
lineMappings.put(source, dest)
|
|
||||||
lastMappedWithNewIndex = source
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastMappedWithNewIndex = source
|
||||||
return dest
|
return dest
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mapNewInterval(source: Int, dest: Int, range: Int) {
|
fun mapNewInterval(source: Int, dest: Int, range: Int) {
|
||||||
val rangeMapping = RangeMapping(source, dest, range)
|
val rangeMapping = RangeMapping(source, dest, range)
|
||||||
rangeMappings.add(rangeMapping)
|
rangeMappings.add(rangeMapping)
|
||||||
|
|
||||||
(source..(source + range - 1)).forEach {
|
|
||||||
lineMappings.put(source, dest)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun couldFoldInRange(first: Int, second: Int): Boolean {
|
private fun couldFoldInRange(first: Int, second: Int): Boolean {
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline2
|
|
||||||
|
|
||||||
import gnu.trove.TIntIntHashMap
|
|
||||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.FileMapping
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.RangeMapping
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.SMAPAndMethodNode
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class CallSiteMarker(val lineNumber: Int)
|
|
||||||
|
|
||||||
open class NestedSourceMapper(
|
|
||||||
override val parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
|
|
||||||
) : DefaultSourceMapper(sourceInfo) {
|
|
||||||
|
|
||||||
val visitedLines = TIntIntHashMap()
|
|
||||||
|
|
||||||
var lastVisitedRange: RangeMapping? = null
|
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
|
||||||
val mappedLineNumber = visitedLines.get(lineNumber)
|
|
||||||
|
|
||||||
if (mappedLineNumber > 0) {
|
|
||||||
iv.visitLineNumber(mappedLineNumber, start)
|
|
||||||
} else {
|
|
||||||
val rangeForMapping = if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber)!!
|
|
||||||
val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber)
|
|
||||||
val visitLineNumber = parent.visitLineNumber(iv, start, sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path)
|
|
||||||
if (visitLineNumber > 0) {
|
|
||||||
visitedLines.put(lineNumber, visitLineNumber)
|
|
||||||
}
|
|
||||||
lastVisitedRange = rangeForMapping
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findMappingIfExists(lineNumber: Int): RangeMapping? {
|
|
||||||
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
|
||||||
value, key ->
|
|
||||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
|
||||||
})
|
|
||||||
return if (index < 0) null else ranges[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open class InlineLambdaSourceMapper(
|
|
||||||
parent: SourceMapper, smap: SMAPAndMethodNode
|
|
||||||
) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
assert(smap.ranges.isNotEmpty()) {
|
|
||||||
"Mapping ranges should be presented in inline lambda: ${smap.node}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
|
||||||
if (ranges.firstOrNull()?.contains(lineNumber) ?: false) {
|
|
||||||
//don't remap origin lambda line numbers
|
|
||||||
iv.visitLineNumber(lineNumber, start)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
super.visitLineNumber(iv, lineNumber, start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
open class DefaultSourceMapper @JvmOverloads constructor(
|
|
||||||
val sourceInfo: SourceInfo,
|
|
||||||
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
|
||||||
) : SourceMapper {
|
|
||||||
|
|
||||||
var callSiteMarker: CallSiteMarker? = null;
|
|
||||||
set(value) {
|
|
||||||
lastMappedWithChanges = null
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastVisited: RawFileMapping? = null
|
|
||||||
private var lastMappedWithChanges: RawFileMapping? = null
|
|
||||||
private var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
|
|
||||||
protected val origin: RawFileMapping
|
|
||||||
|
|
||||||
init {
|
|
||||||
val name = sourceInfo.source
|
|
||||||
val path = sourceInfo.pathOrCleanFQN
|
|
||||||
origin = RawFileMapping(name, path)
|
|
||||||
origin.initRange(1, sourceInfo.linesInFile)
|
|
||||||
fileMappings.put(createKey(name, path), origin)
|
|
||||||
lastVisited = origin
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createKey(name: String, path: String) = "$name#$path"
|
|
||||||
|
|
||||||
override val resultMappings: List<FileMapping>
|
|
||||||
get() = fileMappings.values.map { it.toFileMapping() }
|
|
||||||
|
|
||||||
override fun visitSource(name: String, path: String) {
|
|
||||||
lastVisited = fileMappings.getOrPut(createKey(name, path)) { RawFileMapping(name, path) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitOrigin() {
|
|
||||||
lastVisited = origin
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
|
||||||
if (lineNumber < 0) {
|
|
||||||
//no source information, so just skip this linenumber
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//TODO add assertion that mapping exists
|
|
||||||
//val sourceLineNumber = createMapping(lineNumberToMap)
|
|
||||||
val sourceLineNumber = lineNumber
|
|
||||||
assert(lineNumber == sourceLineNumber)
|
|
||||||
iv.visitLineNumber(lineNumber, start)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, start: Label, source: Int, sourceName: String, sourcePath: String): Int {
|
|
||||||
if (source < 0) {
|
|
||||||
//no source information, so just skip this linenumber
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
visitSource(sourceName, sourcePath)
|
|
||||||
val mappedLineIndex = createMapping(source)
|
|
||||||
iv.visitLineNumber(mappedLineIndex, start)
|
|
||||||
return mappedLineIndex
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun createMapping(lineNumber: Int): Int {
|
|
||||||
val fileMapping = lastVisited!!
|
|
||||||
val mappedLineIndex = fileMapping.mapNewLineNumber(lineNumber, maxUsedValue, lastMappedWithChanges == lastVisited, callSiteMarker)
|
|
||||||
if (mappedLineIndex > maxUsedValue) {
|
|
||||||
lastMappedWithChanges = fileMapping
|
|
||||||
maxUsedValue = mappedLineIndex
|
|
||||||
}
|
|
||||||
return mappedLineIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RawFileMapping(val name: String, val path: String) {
|
|
||||||
private val rangeMappings = arrayListOf<RangeMapping>()
|
|
||||||
|
|
||||||
private var lastMappedWithNewIndex = -1000
|
|
||||||
|
|
||||||
fun toFileMapping() =
|
|
||||||
FileMapping(name, path).apply {
|
|
||||||
for (range in rangeMappings) {
|
|
||||||
addRangeMapping(range)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initRange(start: Int, end: Int) {
|
|
||||||
assert(rangeMappings.isEmpty()) { "initRange should only be called for empty mapping" }
|
|
||||||
rangeMappings.add(RangeMapping(start, start, end - start + 1))
|
|
||||||
lastMappedWithNewIndex = end
|
|
||||||
}
|
|
||||||
|
|
||||||
fun mapNewLineNumber(source: Int, currentIndex: Int, isLastMapped: Boolean, callSiteMarker: CallSiteMarker?): Int {
|
|
||||||
val dest: Int
|
|
||||||
val rangeMapping: RangeMapping
|
|
||||||
if (rangeMappings.isNotEmpty() && isLastMapped && couldFoldInRange(lastMappedWithNewIndex, source)) {
|
|
||||||
rangeMapping = rangeMappings.last()
|
|
||||||
rangeMapping.range += source - lastMappedWithNewIndex
|
|
||||||
dest = rangeMapping.mapSourceToDest(source)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dest = currentIndex + 1
|
|
||||||
rangeMapping = RangeMapping(source, dest, callSiteMarker = callSiteMarker)
|
|
||||||
rangeMappings.add(rangeMapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
lastMappedWithNewIndex = source
|
|
||||||
return dest
|
|
||||||
}
|
|
||||||
|
|
||||||
fun mapNewInterval(source: Int, dest: Int, range: Int) {
|
|
||||||
val rangeMapping = RangeMapping(source, dest, range)
|
|
||||||
rangeMappings.add(rangeMapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun couldFoldInRange(first: Int, second: Int): Boolean {
|
|
||||||
//TODO
|
|
||||||
val delta = second - first
|
|
||||||
return delta > 0 && delta <= 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user