Refactorings: functions moves
This commit is contained in:
@@ -24,9 +24,7 @@ import com.intellij.debugger.engine.DebugProcessImpl
|
|||||||
import com.intellij.debugger.engine.PositionManagerEx
|
import com.intellij.debugger.engine.PositionManagerEx
|
||||||
import com.intellij.debugger.engine.evaluation.EvaluationContext
|
import com.intellij.debugger.engine.evaluation.EvaluationContext
|
||||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||||
import com.intellij.debugger.jdi.VirtualMachineProxyImpl
|
|
||||||
import com.intellij.debugger.requests.ClassPrepareRequestor
|
import com.intellij.debugger.requests.ClassPrepareRequestor
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
import com.intellij.psi.impl.compiled.ClsFileImpl
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
@@ -124,7 +122,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lineNumber > psiFile.getLineCount() && myDebugProcess.isDexDebug()) {
|
if (lineNumber > psiFile.getLineCount() && myDebugProcess.isDexDebug()) {
|
||||||
val inlinePosition = inlineLineAndFileByPosition(
|
val inlinePosition = getOriginalPositionOfInlinedLine(
|
||||||
location.lineNumber(), FqName(location.declaringType().name()), location.sourceName(),
|
location.lineNumber(), FqName(location.declaringType().name()), location.sourceName(),
|
||||||
myDebugProcess.project, GlobalSearchScope.allScope(myDebugProcess.project))
|
myDebugProcess.project, GlobalSearchScope.allScope(myDebugProcess.project))
|
||||||
|
|
||||||
@@ -257,7 +255,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (myDebugProcess.isDexDebug()) {
|
if (myDebugProcess.isDexDebug()) {
|
||||||
val inlineLocations = noStrataLocationsOfLineForInlineFunctions(type, position, myDebugProcess.searchScope)
|
val inlineLocations = getLocationsOfInlinedLine(type, position, myDebugProcess.searchScope)
|
||||||
if (!inlineLocations.isEmpty()) {
|
if (!inlineLocations.isEmpty()) {
|
||||||
return inlineLocations
|
return inlineLocations
|
||||||
}
|
}
|
||||||
@@ -303,9 +301,3 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
|
|||||||
inline fun <U, V> U.readAction(crossinline f: (U) -> V): V {
|
inline fun <U, V> U.readAction(crossinline f: (U) -> V): V {
|
||||||
return runReadAction { f(this) }
|
return runReadAction { f(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Volatile var emulateDexDebugInTests: Boolean = false
|
|
||||||
|
|
||||||
private fun DebugProcess.isDexDebug() =
|
|
||||||
(emulateDexDebugInTests && ApplicationManager.getApplication ().isUnitTestMode) ||
|
|
||||||
(this.virtualMachineProxy as? VirtualMachineProxyImpl)?.virtualMachine?.name() == "Dalvik" // TODO: check other machine name
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
package org.jetbrains.kotlin.idea.debugger
|
package org.jetbrains.kotlin.idea.debugger
|
||||||
|
|
||||||
import com.intellij.debugger.SourcePosition
|
import com.intellij.debugger.SourcePosition
|
||||||
|
import com.intellij.debugger.engine.DebugProcess
|
||||||
|
import com.intellij.debugger.jdi.VirtualMachineProxyImpl
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.sun.jdi.Location
|
import com.sun.jdi.Location
|
||||||
import com.sun.jdi.ReferenceType
|
import com.sun.jdi.ReferenceType
|
||||||
@@ -24,10 +28,26 @@ import org.jetbrains.kotlin.idea.refactoring.getLineStartOffset
|
|||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtFunction
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
|
||||||
fun noStrataLocationsOfLineForInlineFunctions(type: ReferenceType, position: SourcePosition, sourceSearchScope: GlobalSearchScope): List<Location> {
|
internal fun getOriginalPositionOfInlinedLine(
|
||||||
|
lineNumber: Int, fqName: FqName, fileName: String, project: Project, searchScope: GlobalSearchScope): Pair<KtFile, Int>? {
|
||||||
|
val internalName = fqName.asString().replace('.', '/')
|
||||||
|
val jvmClassName = JvmClassName.byInternalName(internalName)
|
||||||
|
|
||||||
|
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, searchScope, jvmClassName, fileName) ?: return null
|
||||||
|
|
||||||
|
val virtualFile = file.virtualFile ?: return null
|
||||||
|
|
||||||
|
val bytes = readClassFile(project, jvmClassName, virtualFile, { isInlineFunctionLineNumber(it, lineNumber, project) }) ?: return null
|
||||||
|
val smapData = readDebugInfo(bytes) ?: return null
|
||||||
|
return mapStacktraceLineToSource(smapData, lineNumber, project, SourceLineKind.EXECUTED_LINE, searchScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getLocationsOfInlinedLine(type: ReferenceType, position: SourcePosition, sourceSearchScope: GlobalSearchScope): List<Location> {
|
||||||
val line = position.line
|
val line = position.line
|
||||||
val file = position.file
|
val file = position.file
|
||||||
val project = position.file.project
|
val project = position.file.project
|
||||||
@@ -43,3 +63,30 @@ fun noStrataLocationsOfLineForInlineFunctions(type: ReferenceType, position: Sou
|
|||||||
|
|
||||||
return inlineLocations
|
return inlineLocations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun inlinedLinesNumbers(
|
||||||
|
inlineLineNumber: Int, inlineFileName: String,
|
||||||
|
destinationTypeFqName: FqName, destinationFileName: String,
|
||||||
|
project: Project, sourceSearchScope: GlobalSearchScope): List<Int> {
|
||||||
|
val internalName = destinationTypeFqName.asString().replace('.', '/')
|
||||||
|
val jvmClassName = JvmClassName.byInternalName(internalName)
|
||||||
|
|
||||||
|
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, sourceSearchScope, jvmClassName, destinationFileName) ?:
|
||||||
|
return listOf()
|
||||||
|
|
||||||
|
val virtualFile = file.virtualFile ?: return listOf()
|
||||||
|
|
||||||
|
val bytes = readClassFile(project, jvmClassName, virtualFile) ?: return listOf()
|
||||||
|
val smapData = readDebugInfo(bytes) ?: return listOf()
|
||||||
|
|
||||||
|
val smap = smapData.kotlinStrata ?: return listOf()
|
||||||
|
|
||||||
|
val mappingToInlinedFile = smap.fileMappings.firstOrNull() { it.name == inlineFileName } ?: return listOf()
|
||||||
|
return mappingToInlinedFile.lineMappings.map { it.mapSourceToDest(inlineLineNumber) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Volatile var emulateDexDebugInTests: Boolean = false
|
||||||
|
|
||||||
|
fun DebugProcess.isDexDebug() =
|
||||||
|
(emulateDexDebugInTests && ApplicationManager.getApplication ().isUnitTestMode) ||
|
||||||
|
(this.virtualMachineProxy as? VirtualMachineProxyImpl)?.virtualMachine?.name() == "Dalvik" // TODO: check other machine names
|
||||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
|||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder
|
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.tail
|
import org.jetbrains.kotlin.name.tail
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -41,40 +40,6 @@ import org.jetbrains.org.objectweb.asm.ClassReader
|
|||||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun inlineLineAndFileByPosition(lineNumber: Int, fqName: FqName, fileName: String, project: Project, searchScope: GlobalSearchScope): Pair<KtFile, Int>? {
|
|
||||||
val internalName = fqName.asString().replace('.', '/')
|
|
||||||
val jvmClassName = JvmClassName.byInternalName(internalName)
|
|
||||||
|
|
||||||
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, searchScope, jvmClassName, fileName) ?: return null
|
|
||||||
|
|
||||||
val virtualFile = file.virtualFile ?: return null
|
|
||||||
|
|
||||||
val bytes = readClassFile(project, jvmClassName, virtualFile, { isInlineFunctionLineNumber(it, lineNumber, project) }) ?: return null
|
|
||||||
val smapData = readDebugInfo(bytes) ?: return null
|
|
||||||
return mapStacktraceLineToSource(smapData, lineNumber, project, SourceLineKind.EXECUTED_LINE, searchScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun inlinedLinesNumbers(
|
|
||||||
inlineLineNumber: Int, inlineFileName: String,
|
|
||||||
destinationTypeFqName: FqName, destinationFileName: String,
|
|
||||||
project: Project, sourceSearchScope: GlobalSearchScope): List<Int> {
|
|
||||||
val internalName = destinationTypeFqName.asString().replace('.', '/')
|
|
||||||
val jvmClassName = JvmClassName.byInternalName(internalName)
|
|
||||||
|
|
||||||
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, sourceSearchScope, jvmClassName, destinationFileName) ?:
|
|
||||||
return listOf()
|
|
||||||
|
|
||||||
val virtualFile = file.virtualFile ?: return listOf()
|
|
||||||
|
|
||||||
val bytes = readClassFile(project, jvmClassName, virtualFile) ?: return listOf()
|
|
||||||
val smapData = readDebugInfo(bytes) ?: return listOf()
|
|
||||||
|
|
||||||
val smap = smapData.kotlinStrata ?: return listOf()
|
|
||||||
|
|
||||||
val mappingToInlinedFile = smap.fileMappings.firstOrNull() { it.name == inlineFileName } ?: return listOf()
|
|
||||||
return mappingToInlinedFile.lineMappings.map { it.mapSourceToDest(inlineLineNumber) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInlineFunctionLineNumber(file: VirtualFile, lineNumber: Int, project: Project): Boolean {
|
fun isInlineFunctionLineNumber(file: VirtualFile, lineNumber: Int, project: Project): Boolean {
|
||||||
val linesInFile = file.toPsiFile(project)?.getLineCount() ?: return false
|
val linesInFile = file.toPsiFile(project)?.getLineCount() ?: return false
|
||||||
return lineNumber > linesInFile
|
return lineNumber > linesInFile
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
||||||
if (getTestName(true).startsWith("dex")) {
|
if (getTestName(true).startsWith("dex")) {
|
||||||
KotlinPositionManagerKt.setEmulateDexDebugInTests(true);
|
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(true);
|
||||||
}
|
}
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
|||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
if (getTestName(true).startsWith("dex")) {
|
if (getTestName(true).startsWith("dex")) {
|
||||||
KotlinPositionManagerKt.setEmulateDexDebugInTests(false);
|
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user