Skip smap generation if there is no source information
#KT-7022 Fixed
This commit is contained in:
@@ -35,12 +35,17 @@ public class SMAPBuilder(val source: String,
|
|||||||
val header = "SMAP\n$source\nKotlin\n*S Kotlin"
|
val header = "SMAP\n$source\nKotlin\n*S Kotlin"
|
||||||
|
|
||||||
fun build(): String? {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileIds = "*F" + fileMappings.mapIndexed {(id, file) -> "\n${file.toSMAPFile(id + 1)}" }.join("")
|
val fileIds = "*F" + realMappings.mapIndexed {(id, file) -> "\n${file.toSMAPFile(id + 1)}" }.join("")
|
||||||
val lineMappings = "*L" + fileMappings.map { it.toSMAPMapping() }.join("")
|
val lineMappings = "*L" + realMappings.map { it.toSMAPMapping() }.join("")
|
||||||
|
|
||||||
return "$header\n$fileIds\n$lineMappings\n*E\n"
|
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) {
|
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)
|
val mappedLineIndex = createMapping(lineNumber)
|
||||||
iv.visitLineNumber(mappedLineIndex, start)
|
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>()
|
val lineMappings = arrayListOf<RangeMapping>()
|
||||||
|
|
||||||
var id = -1;
|
var id = -1;
|
||||||
@@ -314,18 +323,24 @@ public class FileMapping(val name: String, val path: String) {
|
|||||||
lineMappings.add(lineMapping)
|
lineMappings.add(lineMapping)
|
||||||
lineMapping.parent = this
|
lineMapping.parent = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object SKIP : FileMapping("no-source-info", "no-source-info") {
|
||||||
|
init {
|
||||||
|
addRangeMapping(RangeMapping.SKIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO comparable
|
//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;
|
var parent: FileMapping? = null;
|
||||||
|
|
||||||
fun contains(destLine: Int): Boolean {
|
open fun contains(destLine: Int): Boolean {
|
||||||
return dest <= destLine && destLine < dest + range
|
return dest <= destLine && destLine < dest + range
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(destLine: Int): Int {
|
open fun map(destLine: Int): Int {
|
||||||
return source + (destLine - dest)
|
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
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import com.intellij.util.SmartFMap
|
||||||
import kotlin.platform.platformStatic
|
import kotlin.platform.platformStatic
|
||||||
|
|
||||||
object SMAPParser {
|
object SMAPParser {
|
||||||
|
|
||||||
[platformStatic]
|
[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()) {
|
if (mappingInfo == null || mappingInfo.isEmpty()) {
|
||||||
val fm = FileMapping(source, path)
|
val fm: FileMapping
|
||||||
if (methodStartLine <= methodEndLine) {
|
if (source == null || source.isEmpty()) {
|
||||||
//one to one
|
fm = FileMapping.SKIP
|
||||||
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
|
}
|
||||||
|
else {
|
||||||
|
fm = FileMapping(source, path)
|
||||||
|
if (methodStartLine <= methodEndLine) {
|
||||||
|
//one to one
|
||||||
|
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SMAP(listOf(fm))
|
return SMAP(listOf(fm))
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public class B {
|
||||||
|
|
||||||
|
public fun test(): String {
|
||||||
|
var p = "fail"
|
||||||
|
A().test {
|
||||||
|
p = "OK"
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public class A {
|
||||||
|
|
||||||
|
inline public fun test(s: () -> Unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+68
-4
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.jvm.compiler;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
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.DescriptorValidator;
|
||||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator;
|
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator;
|
||||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
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.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
@@ -210,4 +212,66 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
JetTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), output);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user