diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 888e14cb925..d856572d8a0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -343,6 +343,12 @@ public class FunctionCodegen extends GenerationStateAware { InstructionAdapter iv = new InstructionAdapter(mv); Type[] argTypes = asmMethod.getArgumentTypes(); + // The first line of some namespace file is written to the line number attribute of a static delegate to allow to 'step into' it + // This is similar to what javac does with bridge methods + Label label = new Label(); + iv.visitLabel(label); + iv.visitLineNumber(1, label); + int k = 0; for (Type argType : argTypes) { iv.load(k, argType); diff --git a/compiler/testData/lineNumber/staticDelegate/bar.kt b/compiler/testData/lineNumber/staticDelegate/bar.kt new file mode 100644 index 00000000000..ea6da7148e3 --- /dev/null +++ b/compiler/testData/lineNumber/staticDelegate/bar.kt @@ -0,0 +1,4 @@ + +fun bar() { + +} diff --git a/compiler/testData/lineNumber/staticDelegate/foo.kt b/compiler/testData/lineNumber/staticDelegate/foo.kt new file mode 100644 index 00000000000..1f15c564135 --- /dev/null +++ b/compiler/testData/lineNumber/staticDelegate/foo.kt @@ -0,0 +1,4 @@ + +fun foo(): Int { + return 42 +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/LineNumberTest.java b/compiler/tests/org/jetbrains/jet/codegen/LineNumberTest.java index fdbf212641b..c4e8938e8f7 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/LineNumberTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/LineNumberTest.java @@ -31,12 +31,15 @@ import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.parsing.JetParsingTest; import org.jetbrains.jet.test.TestCaseWithTmpdir; import org.jetbrains.jet.utils.ExceptionUtils; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -243,4 +246,31 @@ public class LineNumberTest extends TestCaseWithTmpdir { public void testWhile() { doTest(); } + + public void testStaticDelegate() { + JetFile foo = createPsiFile("staticDelegate/foo.kt"); + JetFile bar = createPsiFile("staticDelegate/bar.kt"); + GenerationState state = GenerationUtils.compileManyFilesGetGenerationStateForTest(foo.getProject(), Arrays.asList(foo, bar)); + ClassReader reader = new ClassReader(state.getFactory().asBytes(JvmAbi.PACKAGE_CLASS + ".class")); + + // There must be exactly one line number attribute for each static delegate in namespace.class, and it should point to the first + // line. There are two static delegates in this test, hence the [1, 1] + List expectedLineNumbers = Arrays.asList(1, 1); + + final List actualLineNumbers = new ArrayList(); + + reader.accept(new ClassVisitor(Opcodes.ASM4) { + @Override + public MethodVisitor visitMethod(int access, String name, final String desc, final String signature, String[] exceptions) { + return new MethodVisitor(Opcodes.ASM4) { + @Override + public void visitLineNumber(int line, Label label) { + actualLineNumbers.add(line); + } + }; + } + }, ClassReader.SKIP_FRAMES); + + assertSameElements(actualLineNumbers, expectedLineNumbers); + } }