show "val$..." synthetic fields on the same level as local vars
authorEugene Zhuravlev <jeka@intellij.com>
Fri, 12 Mar 2010 15:18:38 +0000 (18:18 +0300)
committerEugene Zhuravlev <jeka@intellij.com>
Fri, 12 Mar 2010 15:36:01 +0000 (18:36 +0300)
java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java
java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java
java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ClassRenderer.java

index c2a42eb2e3fb56b352de7626bb0dfb80635e6d94..081471a8ab9b4f06a903fa23d5feedb4798bf42f 100644 (file)
@@ -50,6 +50,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.SpeedSearchBase;
 import com.intellij.ui.TreeSpeedSearch;
 import com.sun.jdi.*;
@@ -500,6 +501,20 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
           descriptor = myNodeManager.getStaticDescriptor(stackDescriptor, type);
         }
         myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));
+
+        if (thisObjectReference != null && evaluationContext.getDebugProcess().getVirtualMachineProxy().canGetSyntheticAttribute())  {
+          final ReferenceType thisRefType = thisObjectReference.referenceType();
+          if (thisRefType instanceof ClassType) {
+            final ClassType clsType = (ClassType)thisRefType;
+            for (Field field : clsType.fields()) {
+              if (field.isSynthetic() && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
+                final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(stackDescriptor, thisObjectReference, field);
+                myChildren.add(myNodeManager.createNode(fieldDescriptor, evaluationContext));
+              }
+            }
+          }
+        }
+
         try {
           buildVariables(stackDescriptor, evaluationContext);
           if (NodeRendererSettings.getInstance().getClassRenderer().SORT_ASCENDING) {
index 521d30ba6ae8c5510130738a3ad987b5bc326409..12911d980dbbdd2dd89061dee2e8e5ae4ad9aa72 100644 (file)
@@ -39,6 +39,7 @@ import com.sun.jdi.*;
 import org.jetbrains.annotations.NotNull;
 
 public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDescriptor{
+  public static final String OUTER_LOCAL_VAR_FIELD_PREFIX = "val$";
   private final Field myField;
   private final ObjectReference myObject;
   private Boolean myIsPrimitive = null;
@@ -66,7 +67,7 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
     final ReferenceType type = myField.declaringType();
     final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
     final String fieldName = myField.name();
-    if (fieldName.startsWith("val$")) {
+    if (fieldName.startsWith(OUTER_LOCAL_VAR_FIELD_PREFIX)) {
       // this field actually mirrors a local variable in the outer class
       String varName = fieldName.substring(fieldName.lastIndexOf('$') + 1);
       PsiElement element = PositionUtil.getContextElement(context);
@@ -137,7 +138,17 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
   }
 
   public String getName() {
-    return myField.name();
+    final String fieldName = myField.name();
+    return isOuterLocalVariableValue()? fieldName.substring(OUTER_LOCAL_VAR_FIELD_PREFIX.length()) : fieldName;
+  }
+
+  public boolean isOuterLocalVariableValue() {
+    try {
+      return DebuggerUtils.isSynthetic(myField) && myField.name().startsWith(OUTER_LOCAL_VAR_FIELD_PREFIX);
+    }
+    catch (UnsupportedOperationException e) {
+      return false;
+    }
   }
 
   public String calcValueName() {
@@ -166,10 +177,10 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
     }
     else {
       //noinspection HardCodedStringLiteral
-      fieldName = "this." + getName();
+      fieldName = isOuterLocalVariableValue()? getName() : "this." + getName();
     }
     try {
-      return (PsiReferenceExpression)elementFactory.createExpressionFromText(fieldName, null);
+      return elementFactory.createExpressionFromText(fieldName, null);
     }
     catch (IncorrectOperationException e) {
       throw new EvaluateException(DebuggerBundle.message("error.invalid.field.name", getName()), e);
index 0c33df0bf32a988dba01458dd97ceab77e7a41cc..36b3a41f4b9e0d5f49593e56414080d047bc5440 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
 import com.intellij.debugger.engine.DebuggerUtils;
 import com.intellij.debugger.engine.evaluation.EvaluateException;
 import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl;
 import com.intellij.debugger.ui.impl.watch.MessageDescriptor;
 import com.intellij.debugger.ui.impl.watch.NodeManagerImpl;
 import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
@@ -29,6 +30,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.DefaultJDOMExternalizer;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiElementFactory;
 import com.intellij.psi.PsiExpression;
@@ -162,15 +164,14 @@ public class ClassRenderer extends NodeRendererImpl{
     builder.setChildren(children);
   }
 
-  private boolean shouldDisplay(TypeComponent component) {
-    if (!SHOW_SYNTHETICS && DebuggerUtils.isSynthetic(component)) {
+  private boolean shouldDisplay(Field field) {
+    final boolean isSynthetic = DebuggerUtils.isSynthetic(field);
+    if (!SHOW_SYNTHETICS && isSynthetic) {
       return false;
     }
-    if (!(component instanceof Field)) {
-      return true;
+    if (isSynthetic && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
+      return false;
     }
-    final Field field = (Field)component;
-
     if(!SHOW_STATIC && field.isStatic()) {
       return false;
     }