Skip smap generation if there is no source information

#KT-7022 Fixed
This commit is contained in:
Michael Bogdanov
2015-03-17 15:54:48 +03:00
parent c945a53eec
commit 6e55ea6480
5 changed files with 137 additions and 17 deletions
@@ -35,12 +35,17 @@ public class SMAPBuilder(val source: String,
val header = "SMAP\n$source\nKotlin\n*S Kotlin"
fun build(): String? {
if (fileMappings.isEmpty()) {
var realMappings = fileMappings.filter {
val mappings = it.lineMappings
mappings.isNotEmpty() && mappings.first() != RangeMapping.SKIP
}
if (realMappings.isEmpty()) {
return null;
}
val fileIds = "*F" + fileMappings.mapIndexed {(id, file) -> "\n${file.toSMAPFile(id + 1)}" }.join("")
val lineMappings = "*L" + fileMappings.map { it.toSMAPMapping() }.join("")
val fileIds = "*F" + realMappings.mapIndexed {(id, file) -> "\n${file.toSMAPFile(id + 1)}" }.join("")
val lineMappings = "*L" + realMappings.map { it.toSMAPMapping() }.join("")
return "$header\n$fileIds\n$lineMappings\n*E\n"
}
@@ -212,6 +217,10 @@ public open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val p
}
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
if (lineNumber < 0) {
//no source information, so just skip this linenumber
return
}
val mappedLineIndex = createMapping(lineNumber)
iv.visitLineNumber(mappedLineIndex, start)
}
@@ -305,7 +314,7 @@ class RawFileMapping(val name: String, val path: String) {
}
}
public class FileMapping(val name: String, val path: String) {
open public class FileMapping(val name: String, val path: String) {
val lineMappings = arrayListOf<RangeMapping>()
var id = -1;
@@ -314,18 +323,24 @@ public class FileMapping(val name: String, val path: String) {
lineMappings.add(lineMapping)
lineMapping.parent = this
}
public object SKIP : FileMapping("no-source-info", "no-source-info") {
init {
addRangeMapping(RangeMapping.SKIP)
}
}
}
//TODO comparable
data public class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
data open public class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
var parent: FileMapping? = null;
fun contains(destLine: Int): Boolean {
open fun contains(destLine: Int): Boolean {
return dest <= destLine && destLine < dest + range
}
fun map(destLine: Int): Int {
open fun map(destLine: Int): Int {
return source + (destLine - dest)
}
@@ -342,4 +357,15 @@ data public class RangeMapping(val source: Int, val dest: Int, var range: Int =
}
}
}
}
public object SKIP : RangeMapping(-1, -1, 1) {
override fun contains(destLine: Int): Boolean {
return true
}
override fun map(destLine: Int): Int {
return -1
}
}
}
@@ -16,17 +16,25 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.util.SmartFMap
import kotlin.platform.platformStatic
object SMAPParser {
[platformStatic]
public fun parseOrCreateDefault(mappingInfo: String?, source: String, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
/*null smap means that there is no any debug info in file (e.g. sourceName)*/
public fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
if (mappingInfo == null || mappingInfo.isEmpty()) {
val fm = FileMapping(source, path)
if (methodStartLine <= methodEndLine) {
//one to one
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
val fm: FileMapping
if (source == null || source.isEmpty()) {
fm = FileMapping.SKIP
}
else {
fm = FileMapping(source, path)
if (methodStartLine <= methodEndLine) {
//one to one
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
}
}
return SMAP(listOf(fm))
}
@@ -0,0 +1,13 @@
package test
public class B {
public fun test(): String {
var p = "fail"
A().test {
p = "OK"
}
return p
}
}
@@ -0,0 +1,9 @@
package test
public class A {
inline public fun test(s: () -> Unit) {
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.jvm.compiler;
import com.google.common.collect.Iterables;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
@@ -38,11 +39,12 @@ import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.util.DescriptorValidator;
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator;
import org.jetbrains.kotlin.utils.UtilsPackage;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.ClassWriter;
import org.jetbrains.org.objectweb.asm.Opcodes;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -210,4 +212,66 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
JetTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), output);
}
/*test source mapping generation when source info is absent*/
public void testInlineFunWithoutDebugInfo() throws Exception {
File inlineSource = new File(getTestDataDirectory(), "sourceInline.kt");
CliBaseTest.executeCompilerGrabOutput(new K2JVMCompiler(), Arrays.asList(
inlineSource.getPath(),
"-d", tmpdir.getPath()
));
File inlineFunClass = new File(tmpdir.getAbsolutePath(), "test/A.class");
ClassReader reader = new ClassReader(new FileInputStream(inlineFunClass));
ClassWriter cw = new ClassWriter(Opcodes.ASM5);
reader.accept(new ClassVisitor(Opcodes.ASM5, cw) {
@Override
public void visitSource(String source, String debug) {
//skip debug info
}
}, 0);
assert inlineFunClass.delete();
assert !inlineFunClass.exists();
FileOutputStream stream = new FileOutputStream(inlineFunClass);
try {
stream.write(cw.toByteArray());
}
finally {
stream.close();
}
File resultSource = new File(getTestDataDirectory(), "source.kt");
CliBaseTest.executeCompilerGrabOutput(new K2JVMCompiler(), Arrays.asList(
resultSource.getPath(),
"-classpath", tmpdir.getPath(),
"-d", tmpdir.getPath()
));
File resultFile = new File(tmpdir.getAbsolutePath(), "test/B.class");
reader = new ClassReader(new FileInputStream(resultFile));
final Ref<String> debugInfo = new Ref<String>();
reader.accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public void visitSource(String source, String debug) {
//skip debug info
debugInfo.set(debug);
}
}, 0);
String expected = "SMAP\n" +
"source.kt\n" +
"Kotlin\n" +
"*S Kotlin\n" +
"*F\n" +
"+ 1 source.kt\n" +
"test/B\n" +
"*L\n" +
"1#1,13:1\n" +
"*E\n";
assertEquals(expected, debugInfo.get());
}
}