diff --git a/idea/src/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilter.kt b/idea/src/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilter.kt index edd1e46b298..a2eed417350 100644 --- a/idea/src/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilter.kt @@ -32,6 +32,8 @@ import org.jetbrains.kotlin.idea.core.refactoring.getLineCount import org.jetbrains.kotlin.idea.core.refactoring.toPsiFile import org.jetbrains.kotlin.idea.util.DebuggerUtils import org.jetbrains.kotlin.idea.util.ProjectRootsUtil +import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.tail import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.utils.addToStdlib.check @@ -69,6 +71,12 @@ class KotlinExceptionFilter(private val searchScope: GlobalSearchScope) : Filter } private fun virtualFileForInlineCall(jvmName: JvmClassName, file: VirtualFile, lineNumber: Int, project: Project): OpenFileHyperlinkInfo? { + if (ProjectRootsUtil.isInContent(project, file, false, true, false)) { + val fileFinder = JvmVirtualFileFinder.SERVICE.getInstance(project) + val classFile = fileFinder.findVirtualFileWithHeader(ClassId(jvmName.packageFqName, jvmName.fqNameForClassNameWithoutDollars.shortName())) ?: return null + return readDebugInfoForInlineFun(classFile.contentsToByteArray(), lineNumber, project) + } + if (!ProjectRootsUtil.isInContent(project, file, true, false, false)) return null val linesInFile = file.toPsiFile(project)?.getLineCount() ?: return null @@ -81,7 +89,7 @@ class KotlinExceptionFilter(private val searchScope: GlobalSearchScope) : Filter val classByByDirectory = findClassFileByPath(jvmName.packageFqName.asString(), className, outputDir) ?: return null - return readDebugInfoForInlineFun(classByByDirectory, lineNumber, project) + return readDebugInfoForInlineFun(classByByDirectory.readBytes(), lineNumber, project) } private fun findClassFileByPath(packageName: String, className: String, outputDir: VirtualFile): File? { @@ -98,8 +106,8 @@ class KotlinExceptionFilter(private val searchScope: GlobalSearchScope) : Filter return null } - private fun readDebugInfoForInlineFun(classFile: File, line: Int, project: Project): OpenFileHyperlinkInfo? { - val debugInfo = readDebugInfo(classFile) ?: return null + private fun readDebugInfoForInlineFun(bytes: ByteArray, line: Int, project: Project): OpenFileHyperlinkInfo? { + val debugInfo = readDebugInfo(bytes) ?: return null val mappings = SMAPParser.parse(debugInfo) @@ -112,8 +120,8 @@ class KotlinExceptionFilter(private val searchScope: GlobalSearchScope) : Filter return OpenFileHyperlinkInfo(project, newSourceFile.virtualFile, mappingInfo.getIntervalIfContains(line)!!.map(line) - 1) } - private fun readDebugInfo(classFile: File): String? { - val cr = ClassReader(classFile.readBytes()); + private fun readDebugInfo(bytes: ByteArray): String? { + val cr = ClassReader(bytes); var debugInfo: String? = null cr.accept(object : ClassVisitor(InlineCodegenUtil.API) { override fun visitSource(source: String?, debug: String?) { diff --git a/idea/testData/debugger/exceptionFilter/inlineFunCallInLibrary/inlineFunCallInLibrary.kt b/idea/testData/debugger/exceptionFilter/inlineFunCallInLibrary/inlineFunCallInLibrary.kt new file mode 100644 index 00000000000..ceebc498f33 --- /dev/null +++ b/idea/testData/debugger/exceptionFilter/inlineFunCallInLibrary/inlineFunCallInLibrary.kt @@ -0,0 +1,11 @@ +package inlineFunCallInLibrary + +import inlineFunctionCall.* + +fun box() { + call() +} + +// WITH_MOCK_LIBRARY: true +// FILE: inlineFunInLibrary.kt +// LINE: 4 \ No newline at end of file diff --git a/idea/testData/debugger/exceptionFilter/inlineFunFromLibrary/inlineFunFromLibrary.kt b/idea/testData/debugger/exceptionFilter/inlineFunFromLibrary/inlineFunFromLibrary.kt new file mode 100644 index 00000000000..b77ff20f9bf --- /dev/null +++ b/idea/testData/debugger/exceptionFilter/inlineFunFromLibrary/inlineFunFromLibrary.kt @@ -0,0 +1,13 @@ +package inlineFunFromLibrary + +import inlineFunInLibrary.* + +fun box() { + foo { + println() + } +} + +// WITH_MOCK_LIBRARY: true +// FILE: inlineFunInLibrary.kt +// LINE: 4 \ No newline at end of file diff --git a/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunInLibrary.kt b/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunInLibrary.kt new file mode 100644 index 00000000000..e6dfc558cd6 --- /dev/null +++ b/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunInLibrary.kt @@ -0,0 +1,6 @@ +package inlineFunInLibrary + +inline fun foo(f: () -> Unit) { + null!! + f() +} diff --git a/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunctionCall.kt b/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunctionCall.kt new file mode 100644 index 00000000000..0b4c545d7fb --- /dev/null +++ b/idea/testData/debugger/mockLibraryForExceptionFilter/inlineFunctionCall.kt @@ -0,0 +1,9 @@ +package inlineFunctionCall + +import inlineFunInLibrary.* + +fun call() { + foo { + println() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/filters/AbstractKotlinExceptionFilterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/filters/AbstractKotlinExceptionFilterTest.kt index 0989e4e7aab..aa26ee19ed3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/filters/AbstractKotlinExceptionFilterTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/filters/AbstractKotlinExceptionFilterTest.kt @@ -109,11 +109,11 @@ public abstract class AbstractKotlinExceptionFilterTest: KotlinCodeInsightTestCa ?: throw AssertionError("Couldn't find file: name = $expectedFileName") val expectedLineNumber = InTextDirectivesUtils.getPrefixedInt(fileText, "// LINE: ")!! - // TODO compare virtual files - assertEquals("Wrong fileName for line $stackTraceElement", expectedFileName, descriptor.file.name) val document = FileDocumentManager.getInstance().getDocument(expectedVirtualFile)!! val expectedOffset = document.getLineStartOffset(expectedLineNumber - 1) - assertEquals("Wrong offset for line $stackTraceElement", expectedOffset, descriptor.offset) + + // TODO compare virtual files + assertEquals("Wrong result for line $stackTraceElement", expectedFileName + ":" + expectedOffset, descriptor.file.name + ":" + descriptor.offset) } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilterTestGenerated.java index 0416dfb23e5..7a512a39bdc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/filters/KotlinExceptionFilterTestGenerated.java @@ -41,12 +41,30 @@ public class KotlinExceptionFilterTestGenerated extends AbstractKotlinExceptionF doTest(fileName); } + @TestMetadata("inlineFunCallInLibrary") + public void testInlineFunCallInLibrary() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/exceptionFilter/inlineFunCallInLibrary/"); + doTest(fileName); + } + + @TestMetadata("inlineFunFromLibrary") + public void testInlineFunFromLibrary() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/exceptionFilter/inlineFunFromLibrary/"); + doTest(fileName); + } + @TestMetadata("inlineFunctionAnotherFile") public void testInlineFunctionAnotherFile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/exceptionFilter/inlineFunctionAnotherFile/"); doTest(fileName); } + @TestMetadata("inlineFunctionInnerClass") + public void testInlineFunctionInnerClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/exceptionFilter/inlineFunctionInnerClass/"); + doTest(fileName); + } + @TestMetadata("inlineFunctionSameFile") public void testInlineFunctionSameFile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/exceptionFilter/inlineFunctionSameFile/");