mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-366620 Evaluate and log works incorrectly in concurrent scenario
Merge-request: IJ-MR-154018 Merged-by: Egor Ushakov <Egor.Ushakov@jetbrains.com> GitOrigin-RevId: 8b73b6442426fd45dde9b74f3989bb848cd7c401
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5d3d9e3059
commit
11d74fb190
+55
-55
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-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 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
/*
|
||||
* Class ArrayAccessEvaluator
|
||||
@@ -29,11 +15,16 @@ import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl;
|
||||
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class ArrayAccessEvaluator implements Evaluator {
|
||||
class ArrayAccessEvaluator implements ModifiableEvaluator {
|
||||
private final Evaluator myArrayReferenceEvaluator;
|
||||
private final Evaluator myIndexEvaluator;
|
||||
|
||||
// TODO remove non-final fields, see IDEA-366793
|
||||
@Deprecated
|
||||
private ArrayReference myEvaluatedArrayReference;
|
||||
@Deprecated
|
||||
private int myEvaluatedIndex;
|
||||
|
||||
ArrayAccessEvaluator(Evaluator arrayReferenceEvaluator, Evaluator indexEvaluator) {
|
||||
@@ -42,21 +33,21 @@ class ArrayAccessEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
myEvaluatedIndex = 0;
|
||||
myEvaluatedArrayReference = null;
|
||||
Value indexValue = (Value)myIndexEvaluator.evaluate(context);
|
||||
Value arrayValue = (Value)myArrayReferenceEvaluator.evaluate(context);
|
||||
if (!(arrayValue instanceof ArrayReference)) {
|
||||
public @NotNull ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
if (!(myArrayReferenceEvaluator.evaluate(context) instanceof ArrayReference evaluatedArrayReference)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.array.reference.expected"));
|
||||
}
|
||||
myEvaluatedArrayReference = (ArrayReference)arrayValue;
|
||||
Value indexValue = (Value)myIndexEvaluator.evaluate(context);
|
||||
if (!DebuggerUtils.isInteger(indexValue)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.invalid.index.expression"));
|
||||
}
|
||||
myEvaluatedIndex = ((PrimitiveValue)indexValue).intValue();
|
||||
int evaluatedIndex = ((PrimitiveValue)indexValue).intValue();
|
||||
|
||||
try {
|
||||
return myEvaluatedArrayReference.getValue(myEvaluatedIndex);
|
||||
Value value = evaluatedArrayReference.getValue(evaluatedIndex);
|
||||
myEvaluatedArrayReference = evaluatedArrayReference;
|
||||
myEvaluatedIndex = evaluatedIndex;
|
||||
return new ModifiableValue(value, new MyModifier(evaluatedArrayReference, evaluatedIndex));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e);
|
||||
@@ -65,41 +56,50 @@ class ArrayAccessEvaluator implements Evaluator {
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
Modifier modifier = null;
|
||||
if (myEvaluatedArrayReference != null) {
|
||||
modifier = new Modifier() {
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return true;
|
||||
}
|
||||
return new MyModifier(myEvaluatedArrayReference, myEvaluatedIndex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
private static class MyModifier implements Modifier {
|
||||
private final ArrayReference myEvaluatedArrayReference;
|
||||
private final int myEvaluatedIndex;
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
myEvaluatedArrayReference.setValue(myEvaluatedIndex, value);
|
||||
}
|
||||
private MyModifier(ArrayReference evaluatedArrayReference, int evaluatedIndex) {
|
||||
myEvaluatedArrayReference = evaluatedArrayReference;
|
||||
myEvaluatedIndex = evaluatedIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws EvaluateException {
|
||||
try {
|
||||
ArrayType type = (ArrayType)myEvaluatedArrayReference.referenceType();
|
||||
return type.componentType();
|
||||
}
|
||||
catch (ClassNotLoadedException e) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return new ArrayElementDescriptorImpl(project, myEvaluatedArrayReference, myEvaluatedIndex);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
myEvaluatedArrayReference.setValue(myEvaluatedIndex, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws EvaluateException {
|
||||
try {
|
||||
ArrayType type = (ArrayType)myEvaluatedArrayReference.referenceType();
|
||||
return type.componentType();
|
||||
}
|
||||
catch (ClassNotLoadedException e) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return new ArrayElementDescriptorImpl(project, myEvaluatedArrayReference, myEvaluatedIndex);
|
||||
}
|
||||
return modifier;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.JavaDebuggerBundle;
|
||||
@@ -8,7 +8,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AssignmentEvaluator implements Evaluator {
|
||||
public class AssignmentEvaluator implements ModifiableEvaluator {
|
||||
private final Evaluator myLeftEvaluator;
|
||||
private final Evaluator myRightEvaluator;
|
||||
|
||||
@@ -18,9 +18,8 @@ public class AssignmentEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
myLeftEvaluator.evaluate(context);
|
||||
final Modifier modifier = myLeftEvaluator.getModifier();
|
||||
public @NotNull ModifiableValue evaluateModifiable(@NotNull EvaluationContextImpl context) throws EvaluateException {
|
||||
Modifier modifier = myLeftEvaluator.evaluateModifiable(context).getModifier();
|
||||
|
||||
final Object right = myRightEvaluator.evaluate(context);
|
||||
if (right != null && !(right instanceof Value)) {
|
||||
@@ -29,7 +28,7 @@ public class AssignmentEvaluator implements Evaluator {
|
||||
|
||||
assign(modifier, right, context);
|
||||
|
||||
return right;
|
||||
return new ModifiableValue(right, modifier);
|
||||
}
|
||||
|
||||
static void assign(Modifier modifier, Object right, EvaluationContextImpl context) throws EvaluateException {
|
||||
|
||||
+6
-5
@@ -1,10 +1,11 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BlockStatementEvaluator implements Evaluator {
|
||||
public class BlockStatementEvaluator implements ModifiableEvaluator {
|
||||
protected Evaluator[] myStatements;
|
||||
|
||||
public BlockStatementEvaluator(Evaluator[] statements) {
|
||||
@@ -12,10 +13,10 @@ public class BlockStatementEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object result = context.getVirtualMachineProxy().mirrorOfVoid();
|
||||
public @NotNull ModifiableValue evaluateModifiable(@NotNull EvaluationContextImpl context) throws EvaluateException {
|
||||
ModifiableValue result = new ModifiableValue(context.getVirtualMachineProxy().mirrorOfVoid(), null);
|
||||
for (Evaluator statement : myStatements) {
|
||||
result = statement.evaluate(context);
|
||||
result = statement.evaluateModifiable(context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class DeconstructionPatternEvaluator extends PatternEvaluator {
|
||||
res = componentEvaluator.match(objRef.getValue(field), context);
|
||||
}
|
||||
if (res && myVariableEvaluator != null) {
|
||||
AssignmentEvaluator.assign(myVariableEvaluator.getModifier(), value, context);
|
||||
AssignmentEvaluator.assign(myVariableEvaluator.evaluateModifiable(context).getModifier(), value, context);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
+19
-7
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
*/
|
||||
public final class DisableGC implements Evaluator {
|
||||
public final class DisableGC implements ModifiableEvaluator {
|
||||
private final Evaluator myDelegate;
|
||||
|
||||
private DisableGC(@NotNull Evaluator delegate) {
|
||||
@@ -24,12 +24,24 @@ public final class DisableGC implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
final Object result = myDelegate.evaluate(context);
|
||||
if (result instanceof ObjectReference) {
|
||||
context.getSuspendContext().keep((ObjectReference)result);
|
||||
public @NotNull ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
if (myDelegate instanceof ModifiableEvaluator modifiableEvaluator) {
|
||||
ModifiableValue result = modifiableEvaluator.evaluateModifiable(context);
|
||||
Object value = result.getValue();
|
||||
keep(context, value);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Object value = myDelegate.evaluate(context);
|
||||
keep(context, value);
|
||||
return new ModifiableValue(value, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void keep(EvaluationContextImpl context, Object value) {
|
||||
if (value instanceof ObjectReference reference) {
|
||||
context.keep(reference);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-6
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
@@ -15,11 +15,6 @@ public class DoWhileStatementEvaluator extends LoopEvaluator {
|
||||
myConditionEvaluator = DisableGC.create(conditionEvaluator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return myConditionEvaluator.getModifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object value = context.getVirtualMachineProxy().mirrorOfVoid();
|
||||
|
||||
+15
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
/*
|
||||
* Interface Evaluator
|
||||
@@ -10,14 +10,27 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
|
||||
public interface Evaluator {
|
||||
Object evaluate(EvaluationContextImpl context) throws EvaluateException;
|
||||
default Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
throw new AbstractMethodError("evaluate or evaluateModifiable must be implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement if the value may be modified (like local variable or a field)
|
||||
*/
|
||||
default ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
return new ModifiableValue(evaluate(context), getModifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to obtain a modifier the expression must be evaluated first
|
||||
*
|
||||
* @return a modifier object allowing to set a value in case the expression is lvalue,
|
||||
* otherwise null is returned
|
||||
*
|
||||
* @deprecated implement {@link #evaluateModifiable(EvaluationContextImpl)} instead
|
||||
* @see ModifiableEvaluator
|
||||
*/
|
||||
@Deprecated
|
||||
default Modifier getModifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
+4
-4
@@ -936,17 +936,17 @@ public final class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
}
|
||||
|
||||
private static Evaluator createFallbackEvaluator(final Evaluator primary, final Evaluator fallback) {
|
||||
return new Evaluator() {
|
||||
return new ModifiableEvaluator() {
|
||||
private boolean myIsFallback;
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
public @NotNull ModifiableValue evaluateModifiable(@NotNull EvaluationContextImpl context) throws EvaluateException {
|
||||
try {
|
||||
return primary.evaluate(context);
|
||||
return primary.evaluateModifiable(context);
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
try {
|
||||
Object res = fallback.evaluate(context);
|
||||
ModifiableValue res = fallback.evaluateModifiable(context);
|
||||
myIsFallback = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
+62
-53
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
/*
|
||||
* Class FieldEvaluator
|
||||
@@ -25,11 +25,15 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FieldEvaluator implements Evaluator {
|
||||
public class FieldEvaluator implements ModifiableEvaluator {
|
||||
private final Evaluator myObjectEvaluator;
|
||||
private final TargetClassFilter myTargetClassFilter;
|
||||
private final String myFieldName;
|
||||
|
||||
// TODO remove non-final fields, see IDEA-366793
|
||||
@Deprecated
|
||||
private Object myEvaluatedQualifier;
|
||||
@Deprecated
|
||||
private Field myEvaluatedField;
|
||||
|
||||
public interface TargetClassFilter {
|
||||
@@ -94,15 +98,9 @@ public class FieldEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
myEvaluatedField = null;
|
||||
myEvaluatedQualifier = null;
|
||||
public @NotNull ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object object = myObjectEvaluator.evaluate(context);
|
||||
|
||||
return evaluateField(object, context);
|
||||
}
|
||||
|
||||
private Object evaluateField(Object object, EvaluationContextImpl context) throws EvaluateException {
|
||||
if (object instanceof ReferenceType refType) {
|
||||
Field field = findField(refType);
|
||||
if (field == null || !field.isStatic()) {
|
||||
@@ -111,9 +109,10 @@ public class FieldEvaluator implements Evaluator {
|
||||
if (field == null || !field.isStatic()) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.no.static.field", myFieldName));
|
||||
}
|
||||
MyModifier modifier = new MyModifier(refType, field);
|
||||
myEvaluatedField = field;
|
||||
myEvaluatedQualifier = refType;
|
||||
return refType.getValue(field);
|
||||
return new ModifiableValue(refType.getValue(field), modifier);
|
||||
}
|
||||
|
||||
if (object instanceof ObjectReference objRef) {
|
||||
@@ -125,7 +124,7 @@ public class FieldEvaluator implements Evaluator {
|
||||
|
||||
// expressions like 'array.length' must be treated separately
|
||||
if (objRef instanceof ArrayReference && "length".equals(myFieldName)) {
|
||||
return context.getVirtualMachineProxy().mirrorOf(((ArrayReference)objRef).length());
|
||||
return new ModifiableValue(context.getVirtualMachineProxy().mirrorOf(((ArrayReference)objRef).length()), null);
|
||||
}
|
||||
|
||||
Field field = findField(refType);
|
||||
@@ -136,9 +135,11 @@ public class FieldEvaluator implements Evaluator {
|
||||
if (field == null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.no.instance.field", myFieldName));
|
||||
}
|
||||
myEvaluatedQualifier = field.isStatic() ? refType : objRef;
|
||||
Object qualifier = field.isStatic() ? refType : objRef;
|
||||
MyModifier modifier = new MyModifier(qualifier, field);
|
||||
myEvaluatedQualifier = qualifier;
|
||||
myEvaluatedField = field;
|
||||
return field.isStatic() ? refType.getValue(field) : objRef.getValue(field);
|
||||
return new ModifiableValue(field.isStatic() ? refType.getValue(field) : objRef.getValue(field), modifier);
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
@@ -150,48 +151,10 @@ public class FieldEvaluator implements Evaluator {
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
Modifier modifier = null;
|
||||
if (myEvaluatedField != null && (myEvaluatedQualifier instanceof ClassType || myEvaluatedQualifier instanceof ObjectReference)) {
|
||||
modifier = new Modifier() {
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return myEvaluatedQualifier instanceof ObjectReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
if (myEvaluatedQualifier instanceof ReferenceType) {
|
||||
ClassType classType = (ClassType)myEvaluatedQualifier;
|
||||
classType.setValue(myEvaluatedField, value);
|
||||
}
|
||||
else {
|
||||
ObjectReference objRef = (ObjectReference)myEvaluatedQualifier;
|
||||
objRef.setValue(myEvaluatedField, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws ClassNotLoadedException {
|
||||
return myEvaluatedField.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
if (myEvaluatedQualifier instanceof ObjectReference) {
|
||||
return new FieldDescriptorImpl(project, (ObjectReference)myEvaluatedQualifier, myEvaluatedField);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new MyModifier(myEvaluatedQualifier, myEvaluatedField);
|
||||
}
|
||||
return modifier;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,4 +201,50 @@ public class FieldEvaluator implements Evaluator {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyModifier implements Modifier {
|
||||
private final Object myEvaluatedQualifier;
|
||||
private final Field myEvaluatedField;
|
||||
|
||||
private MyModifier(Object qualifier, Field field) {
|
||||
myEvaluatedQualifier = qualifier;
|
||||
myEvaluatedField = field; }
|
||||
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return myEvaluatedQualifier instanceof ObjectReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
if (myEvaluatedQualifier instanceof ReferenceType) {
|
||||
ClassType classType = (ClassType)myEvaluatedQualifier;
|
||||
classType.setValue(myEvaluatedField, value);
|
||||
}
|
||||
else {
|
||||
ObjectReference objRef = (ObjectReference)myEvaluatedQualifier;
|
||||
objRef.setValue(myEvaluatedField, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws ClassNotLoadedException {
|
||||
return myEvaluatedField.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
if (myEvaluatedQualifier instanceof ObjectReference) {
|
||||
return new FieldDescriptorImpl(project, (ObjectReference)myEvaluatedQualifier, myEvaluatedField);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-29
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
@@ -23,8 +9,6 @@ public class ForStatementEvaluator extends ForStatementEvaluatorBase {
|
||||
private final Evaluator myConditionEvaluator;
|
||||
private final Evaluator myUpdateEvaluator;
|
||||
|
||||
private Modifier myModifier;
|
||||
|
||||
public ForStatementEvaluator(Evaluator initializationEvaluator,
|
||||
Evaluator conditionEvaluator,
|
||||
Evaluator updateEvaluator,
|
||||
@@ -36,16 +20,10 @@ public class ForStatementEvaluator extends ForStatementEvaluatorBase {
|
||||
myUpdateEvaluator = updateEvaluator != null ? DisableGC.create(updateEvaluator) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return myModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object evaluateInitialization(EvaluationContextImpl context, Object value) throws EvaluateException {
|
||||
if (myInitializationEvaluator != null) {
|
||||
value = myInitializationEvaluator.evaluate(context);
|
||||
myModifier = myInitializationEvaluator.getModifier();
|
||||
return myInitializationEvaluator.evaluate(context);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -53,9 +31,7 @@ public class ForStatementEvaluator extends ForStatementEvaluatorBase {
|
||||
@Override
|
||||
protected Object evaluateCondition(EvaluationContextImpl context) throws EvaluateException {
|
||||
if (myConditionEvaluator != null) {
|
||||
Object value = myConditionEvaluator.evaluate(context);
|
||||
myModifier = myConditionEvaluator.getModifier();
|
||||
return value;
|
||||
return myConditionEvaluator.evaluate(context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -63,8 +39,7 @@ public class ForStatementEvaluator extends ForStatementEvaluatorBase {
|
||||
@Override
|
||||
protected Object evaluateUpdate(EvaluationContextImpl context, Object value) throws EvaluateException {
|
||||
if (myUpdateEvaluator != null) {
|
||||
value = myUpdateEvaluator.evaluate(context);
|
||||
myModifier = myUpdateEvaluator.getModifier();
|
||||
return myUpdateEvaluator.evaluate(context);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
+69
-59
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.JVMNameUtil;
|
||||
@@ -9,85 +9,95 @@ import com.sun.jdi.ArrayReference;
|
||||
import com.sun.jdi.ObjectReference;
|
||||
import com.sun.jdi.Value;
|
||||
|
||||
public class ForeachStatementEvaluator extends ForStatementEvaluatorBase {
|
||||
public class ForeachStatementEvaluator implements Evaluator {
|
||||
private final Evaluator myIterationParameterEvaluator;
|
||||
private final Evaluator myIterableEvaluator;
|
||||
|
||||
private Evaluator myConditionEvaluator;
|
||||
private Evaluator myNextEvaluator;
|
||||
|
||||
private int myArrayLength = -1;
|
||||
private int myCurrentIndex = 0;
|
||||
|
||||
private Modifier myModifier;
|
||||
private final Evaluator myBodyEvaluator;
|
||||
private final String myLabelName;
|
||||
|
||||
public ForeachStatementEvaluator(Evaluator iterationParameterEvaluator,
|
||||
Evaluator iterableEvaluator,
|
||||
Evaluator bodyEvaluator,
|
||||
String labelName) {
|
||||
super(labelName, bodyEvaluator);
|
||||
myIterationParameterEvaluator = iterationParameterEvaluator;
|
||||
myIterableEvaluator = DisableGC.create(iterableEvaluator);
|
||||
myBodyEvaluator = bodyEvaluator;
|
||||
myLabelName = labelName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return myModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object evaluateInitialization(EvaluationContextImpl context, Object value) throws EvaluateException {
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
final Object iterable = myIterableEvaluator.evaluate(context);
|
||||
if (!(iterable instanceof ObjectReference)) {
|
||||
throw new EvaluateException("Unable to do foreach for" + iterable);
|
||||
}
|
||||
IdentityEvaluator iterableEvaluator = new IdentityEvaluator((Value)iterable);
|
||||
|
||||
if (iterable instanceof ArrayReference) {
|
||||
myCurrentIndex = 0;
|
||||
myArrayLength = ((ArrayReference)iterable).length();
|
||||
myNextEvaluator = new AssignmentEvaluator(myIterationParameterEvaluator,
|
||||
new Evaluator() {
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
return ((ArrayReference)iterable).getValue(myCurrentIndex++);
|
||||
}
|
||||
});
|
||||
return new ForStatementEvaluatorBase(myLabelName, myBodyEvaluator) {
|
||||
private int myCurrentIndex = 0;
|
||||
private int myArrayLength = -1;
|
||||
private Evaluator myNextEvaluator;
|
||||
|
||||
@Override
|
||||
protected Object evaluateInitialization(EvaluationContextImpl context, Object value) throws EvaluateException {
|
||||
myArrayLength = ((ArrayReference)iterable).length();
|
||||
myNextEvaluator = new AssignmentEvaluator(myIterationParameterEvaluator,
|
||||
new Evaluator() {
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) {
|
||||
return ((ArrayReference)iterable).getValue(myCurrentIndex++);
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object evaluateCondition(EvaluationContextImpl context) {
|
||||
return myCurrentIndex < myArrayLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateBody(EvaluationContextImpl context) throws EvaluateException {
|
||||
myNextEvaluator.evaluate(context);
|
||||
super.evaluateBody(context);
|
||||
}
|
||||
}.evaluate(context);
|
||||
}
|
||||
else {
|
||||
Object iterator =
|
||||
new MethodEvaluator(iterableEvaluator, JVMNameUtil.getJVMRawText(CommonClassNames.JAVA_LANG_ITERABLE), "iterator", null,
|
||||
new Evaluator[0]).evaluate(context);
|
||||
IdentityEvaluator iteratorEvaluator = new IdentityEvaluator((Value)iterator);
|
||||
myConditionEvaluator =
|
||||
new MethodEvaluator(iteratorEvaluator, JVMNameUtil.getJVMRawText(CommonClassNames.JAVA_UTIL_ITERATOR), "hasNext", null,
|
||||
new Evaluator[0]);
|
||||
myNextEvaluator = new AssignmentEvaluator(myIterationParameterEvaluator, new MethodEvaluator(iteratorEvaluator,
|
||||
JVMNameUtil.getJVMRawText(
|
||||
CommonClassNames.JAVA_UTIL_ITERATOR),
|
||||
"next", null, new Evaluator[0]));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return new ForStatementEvaluatorBase(myLabelName, myBodyEvaluator) {
|
||||
private MethodEvaluator myConditionEvaluator;
|
||||
private AssignmentEvaluator myNextEvaluator;
|
||||
|
||||
private boolean isArray() {
|
||||
return myArrayLength > -1;
|
||||
}
|
||||
@Override
|
||||
protected Object evaluateInitialization(EvaluationContextImpl context, Object value) throws EvaluateException {
|
||||
Object iterator = new MethodEvaluator(new IdentityEvaluator((Value)iterable),
|
||||
JVMNameUtil.getJVMRawText(CommonClassNames.JAVA_LANG_ITERABLE),
|
||||
"iterator", null,
|
||||
new Evaluator[0]).evaluate(context);
|
||||
IdentityEvaluator iteratorEvaluator = new IdentityEvaluator((Value)iterator);
|
||||
myConditionEvaluator = new MethodEvaluator(iteratorEvaluator,
|
||||
JVMNameUtil.getJVMRawText(CommonClassNames.JAVA_UTIL_ITERATOR),
|
||||
"hasNext", null,
|
||||
new Evaluator[0]);
|
||||
myNextEvaluator = new AssignmentEvaluator(myIterationParameterEvaluator,
|
||||
new MethodEvaluator(iteratorEvaluator,
|
||||
JVMNameUtil.getJVMRawText(CommonClassNames.JAVA_UTIL_ITERATOR),
|
||||
"next", null,
|
||||
new Evaluator[0]));
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object evaluateCondition(EvaluationContextImpl context) throws EvaluateException {
|
||||
if (isArray()) {
|
||||
return myCurrentIndex < myArrayLength;
|
||||
}
|
||||
else {
|
||||
Object res = myConditionEvaluator.evaluate(context);
|
||||
myModifier = myConditionEvaluator.getModifier();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected Object evaluateCondition(EvaluationContextImpl context) throws EvaluateException {
|
||||
return myConditionEvaluator.evaluate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateBody(EvaluationContextImpl context) throws EvaluateException {
|
||||
myNextEvaluator.evaluate(context);
|
||||
super.evaluateBody(context);
|
||||
@Override
|
||||
protected void evaluateBody(EvaluationContextImpl context) throws EvaluateException {
|
||||
myNextEvaluator.evaluate(context);
|
||||
super.evaluateBody(context);
|
||||
}
|
||||
}.evaluate(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-11
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
@@ -11,19 +11,12 @@ public class IfStatementEvaluator implements Evaluator {
|
||||
private final Evaluator myThenEvaluator;
|
||||
private final Evaluator myElseEvaluator;
|
||||
|
||||
private Modifier myModifier;
|
||||
|
||||
public IfStatementEvaluator(Evaluator conditionEvaluator, Evaluator thenEvaluator, Evaluator elseEvaluator) {
|
||||
myConditionEvaluator = DisableGC.create(conditionEvaluator);
|
||||
myThenEvaluator = DisableGC.create(thenEvaluator);
|
||||
myElseEvaluator = elseEvaluator == null ? null : DisableGC.create(elseEvaluator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return myModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object value = myConditionEvaluator.evaluate(context);
|
||||
@@ -33,16 +26,13 @@ public class IfStatementEvaluator implements Evaluator {
|
||||
else {
|
||||
if (((BooleanValue)value).booleanValue()) {
|
||||
value = myThenEvaluator.evaluate(context);
|
||||
myModifier = myThenEvaluator.getModifier();
|
||||
}
|
||||
else {
|
||||
if (myElseEvaluator != null) {
|
||||
value = myElseEvaluator.evaluate(context);
|
||||
myModifier = myElseEvaluator.getModifier();
|
||||
}
|
||||
else {
|
||||
value = context.getVirtualMachineProxy().mirrorOfVoid();
|
||||
myModifier = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+73
-54
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
/*
|
||||
* Class LocalVariableEvaluator
|
||||
@@ -25,26 +25,32 @@ import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class LocalVariableEvaluator implements Evaluator {
|
||||
class LocalVariableEvaluator implements ModifiableEvaluator {
|
||||
private static final Logger LOG = Logger.getInstance(LocalVariableEvaluator.class);
|
||||
|
||||
private final String myLocalVariableName;
|
||||
private EvaluationContextImpl myContext;
|
||||
private LocalVariableProxyImpl myEvaluatedVariable;
|
||||
private DecompiledLocalVariable myEvaluatedDecompiledVariable;
|
||||
private final boolean myCanScanFrames;
|
||||
|
||||
// TODO remove non-final fields, see IDEA-366793
|
||||
@Deprecated
|
||||
private EvaluationContextImpl myContext;
|
||||
@Deprecated
|
||||
private LocalVariableProxyImpl myEvaluatedVariable;
|
||||
@Deprecated
|
||||
private DecompiledLocalVariable myEvaluatedDecompiledVariable;
|
||||
|
||||
LocalVariableEvaluator(String localVariableName, boolean canScanFrames) {
|
||||
myLocalVariableName = localVariableName;
|
||||
myCanScanFrames = canScanFrames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
public @NotNull ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
StackFrameProxyImpl frameProxy = context.getFrameProxy();
|
||||
if (frameProxy == null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.no.stackframe"));
|
||||
@@ -66,7 +72,7 @@ class LocalVariableEvaluator implements Evaluator {
|
||||
variable.equals(resolveVariable(frameProxy, myLocalVariableName, context.getProject(), process))) {
|
||||
myEvaluatedVariable = local;
|
||||
myContext = context;
|
||||
return frameProxy.getValue(local);
|
||||
return new ModifiableValue(frameProxy.getValue(local), new MyModifier(context, local, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +89,7 @@ class LocalVariableEvaluator implements Evaluator {
|
||||
if (var.getMatchedNames().contains(myLocalVariableName) || var.getDefaultName().equals(myLocalVariableName)) {
|
||||
myEvaluatedDecompiledVariable = var;
|
||||
myContext = context;
|
||||
return entry.getValue();
|
||||
return new ModifiableValue(entry.getValue(), new MyModifier(context, null, var));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,54 +131,10 @@ class LocalVariableEvaluator implements Evaluator {
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
Modifier modifier = null;
|
||||
if ((myEvaluatedVariable != null || myEvaluatedDecompiledVariable != null) && myContext != null) {
|
||||
modifier = new Modifier() {
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
StackFrameProxyImpl frameProxy = myContext.getFrameProxy();
|
||||
try {
|
||||
assert frameProxy != null;
|
||||
if (myEvaluatedVariable != null) {
|
||||
frameProxy.setValue(myEvaluatedVariable, value);
|
||||
}
|
||||
else { // no debug info
|
||||
LocalVariablesUtil.setValue(frameProxy.getStackFrame(), myEvaluatedDecompiledVariable, value);
|
||||
}
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws ClassNotLoadedException {
|
||||
try {
|
||||
return myEvaluatedVariable.getType();
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return new LocalVariableDescriptorImpl(project, myEvaluatedVariable);
|
||||
}
|
||||
};
|
||||
return new MyModifier(myContext, myEvaluatedVariable, myEvaluatedDecompiledVariable);
|
||||
}
|
||||
return modifier;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static @Nullable PsiVariable resolveVariable(final StackFrameProxy frame,
|
||||
@@ -191,4 +153,61 @@ class LocalVariableEvaluator implements Evaluator {
|
||||
public String toString() {
|
||||
return myLocalVariableName;
|
||||
}
|
||||
|
||||
private static class MyModifier implements Modifier {
|
||||
private final EvaluationContextImpl myContext;
|
||||
private final LocalVariableProxyImpl myEvaluatedVariable;
|
||||
private final DecompiledLocalVariable myEvaluatedDecompiledVariable;
|
||||
|
||||
private MyModifier(EvaluationContextImpl context,
|
||||
LocalVariableProxyImpl evaluatedVariable,
|
||||
DecompiledLocalVariable evaluatedDecompiledVariable) {
|
||||
this.myContext = context;
|
||||
this.myEvaluatedVariable = evaluatedVariable;
|
||||
this.myEvaluatedDecompiledVariable = evaluatedDecompiledVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException {
|
||||
StackFrameProxyImpl frameProxy = myContext.getFrameProxy();
|
||||
try {
|
||||
assert frameProxy != null;
|
||||
if (myEvaluatedVariable != null) {
|
||||
frameProxy.setValue(myEvaluatedVariable, value);
|
||||
}
|
||||
else { // no debug info
|
||||
LocalVariablesUtil.setValue(frameProxy.getStackFrame(), myEvaluatedDecompiledVariable, value);
|
||||
}
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() throws ClassNotLoadedException {
|
||||
try {
|
||||
return myEvaluatedVariable.getType();
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return new LocalVariableDescriptorImpl(project, myEvaluatedVariable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||
|
||||
interface ModifiableEvaluator : Evaluator {
|
||||
@Throws(EvaluateException::class)
|
||||
override fun evaluate(context: EvaluationContextImpl): Any? = evaluateModifiable(context).value
|
||||
|
||||
@Throws(EvaluateException::class)
|
||||
override fun evaluateModifiable(context: EvaluationContextImpl): ModifiableValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a value that can be modified. This class encapsulates a value and an optional modifier
|
||||
* that allows modifications to the value.
|
||||
*
|
||||
* @property value The value being encapsulated, which can be of any type or null.
|
||||
* @property modifier The modifier associated with the value, which provides functionality for modifying the value.
|
||||
*/
|
||||
class ModifiableValue(val value: Any?, val modifier: Modifier?)
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class PatternEvaluator implements Evaluator {
|
||||
res = primitiveType.name().equals(myPrimitiveType);
|
||||
}
|
||||
if (res && myVariableEvaluator != null) {
|
||||
AssignmentEvaluator.assign(myVariableEvaluator.getModifier(), value, context);
|
||||
AssignmentEvaluator.assign(myVariableEvaluator.evaluateModifiable(context).getModifier(), value, context);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
+7
-6
@@ -1,10 +1,11 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PostfixOperationEvaluator implements Evaluator {
|
||||
public class PostfixOperationEvaluator implements ModifiableEvaluator {
|
||||
private final Evaluator myOperandEvaluator;
|
||||
|
||||
private final Evaluator myIncrementImpl;
|
||||
@@ -17,12 +18,12 @@ public class PostfixOperationEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
final Object value = myOperandEvaluator.evaluate(context);
|
||||
myModifier = myOperandEvaluator.getModifier();
|
||||
public @NotNull ModifiableValue evaluateModifiable(@NotNull EvaluationContextImpl context) throws EvaluateException {
|
||||
ModifiableValue modifiableValue = myOperandEvaluator.evaluateModifiable(context);
|
||||
myModifier = modifiableValue.getModifier();
|
||||
Object operationResult = myIncrementImpl.evaluate(context);
|
||||
AssignmentEvaluator.assign(myModifier, operationResult, context);
|
||||
return value;
|
||||
return modifiableValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+57
-47
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.JavaDebuggerBundle;
|
||||
@@ -12,14 +12,18 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.sun.jdi.Type;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SyntheticVariableEvaluator implements Evaluator {
|
||||
public class SyntheticVariableEvaluator implements ModifiableEvaluator {
|
||||
private static final Logger LOG = Logger.getInstance(SyntheticVariableEvaluator.class);
|
||||
|
||||
private final CodeFragmentEvaluator myCodeFragmentEvaluator;
|
||||
private final String myLocalName;
|
||||
private final JVMName myTypeName;
|
||||
|
||||
// TODO remove non-final fields, see IDEA-366793
|
||||
@Deprecated
|
||||
private String myTypeNameString = null;
|
||||
|
||||
public SyntheticVariableEvaluator(CodeFragmentEvaluator codeFragmentEvaluator, String localName, @Nullable JVMName typeName) {
|
||||
@@ -29,59 +33,65 @@ public class SyntheticVariableEvaluator implements Evaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
if (myTypeNameString == null && myTypeName != null) {
|
||||
myTypeNameString = myTypeName.getName(context.getDebugProcess());
|
||||
}
|
||||
return myCodeFragmentEvaluator.getValue(myLocalName, context.getVirtualMachineProxy());
|
||||
public @NotNull ModifiableValue evaluateModifiable(EvaluationContextImpl context) throws EvaluateException {
|
||||
String typeNameString = myTypeName != null ? myTypeName.getName(context.getDebugProcess()) : null;
|
||||
myTypeNameString = typeNameString;
|
||||
return new ModifiableValue(myCodeFragmentEvaluator.getValue(myLocalName, context.getVirtualMachineProxy()),
|
||||
new MyModifier(typeNameString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return new Modifier() {
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws EvaluateException {
|
||||
if (value == null) {
|
||||
if (myTypeNameString != null && DebuggerUtils.isPrimitiveType(myTypeNameString)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.set.primitive.to.null"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Type type = value.type();
|
||||
if (myTypeNameString != null && !DebuggerUtils.instanceOf(type, myTypeNameString)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.cast.object", type.name(), myTypeNameString));
|
||||
}
|
||||
}
|
||||
myCodeFragmentEvaluator.setValue(myLocalName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
LOG.assertTrue(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return new MyModifier(myTypeNameString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myLocalName;
|
||||
}
|
||||
|
||||
private class MyModifier implements Modifier {
|
||||
private final String myTypeNameString;
|
||||
|
||||
private MyModifier(String typeNameString) { this.myTypeNameString = typeNameString; }
|
||||
|
||||
@Override
|
||||
public boolean canInspect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Value value) throws EvaluateException {
|
||||
if (value == null) {
|
||||
if (myTypeNameString != null && DebuggerUtils.isPrimitiveType(myTypeNameString)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.set.primitive.to.null"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Type type = value.type();
|
||||
if (myTypeNameString != null && !DebuggerUtils.instanceOf(type, myTypeNameString)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.cast.object", type.name(), myTypeNameString));
|
||||
}
|
||||
}
|
||||
myCodeFragmentEvaluator.setValue(myLocalName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
LOG.assertTrue(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeDescriptorImpl getInspectItem(Project project) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-16
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
/*
|
||||
* Class TypeEvaluator
|
||||
@@ -13,13 +13,10 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.sun.jdi.ClassLoaderReference;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static com.intellij.util.containers.ContainerUtil.filter;
|
||||
import static com.intellij.util.containers.ContainerUtil.getOnlyItem;
|
||||
|
||||
@@ -28,9 +25,6 @@ public class TypeEvaluator implements Evaluator {
|
||||
|
||||
private final JVMName myTypeName;
|
||||
|
||||
private WeakReference<ReferenceType> myLastResult;
|
||||
private WeakReference<ClassLoaderReference> myLastClassLoader;
|
||||
|
||||
public TypeEvaluator(@NotNull JVMName typeName) {
|
||||
myTypeName = typeName;
|
||||
}
|
||||
@@ -41,13 +35,6 @@ public class TypeEvaluator implements Evaluator {
|
||||
@Override
|
||||
public @NotNull ReferenceType evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
ClassLoaderReference classLoader = context.getClassLoader();
|
||||
ReferenceType lastRes = SoftReference.dereference(myLastResult);
|
||||
if (lastRes != null && classLoader == SoftReference.dereference(myLastClassLoader)) {
|
||||
// if class loader is null, check that vms match
|
||||
if (classLoader != null || lastRes.virtualMachine().equals(context.getVirtualMachineProxy().getVirtualMachine())) {
|
||||
return lastRes;
|
||||
}
|
||||
}
|
||||
DebugProcessImpl debugProcess = context.getDebugProcess();
|
||||
String typeName = myTypeName.getName(debugProcess);
|
||||
ReferenceType type;
|
||||
@@ -69,8 +56,6 @@ public class TypeEvaluator implements Evaluator {
|
||||
if (type == null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("error.class.not.loaded", typeName));
|
||||
}
|
||||
myLastClassLoader = new WeakReference<>(classLoader);
|
||||
myLastResult = new WeakReference<>(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
+1
-20
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
@@ -29,11 +15,6 @@ public class WhileStatementEvaluator extends LoopEvaluator {
|
||||
myConditionEvaluator = DisableGC.create(conditionEvaluator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return myConditionEvaluator.getModifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object value;
|
||||
|
||||
+1
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.evaluate
|
||||
|
||||
@@ -489,8 +489,6 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
|
||||
}
|
||||
}
|
||||
|
||||
override fun getModifier() = null
|
||||
|
||||
companion object {
|
||||
@get:TestOnly
|
||||
@get:ApiStatus.Internal
|
||||
|
||||
Reference in New Issue
Block a user