Smart step into for constructors

This commit is contained in:
Natalia Ukhorskaya
2015-11-25 17:10:36 +03:00
parent 062b27995c
commit 9bcc9e4b1d
5 changed files with 71 additions and 18 deletions
@@ -21,26 +21,22 @@ import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.NamedMethodFilter
import com.intellij.util.Range
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.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.*
public class KotlinBasicStepMethodFilter(
val resolvedFunction: KtElement,
val resolvedElement: KtElement,
val myCallingExpressionLines: Range<Int>
) : NamedMethodFilter {
private val myTargetMethodName: String
init {
myTargetMethodName = when (resolvedFunction) {
myTargetMethodName = when (resolvedElement) {
is KtAnonymousInitializer -> "<init>"
is KtConstructor<*> -> "<init>"
is KtPropertyAccessor -> JvmAbi.getterName((resolvedFunction.getParent() as KtProperty).getName()!!)
else -> resolvedFunction.getName()!!
is KtPropertyAccessor -> JvmAbi.getterName((resolvedElement.getParent() as KtProperty).getName()!!)
else -> resolvedElement.getName()!!
}
}
@@ -52,7 +48,7 @@ public class KotlinBasicStepMethodFilter(
val method = location.method()
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 classes = positionManager.getAllClasses(sourcePosition)
@@ -27,6 +27,7 @@ import com.intellij.util.Range
import com.intellij.util.containers.OrderedSet
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
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
element.accept(object: KtTreeVisitorVoid() {
override fun visitFunctionLiteralExpression(expression: KtFunctionLiteralExpression) {
recordFunctionLiteral(expression.functionLiteral)
}
@@ -175,14 +175,20 @@ public class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
val descriptor = resolvedCall.getResultingDescriptor()
if (descriptor is CallableMemberDescriptor && !isIntrinsic(descriptor)) {
val function = DescriptorToSourceUtilsIde.getAnyDeclaration(file.getProject(), descriptor)
if (function is KtNamedFunction || function is KtSecondaryConstructor) {
if (descriptor is FunctionDescriptor && !isIntrinsic(descriptor)) {
val resolvedElement = DescriptorToSourceUtilsIde.getAnyDeclaration(file.getProject(), descriptor)
if (resolvedElement is KtNamedFunction || resolvedElement is KtConstructor<*>) {
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) {
result.add(MethodSmartStepTarget(function, null, expression, false, lines))
else if (resolvedElement is PsiMethod) {
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))
}
}
}
}
+44
View File
@@ -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()
+1
View File
@@ -25,4 +25,5 @@ val propFoo: Int
// EXISTS: fooWithParam: f.invoke()
// EXISTS: test()
// EXISTS: constructor FooClass()
// EXISTS: constructor FooClass(Int)
// EXISTS: constructor FooClass(Int\, Int)
@@ -53,6 +53,12 @@ public class SmartStepIntoTestGenerated extends AbstractSmartStepIntoTest {
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")
public void testConventionMethod() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/smartStepInto/conventionMethod.kt");