-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Consider following files
a.kt
inline fun a() {
nop()
}
b.kt
inline fun b() {
nop()
}
and callsite.kt with 8 lines
fun main(args : Array<String>) {
a() // line 2
b() // line 3
} // line 4
fun nop() {
} // line 7
Kotlin compiler produces CallsiteKt.class whose bytecode
Constant pool:
...
#7 = Utf8 Lorg/jetbrains/annotations/NotNull;
...
#24 = Utf8 Lkotlin/Metadata;
...
{
public static final void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=1
0: aload_0
1: ldc #9 // String args
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: nop
7: invokestatic #19 // Method nop:()V
10: nop
11: nop
12: invokestatic #19 // Method nop:()V
15: nop
16: return
LocalVariableTable:
Start Length Slot Name Signature
7 4 1 $i$f$a I
12 4 1 $i$f$b I
0 17 0 args [Ljava/lang/String;
LineNumberTable:
line 2: 6
line 9: 7
line 10: 10
line 3: 11
line 11: 12
line 12: 15
line 4: 16
RuntimeInvisibleParameterAnnotations:
0:
0: #7()
public static final void nop();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=0, locals=0, args_size=0
0: return
LineNumberTable:
line 7: 0
}
SourceFile: "callsite.kt"
SourceDebugExtension:
SMAP
callsite.kt
Kotlin
*S Kotlin
*F
+ 1 callsite.kt
CallsiteKt
+ 2 a.kt
AKt
+ 3 b.kt
BKt
*L
1#1,8:1
2#2,2:9
2#3,2:11
*E
*S KotlinDebug
*F
+ 1 callsite.kt
CallsiteKt
*L
2#1,2:9
3#1,2:11
*E
RuntimeVisibleAnnotations:
0: #24(#25=[I#26,I#26,I#27],#28=[I#26,I#29,I#30],#31=I#30,#32=[s#33],#34=[s#5,s#35,s#8,s#35,s#35,s#6,s#16])
Contains inlined instructions with line numbers that are greater than actually present in source file:
$ java -jar jacoco-0.8.2/lib/jacococli.jar classinfo CallsiteKt.class
INST BRAN LINE METH CXTY ELEMENT
11 0 8 2 2 class 0xcc96f697bc87baa7 CallsiteKt
10 0 7 1 1 +- method main([Ljava/lang/String;)V
1 0 | +- line 2
1 0 | +- line 3
1 0 | +- line 4
1 0 | +- line 9
1 0 | +- line 10
1 0 | +- line 11
1 0 | +- line 12
1 0 1 1 1 +- method nop()V
1 0 +- line 7
Since we use source line numbers for generation of page with highlighted source in our HTML report, additional lines (9-12) do not appear on it and do not cause troubles. However they add to values of counters as shown by classinfo above and what is also visible in HTML report:
Not demonstrated by above example, but inlining can also affect "branches" and "complexity" counters.
Moreover these additional lines appear in XML report:
<sourcefile name="callsite.kt">
<line nr="2" mi="2" ci="0" mb="0" cb="0"/>
<line nr="3" mi="1" ci="0" mb="0" cb="0"/>
<line nr="4" mi="1" ci="0" mb="0" cb="0"/>
<line nr="7" mi="1" ci="0" mb="0" cb="0"/>
<line nr="9" mi="1" ci="0" mb="0" cb="0"/>
<line nr="10" mi="1" ci="0" mb="0" cb="0"/>
<line nr="12" mi="1" ci="0" mb="0" cb="0"/>
<line nr="13" mi="1" ci="0" mb="0" cb="0"/>
<line nr="14" mi="1" ci="0" mb="0" cb="0"/>
<counter type="INSTRUCTION" missed="13" covered="0"/>
<counter type="LINE" missed="9" covered="0"/>
<counter type="COMPLEXITY" missed="2" covered="0"/>
<counter type="METHOD" missed="2" covered="0"/>
<counter type="CLASS" missed="1" covered="0"/>
</sourcefile>
Which is not good for tools that read our XML report and try to enforce its consistency with source code by checking that line numbers are not greater than in source code.
While ideally we need to somehow map these additional instructions back to their original location in order to show coverage of original (#654).
I propose to do a baby step and at least ignore them at call sites. Seems that for that is enough to obtain minimal value of OutputStartLine in LineSection that comes after KotlinDebug StratumSection of SMAP recorded in class file - minimum of 9 and 11 in the above example:
*S KotlinDebug
*F
+ 1 callsite.kt
CallsiteKt
*L
2#1,2:9
3#1,2:11
*E
Metadata
Metadata
Assignees
Type
Projects
Status
Status

