diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt index a7b5dfa907b..7428a598d2b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerUtils.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.idea.debugger -import com.google.common.collect.Sets import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtilRt import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.KotlinFileTypeFactory +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.JvmClassName -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor import java.util.* @@ -101,14 +100,12 @@ object DebuggerUtils { fun analyzeInlinedFunctions( resolutionFacadeForFile: ResolutionFacade, - bindingContextForFile: BindingContext, file: KtFile, analyzeOnlyReifiedInlineFunctions: Boolean ): Pair> { val analyzedElements = HashSet() val context = analyzeElementWithInline( resolutionFacadeForFile, - bindingContextForFile, file, 1, analyzedElements, @@ -127,30 +124,30 @@ object DebuggerUtils { return Pair>(context, ArrayList(toProcess)) } - fun analyzeElementWithInline( - resolutionFacade: ResolutionFacade, - bindingContext: BindingContext, - function: KtNamedFunction, - analyzeInlineFunctions: Boolean): Collection { + fun analyzeElementWithInline(function: KtNamedFunction, analyzeInlineFunctions: Boolean): Collection { val analyzedElements = HashSet() - analyzeElementWithInline(resolutionFacade, bindingContext, function, 1, analyzedElements, !analyzeInlineFunctions) + analyzeElementWithInline(function.getResolutionFacade(), function, 1, analyzedElements, !analyzeInlineFunctions) return analyzedElements } private fun analyzeElementWithInline( resolutionFacade: ResolutionFacade, - bindingContext: BindingContext, element: KtElement, deep: Int, analyzedElements: MutableSet, analyzeInlineFunctions: Boolean): BindingContext { val project = element.project - val collectedElements = HashSet() + val inlineFunctions = HashSet() + + val innerContexts = ArrayList() element.accept(object : KtTreeVisitorVoid() { override fun visitExpression(expression: KtExpression) { super.visitExpression(expression) + val bindingContext = resolutionFacade.analyze(expression) + innerContexts.add(bindingContext) + val call = bindingContext.get(BindingContext.CALL, expression) ?: return val resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, call) @@ -160,6 +157,9 @@ object DebuggerUtils { override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) { super.visitDestructuringDeclaration(destructuringDeclaration) + val bindingContext = resolutionFacade.analyze(destructuringDeclaration) + innerContexts.add(bindingContext) + for (entry in destructuringDeclaration.entries) { val resolvedCall = bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, entry) checkResolveCall(resolvedCall) @@ -169,6 +169,9 @@ object DebuggerUtils { override fun visitForExpression(expression: KtForExpression) { super.visitForExpression(expression) + val bindingContext = resolutionFacade.analyze(expression) + innerContexts.add(bindingContext) + checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, expression.loopRange)) checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression.loopRange)) checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, expression.loopRange)) @@ -183,7 +186,7 @@ object DebuggerUtils { if (InlineUtil.isInline(descriptor) && (analyzeInlineFunctions || hasReifiedTypeParameters(descriptor))) { val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) if (declaration != null && declaration is KtNamedFunction && !analyzedElements.contains(declaration)) { - collectedElements.add(declaration) + inlineFunctions.add(declaration) } } } @@ -191,24 +194,18 @@ object DebuggerUtils { analyzedElements.add(element) - if (!collectedElements.isEmpty() && deep < 10) { - val innerContexts = ArrayList() - for (inlineFunctions in collectedElements) { - val body = inlineFunctions.bodyExpression + if (!inlineFunctions.isEmpty() && deep < 10) { + for (inlineFunction in inlineFunctions) { + val body = inlineFunction.bodyExpression if (body != null) { - val bindingContextForFunction = resolutionFacade.analyze(body, BodyResolveMode.FULL) - innerContexts.add(analyzeElementWithInline(resolutionFacade, bindingContextForFunction, inlineFunctions, deep + 1, - analyzedElements, analyzeInlineFunctions)) + innerContexts.add(analyzeElementWithInline(resolutionFacade, inlineFunction, deep + 1, analyzedElements, analyzeInlineFunctions)) } } - innerContexts.add(bindingContext) - - analyzedElements.addAll(collectedElements) - return CompositeBindingContext.create(innerContexts) + analyzedElements.addAll(inlineFunctions) } - return bindingContext + return CompositeBindingContext.create(innerContexts) } private fun hasReifiedTypeParameters(descriptor: CallableDescriptor): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index 78f7647c70f..0ece2a6c2d3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -88,7 +88,7 @@ internal val GENERATED_FUNCTION_NAME = "generated_for_debugger_kotlin_rulezzzz" private val DEBUG_MODE = false -object KotlinEvaluationBuilder: EvaluatorBuilder { +object KotlinEvaluationBuilder : EvaluatorBuilder { override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator { if (codeFragment !is KtCodeFragment || position == null) { return EvaluatorBuilderImpl.getInstance()!!.build(codeFragment, position) @@ -121,7 +121,7 @@ object KotlinEvaluationBuilder: EvaluatorBuilder { } } -class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: SourcePosition): Evaluator { +class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: SourcePosition) : Evaluator { override fun evaluate(context: EvaluationContextImpl): Any? { if (codeFragment.text.isEmpty()) { return context.debugProcess.virtualMachineProxy.mirrorOfVoid() @@ -163,9 +163,9 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour Attachment("context.info", text)) LOG.error(LogMessageEx.createEvent( - "Couldn't evaluate expression", - ExceptionUtil.getThrowableText(e), - mergeAttachments(*attachments))) + "Couldn't evaluate expression", + ExceptionUtil.getThrowableText(e), + mergeAttachments(*attachments))) val cause = if (e.message != null) ": ${e.message}" else "" exception("An exception occurs during Evaluate Expression Action $cause") @@ -195,7 +195,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour codeFragment.checkForErrors() val extractionResult = getFunctionForExtractedFragment(codeFragment, sourcePosition.file, sourcePosition.line) - ?: throw IllegalStateException("Code fragment cannot be extracted to function: ${codeFragment.text}") + ?: throw IllegalStateException("Code fragment cannot be extracted to function: ${codeFragment.text}") val parametersDescriptor = extractionResult.getParametersForDebugger(codeFragment) val extractedFunction = extractionResult.declaration as KtNamedFunction @@ -325,7 +325,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour val contextElementFile = fragment.context?.containingFile if (contextElementFile is KtCodeFragment) { - contextElementFile.accept(object: KtTreeVisitorVoid() { + contextElementFile.accept(object : KtTreeVisitorVoid() { override fun visitProperty(property: KtProperty) { val value = property.getUserData(KotlinCodeFragmentFactory.LABEL_VARIABLE_VALUE_KEY) if (value != null) { @@ -435,7 +435,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour val declarationDescriptor = paramAnonymousType.constructor.declarationDescriptor if (declarationDescriptor is ClassDescriptor) { val localVariable = visitor.findValue(localVariableName, asmType = null, checkType = false, failIfNotFound = false) - ?: exception("Couldn't find local variable this in current frame to get classType for anonymous type $paramAnonymousType}") + ?: exception("Couldn't find local variable this in current frame to get classType for anonymous type $paramAnonymousType}") record(CodegenBinding.ASM_TYPE, declarationDescriptor, localVariable.asmType) if (LOG.isDebugEnabled) { LOG.debug("Asm type ${localVariable.asmType.className} was recorded for ${declarationDescriptor.name}") @@ -474,7 +474,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour } if (analyzeInlineFunctions) { - val (newBindingContext, files) = DebuggerUtils.analyzeInlinedFunctions(resolutionFacade, bindingContext, this, false) + val (newBindingContext, files) = DebuggerUtils.analyzeInlinedFunctions(resolutionFacade, this, false) ExtendedAnalysisResult(newBindingContext, analysisResult.moduleDescriptor, files) } else { diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt index 87b6e61e420..2f668de648f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt @@ -181,13 +181,7 @@ private fun getInlineFunctionsIfAny(file: KtFile, offset: Int): List() - + val inlineFunctionsCalls = DebuggerUtils.analyzeElementWithInline(containingFunction, false).filterIsInstance() return inlineFunctionsCalls } diff --git a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java index 96ae29f0b81..42e6866a008 100644 --- a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java +++ b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java @@ -292,10 +292,8 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable { ) { ResolutionFacade resolutionFacade = ResolutionUtils.getResolutionFacade(ktFile); - BindingContext bindingContextForFile = resolutionFacade.analyzeFullyAndGetResult(Collections.singletonList(ktFile)).getBindingContext(); - kotlin.Pair> result = DebuggerUtils.INSTANCE.analyzeInlinedFunctions( - resolutionFacade, bindingContextForFile, ktFile, configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE) + resolutionFacade, ktFile, configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE) ); BindingContext bindingContext = result.getFirst();