void (@NotNull PsiReferenceExpression expression) { if (LOG.isDebugEnabled()) { LOG.debug("visitReferenceExpression " + expression); } PsiExpression qualifier = expression.getQualifierExpression(); JavaResolveResult resolveResult = expression.advancedResolve(true); PsiElement element = resolveResult.getElement(); if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { final Value labeledValue = element.getUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY); if (labeledValue != null) { myResult = new IdentityEvaluator(labeledValue); return; } final PsiVariable psiVar = (PsiVariable)element; String localName = psiVar.getName(); //synthetic variable final PsiFile containingFile = element.getContainingFile(); if (myCurrentFragmentEvaluator != null && ((containingFile instanceof PsiCodeFragment && myVisitedFragments.contains(containingFile)) || myCurrentFragmentEvaluator.hasValue(localName))) { // psiVariable may live in PsiCodeFragment not only in debugger editors, for example Fabrique has such variables. // So treat it as synthetic var only when this code fragment is located in DebuggerEditor, // that's why we need to check that containing code fragment is the one we visited JVMName jvmName = JVMNameUtil.getJVMQualifiedName(CompilingEvaluatorTypesUtil.getVariableType((PsiVariable)element)); myResult = new SyntheticVariableEvaluator(myCurrentFragmentEvaluator, localName, jvmName); return; } // local variable PsiClass variableClass = getContainingClass(psiVar); final PsiClass positionClass = getPositionClass(); if (Objects.equals(positionClass, variableClass)) { PsiElement method = DebuggerUtilsEx.getContainingMethod(expression); boolean canScanFrames = method instanceof PsiLambdaExpression || ContextUtil.isJspImplicit(element); myResult = new LocalVariableEvaluator(localName, canScanFrames); return; } // the expression references final var outside the context's class (in some of the outer classes) // oneLevelLess() because val$ are located in the same class CaptureTraverser traverser = createTraverser(variableClass, "Base class not found for " + psiVar.getName(), false).oneLevelLess(); if (traverser.isValid()) { PsiExpression initializer = psiVar.getInitializer(); if (initializer != null) { Object value = JavaPsiFacade.getInstance(psiVar.getProject()).getConstantEvaluationHelper().computeConstantExpression(initializer); if (value != null) { PsiType type = resolveResult.getSubstitutor().substitute(psiVar.getType()); myResult = new LiteralEvaluator(value, type.getCanonicalText()); return; } } Evaluator objectEvaluator = new ThisEvaluator(traverser); myResult = createFallbackEvaluator( new FieldEvaluator(objectEvaluator, FieldEvaluator.createClassFilter(positionClass), "val$" + localName), new LocalVariableEvaluator(localName, true)); return; } throw evaluateException(JavaDebuggerBundle.message("evaluation.error.local.variable.missing.from.class.closure", localName)); } else if (element instanceof PsiField psiField) { final PsiClass fieldClass = psiField.getContainingClass(); if (fieldClass == null) { throw evaluateException(JavaDebuggerBundle.message("evaluation.error.cannot.resolve.field.class", psiField.getName())); } Evaluator objectEvaluator; if (psiField.hasModifierProperty(PsiModifier.STATIC)) { JVMName className = JVMNameUtil.getContextClassJVMQualifiedName(SourcePosition.createFromElement(psiField)); if (className == null) { className = JVMNameUtil.getJVMQualifiedName(fieldClass); } objectEvaluator = new TypeEvaluator(className); } else if (qualifier != null) { qualifier.accept(this); objectEvaluator = myResult; } else { CaptureTraverser traverser = createTraverser(fieldClass, fieldClass.getName(), true); if (!traverser.isValid()) { throw evaluateException(JavaDebuggerBundle.message("evaluation.error.cannot.sources.for.field.class", psiField.getName())); } objectEvaluator = new ThisEvaluator(traverser); } myResult = new FieldEvaluator(objectEvaluator, FieldEvaluator.createClassFilter(fieldClass), psiField.getName()); } else { //let's guess what this could be PsiElement nameElement = expression.getReferenceNameElement(); // get "b" part String name; if (nameElement instanceof PsiIdentifier) { name = nameElement.getText(); } else { final String elementDisplayString = nameElement != null ? nameElement.getText() : "(null)"; throw evaluateException(JavaDebuggerBundle.message("evaluation.error.identifier.expected", elementDisplayString)); } if (qualifier != null) { final PsiElement qualifierTarget = qualifier instanceof PsiReferenceExpression ? ((PsiReferenceExpression)qualifier).resolve() : null; if (qualifierTarget instanceof PsiClass psiClass) { // this is a call to a 'static' field final JVMName typeName = JVMNameUtil.getJVMQualifiedName(psiClass); myResult = new FieldEvaluator(new TypeEvaluator(typeName), FieldEvaluator.createClassFilter(psiClass), name); } else { qualifier.accept(this); if (myResult == null) { throw evaluateException(JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.qualifier", qualifier.getText())); } myResult = new FieldEvaluator(myResult, FieldEvaluator.createClassFilter(qualifier.getType()), name); } } else { myResult = createFallbackEvaluator(new LocalVariableEvaluator(name, false), new FieldEvaluator(new ThisEvaluator(), FieldEvaluator.TargetClassFilter.ALL, name)); } } }