[debugger dfa] Refactor: join read actions where possible

GitOrigin-RevId: 5f89163a61e1358590fe43af3a719a970bfd0848
This commit is contained in:
Maksim Zuev
2025-06-28 09:54:16 +00:00
committed by intellij-monorepo-bot
parent 343aaf5b53
commit 720a59914d
3 changed files with 68 additions and 56 deletions
@@ -25,21 +25,23 @@ private class JavaDfaAssistProvider : DfaAssistProvider {
val method = location.method()
val methodName = method.name()
val methodArgumentsSize = method.argumentTypeNames().size
val context = readAction { DebuggerUtilsEx.getContainingMethod(element) }
if (context is PsiMethod) {
return readAction {
val name = if (context.isConstructor()) "<init>" else context.getName()
name == methodName && context.getParameterList().getParametersCount() == methodArgumentsSize
val isLambda = DebuggerUtilsEx.isLambda(method)
return readAction {
when (val context = DebuggerUtilsEx.getContainingMethod(element)) {
is PsiMethod -> {
val name = if (context.isConstructor()) "<init>" else context.getName()
name == methodName && context.getParameterList().getParametersCount() == methodArgumentsSize
}
is PsiLambdaExpression -> {
isLambda && methodArgumentsSize >= context.getParameterList().getParametersCount()
}
is PsiClassInitializer -> {
val expectedMethod = if (context.hasModifierProperty(PsiModifier.STATIC)) "<clinit>" else "<init>"
methodName == expectedMethod
}
else -> false
}
}
if (context is PsiLambdaExpression) {
return DebuggerUtilsEx.isLambda(method) && readAction { methodArgumentsSize >= context.getParameterList().getParametersCount() }
}
if (context is PsiClassInitializer) {
val expectedMethod = readAction { if (context.hasModifierProperty(PsiModifier.STATIC)) "<clinit>" else "<init>" }
return methodName == expectedMethod
}
return false
}
override fun getAnchor(element: PsiElement): PsiElement? {
@@ -111,8 +113,10 @@ private class JavaDfaAssistProvider : DfaAssistProvider {
return captureTraverser.traverse(proxy.thisObject())
}
if (psi is PsiLocalVariable || psi is PsiParameter) {
val varName: String = readAction { psi.getName()!! }
val resolveVariable = readAction { PsiResolveHelper.getInstance(psi.getProject()).resolveReferencedVariable(varName, anchor) }
val (varName, resolveVariable) = readAction {
val name = psi.getName()!!
name to PsiResolveHelper.getInstance(psi.getProject()).resolveReferencedVariable(name, anchor)
}
if (resolveVariable !== psi) {
// Another variable with the same name could be tracked by DFA in different code branch but not visible at current code location
return null
@@ -137,18 +141,21 @@ private class JavaDfaAssistProvider : DfaAssistProvider {
}
}
}
if (psi is PsiField && readAction { psi.hasModifierProperty(PsiModifier.STATIC) }) {
val psiClass = readAction { psi.getContainingClass() }
if (psiClass != null) {
val name = readAction { psiClass.getQualifiedName() }
if (name != null) {
val type = ContainerUtil.getOnlyItem(proxy.getVirtualMachine().classesByName(name))
if (type != null && type.isPrepared) {
val field = DebuggerUtils.findField(type, readAction { psi.getName() })
if (field != null && field.isStatic) {
return wrap(type.getValue(field))
}
}
val fieldData = readAction {
if (psi !is PsiField) return@readAction null
if (!psi.hasModifierProperty(PsiModifier.STATIC)) return@readAction null
val psiClass = psi.getContainingClass() ?: return@readAction null
val name = psiClass.getQualifiedName() ?: return@readAction null
val fieldName = psi.getName()
name to fieldName
}
if (fieldData != null) {
val (className, fieldName) = fieldData
val type = ContainerUtil.getOnlyItem(proxy.getVirtualMachine().classesByName(className))
if (type != null && type.isPrepared) {
val field = DebuggerUtils.findField(type, fieldName)
if (field != null && field.isStatic) {
return wrap(type.getValue(field))
}
}
}
@@ -177,18 +184,16 @@ private class JavaDfaAssistProvider : DfaAssistProvider {
}
is ObjectReference -> {
val type = qualifier.referenceType()
val typeName = type.name()
for (descriptor in descriptors) {
val element = readAction { descriptor.psiElement }
if (element is PsiField) {
val psiClass = readAction { element.getContainingClass() }
if (psiClass != null && type.name() == readAction { JVMNameUtil.getClassVMName(psiClass) }) {
val field = DebuggerUtils.findField(type, readAction { element.getName() })
if (field != null) {
map[descriptor] = wrap(qualifier.getValue(field))
continue
}
}
}
val fieldName = readAction {
val element = descriptor.psiElement as? PsiField ?: return@readAction null
val psiClass = element.getContainingClass() ?: return@readAction null
if (typeName != JVMNameUtil.getClassVMName(psiClass)) return@readAction null
element.getName()
} ?: continue
val field = DebuggerUtils.findField(type, fieldName) ?: continue
map[descriptor] = wrap(qualifier.getValue(field))
}
}
}
@@ -93,10 +93,11 @@ private class KotlinDfaAssistProvider : DfaAssistProvider {
}
}
return null
}
else if (descriptor is KtVariableDescriptor) {
val psiVariable = readAction { descriptor.psiElement }
val name = readAction { (psiVariable as KtNamedDeclaration).name }
} else if (descriptor is KtVariableDescriptor) {
val name = readAction {
val psiVariable = descriptor.psiElement as? KtNamedDeclaration ?: return@readAction null
psiVariable.name
}
val variable = proxy.visibleVariableByName(name)
if (variable != null) {
return postprocess(proxy.getVariableValue(variable))
@@ -115,14 +116,12 @@ private class KotlinDfaAssistProvider : DfaAssistProvider {
// Avoid relying on hashCode/equals, as descriptors are known to be deduplicated here
val map = IdentityHashMap<VariableDescriptor, Value>()
for (descriptor in descriptors) {
val psiVariable = readAction { descriptor.psiElement }
if (psiVariable is KtCallableDeclaration) {
val name = readAction { psiVariable.name }
val field = name?.let { DebuggerUtils.findField(qualifier.referenceType(), it) }
if (field != null) {
map[descriptor] = postprocess(qualifier.getValue(field))
}
}
val name = readAction {
val psiVariable = descriptor.psiElement as? KtCallableDeclaration ?: return@readAction null
psiVariable.name
} ?: continue
val field = DebuggerUtils.findField(qualifier.referenceType(), name) ?: continue
map[descriptor] = postprocess(qualifier.getValue(field))
}
return map
}
@@ -97,7 +97,11 @@ private class K2DfaAssistProvider : DfaAssistProvider {
return value
}
private suspend fun getJdiValueForDfaVariableInner(proxy: StackFrameProxyEx, descriptor: VariableDescriptor, anchor: KtElement): Value? {
private suspend fun getJdiValueForDfaVariableInner(
proxy: StackFrameProxyEx,
descriptor: VariableDescriptor,
anchor: KtElement
): Value? {
val variables = (proxy as StackFrameProxyImpl).visibleVariables()
val inlineDepth = getInlineDepth(variables)
val inlineSuffix = KotlinDebuggerConstants.INLINE_FUN_VAR_SUFFIX.repeat(inlineDepth)
@@ -197,11 +201,13 @@ private class K2DfaAssistProvider : DfaAssistProvider {
var variable = proxy.visibleVariableByName(result.name)
var value: Value? = null
if (variable == null) {
val psi = result.psi
val scope = readAction { anchor.getScope() }
if (psi != null && scope != null
&& readAction { psi.containingFile == scope.containingFile && !scope.isAncestor(psi) }
) {
val isValidScope = readAction {
val psi = result.psi ?: return@readAction false
val scope = anchor.getScope()
scope != null && psi.containingFile == scope.containingFile
&& !scope.isAncestor(psi)
}
if (isValidScope) {
// Captured variable
val capturedName = AsmUtil.CAPTURED_PREFIX + result.name
variable = proxy.visibleVariableByName(capturedName)
@@ -301,6 +307,7 @@ private class K2DfaAssistProvider : DfaAssistProvider {
QualifierVariableResult.InlineClassProperty -> {
map[descriptor] = if (qualifier is DfaAssistProvider.InlinedValue) qualifier.value else qualifier
}
is QualifierVariableResult.NamedVariable -> {
val type = (qualifier as? ObjectReference)?.referenceType()
if (type != null) {
@@ -310,6 +317,7 @@ private class K2DfaAssistProvider : DfaAssistProvider {
}
}
}
else -> {}
}
}