--Properly resolve types in the debugger using the fully qualified type name
authorYuli Fiterman fitermay <fiterman@gmail.com>
Fri, 1 Apr 2016 00:47:31 +0000 (20:47 -0400)
committerfitermay <fiterman@gmail.com>
Wed, 13 Apr 2016 02:55:24 +0000 (22:55 -0400)
--Properly resolve types in the debugger using the fully qualified type name

--Make pydevd_xml return FQN name

python/helpers/pydev/_pydevd_bundle/pydevd_xml.py
python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java
python/pydevSrc/com/jetbrains/python/debugger/PyReferringObjectsValue.java
python/pydevSrc/com/jetbrains/python/debugger/pydev/GetFrameCommand.java
python/pydevSrc/com/jetbrains/python/debugger/pydev/GetVariableCommand.java
python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java
python/src/com/jetbrains/python/debugger/PyDebugProcess.java
python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java
python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java
python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java

index 56cd26b1a675ab4d756870c8053541a747212972..e3ef8f87454e9c874281c91b3739870a3865e44e 100644 (file)
@@ -176,6 +176,9 @@ def frame_vars_to_xml(frame_f_locals):
     return xml
 
 
+def get_type_qualifier(type):
+    return getattr(type, "__module__", "")
+
 def var_to_xml(val, name, doTrim=True, additionalInXml=''):
     """ single variable or dictionary to xml representation """
 
@@ -187,6 +190,8 @@ def var_to_xml(val, name, doTrim=True, additionalInXml=''):
         v = val
 
     _type, typeName, resolver = get_type(v)
+    type_qualifier = get_type_qualifier(_type)
+
 
     do_not_call_value_str = False
     if isinstance(resolver, pydevd_resolver.djangoFormResolver.__class__):
@@ -233,7 +238,7 @@ def var_to_xml(val, name, doTrim=True, additionalInXml=''):
         name = quote(name, '/>_= ') #TODO: Fix PY-5834 without using quote
     except:
         pass
-    xml = '<var name="%s" type="%s"' % (make_valid_xml_value(name), make_valid_xml_value(typeName))
+    xml = '<var name="%s" type="%s" qualifier="%s"' % (make_valid_xml_value(name), make_valid_xml_value(typeName), make_valid_xml_value(type_qualifier))
 
     if value:
         #cannot be too big... communication may not handle it.
index e0962e5f6aea872668adde891e2930ca706bcc79..ae6d982a44e7b242a3581be336391aca4939412f 100644 (file)
@@ -1,5 +1,6 @@
 package com.jetbrains.python.debugger;
 
+import com.google.common.base.Strings;
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
@@ -18,6 +19,7 @@ public class PyDebugValue extends XNamedValue {
 
   private String myTempName = null;
   private final String myType;
+  private final String myTypeQualifier;
   private final String myValue;
   private final boolean myContainer;
   private final PyDebugValue myParent;
@@ -29,15 +31,16 @@ public class PyDebugValue extends XNamedValue {
 
   private final boolean myErrorOnEval;
 
-  public PyDebugValue(@NotNull final String name, final String type, final String value, final boolean container,
+  public PyDebugValue(@NotNull final String name, final String type, String typeQualifier, final String value, final boolean container,
                       boolean errorOnEval, final PyFrameAccessor frameAccessor) {
-    this(name, type, value, container, errorOnEval, null, frameAccessor);
+    this(name, type, typeQualifier, value, container, errorOnEval, null, frameAccessor);
   }
 
-  public PyDebugValue(@NotNull final String name, final String type, final String value, final boolean container,
+  public PyDebugValue(@NotNull final String name, final String type, String typeQualifier, final String value, final boolean container,
                       boolean errorOnEval, final PyDebugValue parent, final PyFrameAccessor frameAccessor) {
     super(name);
     myType = type;
+    myTypeQualifier = Strings.isNullOrEmpty(typeQualifier) ? null : typeQualifier;
     myValue = value;
     myContainer = container;
     myErrorOnEval = errorOnEval;
@@ -70,7 +73,7 @@ public class PyDebugValue extends XNamedValue {
   }
   
   public PyDebugValue setParent(@Nullable PyDebugValue parent) {
-    return new PyDebugValue(myName, myType, myValue, myContainer, myErrorOnEval, parent, myFrameAccessor);
+    return new PyDebugValue(myName, myType, null, myValue, myContainer, myErrorOnEval, parent, myFrameAccessor);
   }
 
   public PyDebugValue getParent() {
@@ -213,7 +216,7 @@ public class PyDebugValue extends XNamedValue {
   }
   
   public PyDebugValue setName(String newName) {
-    return new PyDebugValue(newName, myType, myValue, myContainer, myErrorOnEval, myParent, myFrameAccessor);
+    return new PyDebugValue(newName, myType, null, myValue, myContainer, myErrorOnEval, myParent, myFrameAccessor);
   }
 
   @Nullable
@@ -268,6 +271,17 @@ public class PyDebugValue extends XNamedValue {
 
   @Override
   public void computeTypeSourcePosition(@NotNull XNavigatable navigatable) {
-    navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForType(myType));
+
+    navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForType(getQualifiedType()));
+  }
+
+  public String getQualifiedType() {
+    if (Strings.isNullOrEmpty(myType))
+      return null;
+    return (myTypeQualifier == null) ? myType : (myTypeQualifier + "." + myType);
+  }
+
+  public String getTypeQualifier() {
+    return myTypeQualifier;
   }
 }
index 283653659d0dda698838d81ad618eb58df5d0037..3493e164558130562c7719b20f4ed368b5e2150d 100644 (file)
@@ -28,14 +28,15 @@ public class PyReferringObjectsValue extends PyDebugValue {
 
   public PyReferringObjectsValue(@NotNull String name,
                                  String type,
+                                 String typeQualifier,
                                  String value,
                                  boolean container, boolean errorOnEval, @NotNull PyFrameAccessor frameAccessor) {
-    super(name, type, value, container, errorOnEval, frameAccessor);
+    super(name, type, typeQualifier, value, container, errorOnEval, frameAccessor);
     myReferrersLoader = frameAccessor.getReferrersLoader();
   }
 
   public PyReferringObjectsValue(PyDebugValue debugValue) {
-    this(debugValue.getName(), debugValue.getType(), debugValue.getValue(), debugValue.isContainer(), debugValue.isErrorOnEval(), debugValue.getFrameAccessor());
+    this(debugValue.getName(), debugValue.getType(), debugValue.getTypeQualifier(), debugValue.getValue(), debugValue.isContainer(), debugValue.isErrorOnEval(), debugValue.getFrameAccessor());
   }
 
   @Override
index 9df4ffa092dfff90e43a1ed3bc60d74cc6d8c65d..7a854b961fe53e0fa62caa5fe7d38556f3046088 100644 (file)
@@ -47,7 +47,7 @@ public class GetFrameCommand extends AbstractFrameCommand {
   }
 
   protected PyDebugValue extend(final PyDebugValue value) {
-    return new PyDebugValue(value.getName(), value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(), null, myDebugProcess);
+    return new PyDebugValue(value.getName(), value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), value.isErrorOnEval(), null, myDebugProcess);
   }
 
   public XValueChildrenList getVariables() {
index 466780066f773fbd1bf72e46d4fdcdacfe2765a6..cc054917fdd1f86f310cab5dedcbf98f5e6a5af7 100644 (file)
@@ -50,7 +50,7 @@ public class GetVariableCommand extends GetFrameCommand {
 
   @Override
   protected PyDebugValue extend(final PyDebugValue value) {
-    return new PyDebugValue(value.getName(), value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(), myParent,
+    return new PyDebugValue(value.getName(), value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), value.isErrorOnEval(), myParent,
                             myDebugProcess);
   }
 }
index ea4d5173b31bd112d5767f96af9142b1fb589b9c..6af8638d905204cf22ea79997536517ca031b937 100644 (file)
@@ -252,6 +252,8 @@ public class ProtocolParser {
 
     final String name = readString(reader, "name", null);
     final String type = readString(reader, "type", null);
+    final String qualifier = readString(reader, "qualifier", null); //to be able to get the fully qualified type if necessary
+
     String value = readString(reader, "value", null);
     final String isContainer = readString(reader, "isContainer", "");
     final String isErrorOnEval = readString(reader, "isErrorOnEval", "");
@@ -260,7 +262,7 @@ public class ProtocolParser {
       value = value.substring(type.length() + 2);
     }
 
-    return new PyDebugValue(name, type, value, "True".equals(isContainer), "True".equals(isErrorOnEval), frameAccessor);
+    return new PyDebugValue(name, type, qualifier, value, "True".equals(isContainer), "True".equals(isErrorOnEval), frameAccessor);
   }
 
   public static ArrayChunk parseArrayValues(final String text, final PyFrameAccessor frameAccessor) throws PyDebuggerException {
@@ -279,7 +281,7 @@ public class ProtocolParser {
       String max = readString(reader, "max", null);
       String min = readString(reader, "min", null);
       result =
-        new ArrayChunk(new PyDebugValue(slice, null, null, false, false, frameAccessor), slice, rows, cols, max, min, format, type, null);
+        new ArrayChunk(new PyDebugValue(slice, null, null, null, false, false, frameAccessor), slice, rows, cols, max, min, format, type, null);
       reader.moveUp();
     }
 
index cf08a9ec0ecf356dd1426f1fd3b177e43bb8931d..8b50fad604b9874bce7026ccbbf0b9c2c896a73e 100644 (file)
@@ -60,8 +60,10 @@ import com.jetbrains.python.PythonFileType;
 import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
 import com.jetbrains.python.console.pydev.PydevCompletionVariant;
 import com.jetbrains.python.debugger.pydev.*;
+import com.jetbrains.python.psi.PyClass;
 import com.jetbrains.python.psi.PyFunction;
 import com.jetbrains.python.psi.PyImportElement;
+import com.jetbrains.python.psi.PyPsiFacade;
 import com.jetbrains.python.psi.resolve.PyResolveUtil;
 import com.jetbrains.python.psi.types.PyClassType;
 import com.jetbrains.python.psi.types.PyType;
@@ -839,6 +841,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
   @Nullable
   @Override
   public XSourcePosition getSourcePositionForName(String name) {
+    if (name == null)
+      return null;
     XSourcePosition currentPosition = getCurrentFrameSourcePosition();
 
     final PsiFile file = getPsiFile(currentPosition);
@@ -856,12 +860,23 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
     PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() {
       @Override
       public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
-        if (!(element instanceof PyImportElement)) {
+        if ((element instanceof PyImportElement)) {
+          PyImportElement importElement = (PyImportElement)element;
+          if (name.equals(importElement.getVisibleName())) {
+            if (elementRef.isNull()) {
+              elementRef.set(element);
+            }
+            return false;
+
+          }
+          return true;
+        }
+        else {
           if (elementRef.isNull()) {
             elementRef.set(element);
           }
+          return false;
         }
-        return false;
       }
 
       @Nullable
@@ -900,10 +915,20 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
     if (file == null) return null;
 
 
-    PyType type = PyTypeParser.getTypeByName(file, typeName);
 
-    if (type instanceof PyClassType) {
-      return XSourcePositionImpl.createByElement(((PyClassType)type).getPyClass());
+    if (!typeName.contains(".")) {
+      PyType type = PyTypeParser.getTypeByName(file, typeName);
+
+      if (type instanceof PyClassType) {
+        return XSourcePositionImpl.createByElement(((PyClassType)type).getPyClass());
+      }
+    }
+
+    PyPsiFacade psiFacade = PyPsiFacade.getInstance(getProject());
+    PyClass aClass = psiFacade.findClass(typeName);
+    if (aClass != null)
+    {
+      return XSourcePositionImpl.createByElement(aClass);
     }
 
     return null;
index 7ee0e3f22f9718196178e555792c2e729731bc4a..29cef063f1b308d4c371e91e85e0395bc3ca998f 100644 (file)
@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable;
 
 public class PyDebuggerEvaluator extends XDebuggerEvaluator {
 
-  private static final PyDebugValue NONE = new PyDebugValue("", "NoneType", "None", false, false, null, null);
+  private static final PyDebugValue NONE = new PyDebugValue("", "NoneType", null, "None", false, false, null, null);
 
   private Project myProject;
   private final PyFrameAccessor myDebugProcess;
index 1947968c843e630ab7325ed5160109b3c31cba3f..a2b68cb8461d1f83807edcbf7562989bc202fe23 100644 (file)
@@ -51,7 +51,7 @@ public class AsyncArrayTableModel extends AbstractTableModel {
       public ListenableFuture<ArrayChunk> load(final Pair<Integer, Integer> key) throws Exception {
         final PyDebugValue value = myProvider.getDebugValue();
         final PyDebugValue slicedValue =
-          new PyDebugValue(myProvider.getSliceText(), value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
+          new PyDebugValue(myProvider.getSliceText(), value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
                            value.getParent(), value.getFrameAccessor());
 
         ListenableFutureTask<ArrayChunk> task = ListenableFutureTask.create(new Callable<ArrayChunk>() {
index 1424140c8b78e7defc9a78c53fd0380f8aabefbb..0ae8bed9ebb9f2dedfbaa89f829d41ca05038db8 100644 (file)
  */
 package com.jetbrains.python.debugger.array;
 
-import com.google.common.util.concurrent.ListenableFutureTask;
 import com.intellij.codeInsight.hint.HintManager;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.Result;
-import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Pair;
-import com.intellij.util.Consumer;
 import com.intellij.util.ui.UIUtil;
-import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.intellij.xdebugger.frame.XValue;
 import com.jetbrains.python.debugger.*;
 import org.jetbrains.annotations.NotNull;
 
-import javax.management.InvalidAttributeValueException;
 import javax.swing.*;
-import javax.swing.table.TableCellEditor;
 import java.awt.*;
 import java.awt.event.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -179,7 +165,7 @@ public class NumpyArrayTable {
         final PyDebugValue value = getDebugValue();
         PyDebugValue parent = value.getParent();
         final PyDebugValue slicedValue =
-          new PyDebugValue(slice, value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
+          new PyDebugValue(slice, value.getType(), null, value.getValue(), value.isContainer(), value.isErrorOnEval(),
                            parent, value.getFrameAccessor());
 
         final String format = getFormat().isEmpty() ? "%" : getFormat();