Smart step into for constructors
This commit is contained in:
+7
-11
@@ -21,26 +21,22 @@ import com.intellij.debugger.engine.DebugProcessImpl
|
|||||||
import com.intellij.debugger.engine.NamedMethodFilter
|
import com.intellij.debugger.engine.NamedMethodFilter
|
||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import com.sun.jdi.Location
|
import com.sun.jdi.Location
|
||||||
import com.sun.jdi.Method
|
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.psi.KtConstructor
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
|
||||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
|
||||||
|
|
||||||
public class KotlinBasicStepMethodFilter(
|
public class KotlinBasicStepMethodFilter(
|
||||||
val resolvedFunction: KtElement,
|
val resolvedElement: KtElement,
|
||||||
val myCallingExpressionLines: Range<Int>
|
val myCallingExpressionLines: Range<Int>
|
||||||
) : NamedMethodFilter {
|
) : NamedMethodFilter {
|
||||||
private val myTargetMethodName: String
|
private val myTargetMethodName: String
|
||||||
|
|
||||||
init {
|
init {
|
||||||
myTargetMethodName = when (resolvedFunction) {
|
myTargetMethodName = when (resolvedElement) {
|
||||||
|
is KtAnonymousInitializer -> "<init>"
|
||||||
is KtConstructor<*> -> "<init>"
|
is KtConstructor<*> -> "<init>"
|
||||||
is KtPropertyAccessor -> JvmAbi.getterName((resolvedFunction.getParent() as KtProperty).getName()!!)
|
is KtPropertyAccessor -> JvmAbi.getterName((resolvedElement.getParent() as KtProperty).getName()!!)
|
||||||
else -> resolvedFunction.getName()!!
|
else -> resolvedElement.getName()!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +48,7 @@ public class KotlinBasicStepMethodFilter(
|
|||||||
val method = location.method()
|
val method = location.method()
|
||||||
if (myTargetMethodName != method.name()) return false
|
if (myTargetMethodName != method.name()) return false
|
||||||
|
|
||||||
val sourcePosition = runReadAction { SourcePosition.createFromElement(resolvedFunction) } ?: return false
|
val sourcePosition = runReadAction { SourcePosition.createFromElement(resolvedElement) } ?: return false
|
||||||
val positionManager = process.getPositionManager() ?: return false
|
val positionManager = process.getPositionManager() ?: return false
|
||||||
|
|
||||||
val classes = positionManager.getAllClasses(sourcePosition)
|
val classes = positionManager.getAllClasses(sourcePosition)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.intellij.util.Range
|
|||||||
import com.intellij.util.containers.OrderedSet
|
import com.intellij.util.containers.OrderedSet
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
@@ -64,7 +65,6 @@ public class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
|||||||
|
|
||||||
// TODO support class initializers, local functions, delegated properties with specified type, setter for properties
|
// TODO support class initializers, local functions, delegated properties with specified type, setter for properties
|
||||||
element.accept(object: KtTreeVisitorVoid() {
|
element.accept(object: KtTreeVisitorVoid() {
|
||||||
|
|
||||||
override fun visitFunctionLiteralExpression(expression: KtFunctionLiteralExpression) {
|
override fun visitFunctionLiteralExpression(expression: KtFunctionLiteralExpression) {
|
||||||
recordFunctionLiteral(expression.functionLiteral)
|
recordFunctionLiteral(expression.functionLiteral)
|
||||||
}
|
}
|
||||||
@@ -175,14 +175,20 @@ public class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
|||||||
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||||
|
|
||||||
val descriptor = resolvedCall.getResultingDescriptor()
|
val descriptor = resolvedCall.getResultingDescriptor()
|
||||||
if (descriptor is CallableMemberDescriptor && !isIntrinsic(descriptor)) {
|
if (descriptor is FunctionDescriptor && !isIntrinsic(descriptor)) {
|
||||||
val function = DescriptorToSourceUtilsIde.getAnyDeclaration(file.getProject(), descriptor)
|
val resolvedElement = DescriptorToSourceUtilsIde.getAnyDeclaration(file.getProject(), descriptor)
|
||||||
if (function is KtNamedFunction || function is KtSecondaryConstructor) {
|
if (resolvedElement is KtNamedFunction || resolvedElement is KtConstructor<*>) {
|
||||||
val label = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
val label = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
||||||
result.add(KotlinMethodSmartStepTarget(function as KtFunction, label, expression, lines))
|
result.add(KotlinMethodSmartStepTarget(resolvedElement as KtFunction, label, expression, lines))
|
||||||
}
|
}
|
||||||
else if (function is PsiMethod) {
|
else if (resolvedElement is PsiMethod) {
|
||||||
result.add(MethodSmartStepTarget(function, null, expression, false, lines))
|
result.add(MethodSmartStepTarget(resolvedElement, null, expression, false, lines))
|
||||||
|
}
|
||||||
|
else if (resolvedElement is KtClass) {
|
||||||
|
resolvedElement.getAnonymousInitializers().firstOrNull()?.let {
|
||||||
|
val label = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
||||||
|
result.add(KotlinMethodSmartStepTarget(it, label, expression, lines))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
fun foo() {
|
||||||
|
println("${A()} ${B()} ${C(1)} ${D()} ${E(1)} ${F()} ${G()} ${J()} ${K(1)} ${L()}")<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
class A
|
||||||
|
class B()
|
||||||
|
class C(val a: Int)
|
||||||
|
class D {
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
|
class E {
|
||||||
|
constructor(i: Int)
|
||||||
|
}
|
||||||
|
class F {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class G {
|
||||||
|
constructor(i: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class J {
|
||||||
|
init {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class K(val a: Int) {
|
||||||
|
init {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class L {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXISTS: println(Any?), constructor B(), constructor C(Int), constructor D(), constructor E(Int), constructor F(), constructor G(Int), constructor J(), constructor K(Int), constructor L()
|
||||||
@@ -25,4 +25,5 @@ val propFoo: Int
|
|||||||
// EXISTS: fooWithParam: f.invoke()
|
// EXISTS: fooWithParam: f.invoke()
|
||||||
// EXISTS: test()
|
// EXISTS: test()
|
||||||
// EXISTS: constructor FooClass()
|
// EXISTS: constructor FooClass()
|
||||||
|
// EXISTS: constructor FooClass(Int)
|
||||||
// EXISTS: constructor FooClass(Int\, Int)
|
// EXISTS: constructor FooClass(Int\, Int)
|
||||||
@@ -53,6 +53,12 @@ public class SmartStepIntoTestGenerated extends AbstractSmartStepIntoTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constructor.kt")
|
||||||
|
public void testConstructor() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/smartStepInto/constructor.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("conventionMethod.kt")
|
@TestMetadata("conventionMethod.kt")
|
||||||
public void testConventionMethod() throws Exception {
|
public void testConventionMethod() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/smartStepInto/conventionMethod.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/smartStepInto/conventionMethod.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user