Debugger: Extract Smart step visitor
This commit is contained in:
+26
-222
@@ -1,251 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto
|
||||
|
||||
import com.intellij.debugger.SourcePosition
|
||||
import com.intellij.debugger.actions.JvmSmartStepIntoHandler
|
||||
import com.intellij.debugger.actions.MethodSmartStepTarget
|
||||
import com.intellij.debugger.actions.SmartStepTarget
|
||||
import com.intellij.debugger.engine.MethodFilter
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Range
|
||||
import com.intellij.util.containers.OrderedSet
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.load.java.isFromJava
|
||||
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils.getTopmostElementAtOffset
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinBasicStepMethodFilter
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinLambdaMethodFilter
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinLambdaSmartStepTarget
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinMethodSmartStepTarget
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
|
||||
class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
|
||||
override fun isAvailable(position: SourcePosition?) = position?.file is KtFile
|
||||
|
||||
override fun findSmartStepTargets(position: SourcePosition): List<SmartStepTarget> {
|
||||
val file = position.file
|
||||
val element = position.elementAt ?: return emptyList()
|
||||
val ktElement = getTopmostElementAtOffset(element, element.textRange.startOffset) as? KtElement
|
||||
val elementTextRange = ktElement?.textRange ?: return emptyList()
|
||||
val document = PsiDocumentManager.getInstance(file.project).getDocument(file) ?: return emptyList()
|
||||
val lines = Range(document.getLineNumber(elementTextRange.startOffset), document.getLineNumber(elementTextRange.endOffset))
|
||||
|
||||
val elementAtOffset = position.elementAt ?: return emptyList()
|
||||
val consumer = OrderedSet<SmartStepTarget>()
|
||||
val visitor = SmartStepTargetVisitor(ktElement, lines, consumer)
|
||||
ktElement.accept(visitor, null)
|
||||
|
||||
val element = CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, elementAtOffset.textRange.startOffset) as? KtElement
|
||||
?: return emptyList()
|
||||
|
||||
val elementTextRange = element.textRange ?: return emptyList()
|
||||
|
||||
val doc = PsiDocumentManager.getInstance(file.project).getDocument(file) ?: return emptyList()
|
||||
|
||||
val lines = Range(doc.getLineNumber(elementTextRange.startOffset), doc.getLineNumber(elementTextRange.endOffset))
|
||||
@Suppress("DEPRECATION")
|
||||
val bindingContext = element.analyzeWithAllCompilerChecks().bindingContext
|
||||
val result = OrderedSet<SmartStepTarget>()
|
||||
|
||||
// TODO support class initializers, local functions, delegated properties with specified type, setter for properties
|
||||
element.accept(object : KtTreeVisitorVoid() {
|
||||
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
|
||||
recordFunctionLiteral(lambdaExpression.functionLiteral)
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
if (!recordFunctionLiteral(function)) {
|
||||
super.visitNamedFunction(function)
|
||||
}
|
||||
}
|
||||
|
||||
private fun recordFunctionLiteral(function: KtFunction): Boolean {
|
||||
val context = function.analyze()
|
||||
val resolvedCall = function.getParentCall(context).getResolvedCall(context)
|
||||
if (resolvedCall != null) {
|
||||
val arguments = resolvedCall.valueArguments
|
||||
for ((param, argument) in arguments) {
|
||||
if (argument.arguments.any { getArgumentExpression(it) == function }) {
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||
val label = KotlinLambdaSmartStepTarget.calcLabel(resultingDescriptor, param.name)
|
||||
result.add(
|
||||
KotlinLambdaSmartStepTarget(
|
||||
label, function, lines, InlineUtil.isInline(resultingDescriptor), param.type.isSuspendFunctionType
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getArgumentExpression(it: ValueArgument) =
|
||||
(it.getArgumentExpression() as? KtLambdaExpression)?.functionLiteral ?: it.getArgumentExpression()
|
||||
|
||||
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression) {
|
||||
// skip calls in object declarations
|
||||
}
|
||||
|
||||
override fun visitIfExpression(expression: KtIfExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhileExpression(expression: KtWhileExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitDoWhileExpression(expression: KtDoWhileExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitForExpression(expression: KtForExpression) {
|
||||
expression.loopRange?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(expression: KtWhenExpression) {
|
||||
expression.subjectExpression?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitArrayAccessExpression(expression: KtArrayAccessExpression) {
|
||||
recordFunction(expression)
|
||||
super.visitArrayAccessExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitUnaryExpression(expression: KtUnaryExpression) {
|
||||
recordFunction(expression.operationReference)
|
||||
super.visitUnaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||
recordFunction(expression.operationReference)
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
val calleeExpression = expression.calleeExpression
|
||||
if (calleeExpression != null) {
|
||||
recordFunction(calleeExpression)
|
||||
}
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
recordGetter(expression)
|
||||
super.visitSimpleNameExpression(expression)
|
||||
}
|
||||
|
||||
private fun recordGetter(expression: KtSimpleNameExpression) {
|
||||
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||
val propertyDescriptor = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: return
|
||||
|
||||
val getterDescriptor = propertyDescriptor.getter
|
||||
if (getterDescriptor == null || getterDescriptor.isDefault) return
|
||||
|
||||
val ktDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, getterDescriptor) as? KtDeclaration ?: return
|
||||
|
||||
val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
|
||||
if (delegatedResolvedCall != null) {
|
||||
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor
|
||||
val label = "${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
|
||||
result.add(KotlinMethodSmartStepTarget(delegatedPropertyGetterDescriptor, ktDeclaration, label, expression, lines))
|
||||
} else {
|
||||
if (ktDeclaration is KtPropertyAccessor && ktDeclaration.hasBody()) {
|
||||
val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor)
|
||||
result.add(KotlinMethodSmartStepTarget(getterDescriptor, ktDeclaration, label, expression, lines))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun recordFunction(expression: KtExpression) {
|
||||
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
if (descriptor !is FunctionDescriptor || isIntrinsic(descriptor)) return
|
||||
|
||||
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
|
||||
if (descriptor.isFromJava) {
|
||||
if (declaration is PsiMethod) {
|
||||
result.add(MethodSmartStepTarget(declaration, null, expression, false, lines))
|
||||
}
|
||||
} else {
|
||||
if (declaration == null && !isInvokeInBuiltinFunction(descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration !is KtDeclaration?) return
|
||||
|
||||
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) {
|
||||
if (declaration is KtClass && declaration.getAnonymousInitializers().isEmpty()) {
|
||||
// There is no constructor or init block, so do not show it in smart step into
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val callLabel = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
||||
val label = when (descriptor) {
|
||||
is FunctionInvokeDescriptor -> {
|
||||
when (expression) {
|
||||
is KtSimpleNameExpression -> "${runReadAction { expression.text }}.$callLabel"
|
||||
else -> callLabel
|
||||
}
|
||||
}
|
||||
else -> callLabel
|
||||
}
|
||||
|
||||
result.add(KotlinMethodSmartStepTarget(descriptor, declaration, label, expression, lines))
|
||||
}
|
||||
}
|
||||
}, null)
|
||||
|
||||
return result
|
||||
return consumer
|
||||
}
|
||||
|
||||
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? {
|
||||
return when (stepTarget) {
|
||||
is KotlinMethodSmartStepTarget ->
|
||||
KotlinBasicStepMethodFilter(
|
||||
stepTarget.declaration?.createSmartPointer(),
|
||||
stepTarget.isInvoke,
|
||||
stepTarget.targetMethodName,
|
||||
stepTarget.callingExpressionLines!!
|
||||
)
|
||||
is KotlinLambdaSmartStepTarget ->
|
||||
KotlinLambdaMethodFilter(
|
||||
stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline, stepTarget.isSuspend
|
||||
)
|
||||
is KotlinMethodSmartStepTarget -> {
|
||||
val declarationPtr = stepTarget.declaration?.createSmartPointer()
|
||||
val lines = stepTarget.callingExpressionLines ?: return null
|
||||
KotlinBasicStepMethodFilter(declarationPtr, stepTarget.isInvoke, stepTarget.targetMethodName, lines)
|
||||
}
|
||||
is KotlinLambdaSmartStepTarget -> {
|
||||
val lines = stepTarget.callingExpressionLines ?: return null
|
||||
KotlinLambdaMethodFilter(stepTarget.getLambda(), lines, stepTarget.isInline, stepTarget.isSuspend)
|
||||
}
|
||||
else -> super.createMethodFilter(stepTarget)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val methods = IntrinsicMethods(JvmTarget.JVM_1_6)
|
||||
|
||||
private fun isIntrinsic(descriptor: CallableMemberDescriptor): Boolean {
|
||||
return methods.getIntrinsic(descriptor) != null
|
||||
}
|
||||
|
||||
private fun isInvokeInBuiltinFunction(descriptor: DeclarationDescriptor): Boolean {
|
||||
if (descriptor !is FunctionInvokeDescriptor) return false
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||
return classDescriptor.defaultType.isBuiltinFunctionalType
|
||||
}
|
||||
}
|
||||
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto
|
||||
|
||||
import com.intellij.debugger.actions.MethodSmartStepTarget
|
||||
import com.intellij.debugger.actions.SmartStepTarget
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Range
|
||||
import com.intellij.util.containers.OrderedSet
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinLambdaSmartStepTarget
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinMethodSmartStepTarget
|
||||
import org.jetbrains.kotlin.idea.project.platform
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.load.java.isFromJava
|
||||
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
// TODO support class initializers, local functions, delegated properties with specified type, setter for properties
|
||||
class SmartStepTargetVisitor(
|
||||
private val element: KtElement,
|
||||
private val lines: Range<Int>,
|
||||
private val consumer: OrderedSet<SmartStepTarget>
|
||||
) : KtTreeVisitorVoid() {
|
||||
private fun append(target: SmartStepTarget) {
|
||||
consumer += target
|
||||
}
|
||||
|
||||
private val intrinsicMethods = run {
|
||||
val jvmTarget = element.platform.firstIsInstanceOrNull<JdkPlatform>()?.targetVersion ?: JvmTarget.DEFAULT
|
||||
IntrinsicMethods(jvmTarget)
|
||||
}
|
||||
|
||||
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
|
||||
recordFunction(lambdaExpression.functionLiteral)
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
if (!recordFunction(function)) {
|
||||
super.visitNamedFunction(function)
|
||||
}
|
||||
}
|
||||
|
||||
private fun recordFunction(function: KtFunction): Boolean {
|
||||
val context = function.analyze()
|
||||
val resolvedCall = function.getParentCall(context).getResolvedCall(context) ?: return false
|
||||
val arguments = resolvedCall.valueArguments
|
||||
|
||||
for ((param, argument) in arguments) {
|
||||
if (argument.arguments.any { getArgumentExpression(it) == function }) {
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||
val label = KotlinLambdaSmartStepTarget.calcLabel(resultingDescriptor, param.name)
|
||||
val isInline = InlineUtil.isInline(resultingDescriptor)
|
||||
val isSuspend = param.type.isSuspendFunctionType
|
||||
val target = KotlinLambdaSmartStepTarget(label, function, lines, isInline, isSuspend)
|
||||
append(target)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getArgumentExpression(it: ValueArgument): KtExpression? {
|
||||
return (it.getArgumentExpression() as? KtLambdaExpression)?.functionLiteral ?: it.getArgumentExpression()
|
||||
}
|
||||
|
||||
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression) {
|
||||
// Skip calls in object declarations
|
||||
}
|
||||
|
||||
override fun visitIfExpression(expression: KtIfExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhileExpression(expression: KtWhileExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitDoWhileExpression(expression: KtDoWhileExpression) {
|
||||
expression.condition?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitForExpression(expression: KtForExpression) {
|
||||
expression.loopRange?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(expression: KtWhenExpression) {
|
||||
expression.subjectExpression?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitArrayAccessExpression(expression: KtArrayAccessExpression) {
|
||||
recordFunctionCall(expression)
|
||||
super.visitArrayAccessExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitUnaryExpression(expression: KtUnaryExpression) {
|
||||
recordFunctionCall(expression.operationReference)
|
||||
super.visitUnaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||
recordFunctionCall(expression.operationReference)
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
val calleeExpression = expression.calleeExpression
|
||||
if (calleeExpression != null) {
|
||||
recordFunctionCall(calleeExpression)
|
||||
}
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
recordGetter(expression)
|
||||
super.visitSimpleNameExpression(expression)
|
||||
}
|
||||
|
||||
private fun recordGetter(expression: KtSimpleNameExpression) {
|
||||
val bindingContext = expression.analyze()
|
||||
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||
val propertyDescriptor = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: return
|
||||
|
||||
val getterDescriptor = propertyDescriptor.getter
|
||||
if (getterDescriptor == null || getterDescriptor.isDefault) return
|
||||
|
||||
val ktDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, getterDescriptor) as? KtDeclaration ?: return
|
||||
|
||||
val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
|
||||
if (delegatedResolvedCall != null) {
|
||||
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor
|
||||
val label = "${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
|
||||
append(KotlinMethodSmartStepTarget(delegatedPropertyGetterDescriptor, ktDeclaration, label, expression, lines))
|
||||
} else {
|
||||
if (ktDeclaration is KtPropertyAccessor && ktDeclaration.hasBody()) {
|
||||
val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor)
|
||||
append(KotlinMethodSmartStepTarget(getterDescriptor, ktDeclaration, label, expression, lines))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun recordFunctionCall(expression: KtExpression) {
|
||||
val resolvedCall = expression.resolveToCall() ?: return
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
if (descriptor !is FunctionDescriptor || isIntrinsic(descriptor)) return
|
||||
|
||||
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, descriptor)
|
||||
if (descriptor.isFromJava) {
|
||||
if (declaration is PsiMethod) {
|
||||
append(MethodSmartStepTarget(declaration, null, expression, false, lines))
|
||||
}
|
||||
} else {
|
||||
if (declaration == null && !isInvokeInBuiltinFunction(descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration !is KtDeclaration?) return
|
||||
|
||||
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) {
|
||||
if (declaration is KtClass && declaration.getAnonymousInitializers().isEmpty()) {
|
||||
// There is no constructor or init block, so do not show it in smart step into
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val callLabel = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
||||
val label = when (descriptor) {
|
||||
is FunctionInvokeDescriptor -> {
|
||||
when (expression) {
|
||||
is KtSimpleNameExpression -> "${runReadAction { expression.text }}.$callLabel"
|
||||
else -> callLabel
|
||||
}
|
||||
}
|
||||
else -> callLabel
|
||||
}
|
||||
|
||||
append(KotlinMethodSmartStepTarget(descriptor, declaration, label, expression, lines))
|
||||
}
|
||||
}
|
||||
|
||||
private fun isIntrinsic(descriptor: CallableMemberDescriptor): Boolean {
|
||||
return intrinsicMethods.getIntrinsic(descriptor) != null
|
||||
}
|
||||
|
||||
private fun isInvokeInBuiltinFunction(descriptor: DeclarationDescriptor): Boolean {
|
||||
if (descriptor !is FunctionInvokeDescriptor) return false
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||
return classDescriptor.defaultType.isBuiltinFunctionalType
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.debugger.test
|
||||
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.KotlinSmartStepIntoHandler
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto.KotlinSmartStepIntoHandler
|
||||
import org.jetbrains.kotlin.idea.debugger.test.mock.MockSourcePosition
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ import com.intellij.debugger.impl.PositionUtil
|
||||
import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.sun.jdi.request.StepRequest
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.*
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto.KotlinSmartStepIntoHandler
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.SteppingInstruction
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.SteppingInstructionKind
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.renderSourcePosition
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesState"/>
|
||||
|
||||
<debugger.asyncStackTraceProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinCoroutinesAsyncStackTraceProvider"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.positionManagerFactory implementation="org.jetbrains.kotlin.idea.debugger.KotlinPositionManagerFactory"/>
|
||||
<debugger.codeFragmentFactory implementation="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory"/>
|
||||
<debuggerEditorTextProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider"/>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesState"/>
|
||||
|
||||
<debugger.asyncStackTraceProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinCoroutinesAsyncStackTraceProvider"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.positionManagerFactory implementation="org.jetbrains.kotlin.idea.debugger.KotlinPositionManagerFactory"/>
|
||||
<debugger.codeFragmentFactory implementation="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory"/>
|
||||
<debuggerEditorTextProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider"/>
|
||||
|
||||
Reference in New Issue
Block a user