--Add support for resolving source positions inside inner level elements
authorYuli Fiterman fitermay <fiterman@gmail.com>
Fri, 1 Apr 2016 19:57:18 +0000 (15:57 -0400)
committerfitermay <fiterman@gmail.com>
Wed, 13 Apr 2016 02:56:57 +0000 (22:56 -0400)
python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java
python/pydevSrc/com/jetbrains/python/debugger/PyFrameAccessor.java
python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
python/src/com/jetbrains/python/debugger/PyDebugProcess.java

index afd426d05df0915de6b9c8065e60b58fb164fa26..02b1b591684eb6f9d800d5a4f90ebad1fede078b 100644 (file)
@@ -263,7 +263,13 @@ public class PyDebugValue extends XNamedValue {
 
   @Override
   public void computeSourcePosition(@NotNull XNavigatable navigatable) {
 
   @Override
   public void computeSourcePosition(@NotNull XNavigatable navigatable) {
-    navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForName(myName));
+    if (myParent == null) {
+      navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForName(myName, null));
+    }
+    else
+    {
+      navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForName(myName, myParent.getDeclaringType()));
+    }
   }
 
   @Override
   }
 
   @Override
@@ -279,7 +285,7 @@ public class PyDebugValue extends XNamedValue {
     navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForType(lookupType));
   }
 
     navigatable.setSourcePosition(myFrameAccessor.getSourcePositionForType(lookupType));
   }
 
-  private String getDeclaringType() {
+  protected final String getDeclaringType() {
     String lookupType = getQualifiedType();
     if (!Strings.isNullOrEmpty(myValue))
     {
     String lookupType = getQualifiedType();
     if (!Strings.isNullOrEmpty(myValue))
     {
index bd6d5449a51d5309d5fadebfeb74fa3c97221d73..0bb4ee11606a1778eb7b901baf783f1de48a0841 100644 (file)
@@ -25,7 +25,7 @@ public interface PyFrameAccessor {
   ArrayChunk getArrayItems(PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format) throws PyDebuggerException;
 
   @Nullable
   ArrayChunk getArrayItems(PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format) throws PyDebuggerException;
 
   @Nullable
-  XSourcePosition getSourcePositionForName(String name);
+  XSourcePosition getSourcePositionForName(String name, String parentType);
 
   @Nullable
   XSourcePosition getSourcePositionForType(String type);
 
   @Nullable
   XSourcePosition getSourcePositionForType(String type);
index 12815a3d82518b5d41e5da00c61a81e833fc9a48..af61cab907347228388245923243d60da8824036 100644 (file)
@@ -575,7 +575,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
 
   @Nullable
   @Override
 
   @Nullable
   @Override
-  public XSourcePosition getSourcePositionForName(String name) {
+  public XSourcePosition getSourcePositionForName(String name, String parentType) {
     return null;
   }
 
     return null;
   }
 
index f95464c32d6d86efa3bab57905509c7ee81c816e..f79490821d0afb8ac1aeef742a7ce887b9deae4c 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.jetbrains.python.debugger;
 
  */
 package com.jetbrains.python.debugger;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.intellij.execution.process.ProcessEvent;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.intellij.execution.process.ProcessEvent;
@@ -30,6 +31,8 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.Task;
@@ -61,7 +64,9 @@ import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
 import com.jetbrains.python.console.pydev.PydevCompletionVariant;
 import com.jetbrains.python.debugger.pydev.*;
 import com.jetbrains.python.psi.*;
 import com.jetbrains.python.console.pydev.PydevCompletionVariant;
 import com.jetbrains.python.debugger.pydev.*;
 import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.resolve.PyResolveContext;
 import com.jetbrains.python.psi.resolve.PyResolveUtil;
 import com.jetbrains.python.psi.resolve.PyResolveUtil;
+import com.jetbrains.python.psi.resolve.RatedResolveResult;
 import com.jetbrains.python.psi.types.PyClassType;
 import com.jetbrains.python.psi.types.PyModuleType;
 import com.jetbrains.python.psi.types.PyType;
 import com.jetbrains.python.psi.types.PyClassType;
 import com.jetbrains.python.psi.types.PyModuleType;
 import com.jetbrains.python.psi.types.PyType;
@@ -838,22 +843,46 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
 
   @Nullable
   @Override
 
   @Nullable
   @Override
-  public XSourcePosition getSourcePositionForName(String name) {
-    if (name == null)
-      return null;
+  public XSourcePosition getSourcePositionForName(String name, String parentType) {
+    if (name == null) return null;
     XSourcePosition currentPosition = getCurrentFrameSourcePosition();
 
     final PsiFile file = getPsiFile(currentPosition);
 
     if (file == null) return null;
 
     XSourcePosition currentPosition = getCurrentFrameSourcePosition();
 
     final PsiFile file = getPsiFile(currentPosition);
 
     if (file == null) return null;
 
+    if (Strings.isNullOrEmpty(parentType)) {
+      final Ref<PsiElement> elementRef = resolveInCurrentFrame(name, currentPosition, file);
+      return elementRef.isNull() ? null : XSourcePositionImpl.createByElement(elementRef.get());
+    }
+    else {
+      final PyType parentDef = resolveTypeFromString(parentType, file);
+      if (parentDef == null)
+        return null;
+      List<? extends RatedResolveResult> results =
+        parentDef.resolveMember(name, null, AccessDirection.READ, PyResolveContext.noImplicits());
+      if (results != null && !results.isEmpty()) {
+        return XSourcePositionImpl.createByElement(results.get(0).getElement());
+      }
+      else {
+          return typeToPosition(parentDef); // at least try to return parent
+      }
+
+    }
+
+  }
+
+
+
+  @NotNull
+  private static Ref<PsiElement> resolveInCurrentFrame(final String name, XSourcePosition currentPosition, PsiFile file) {
+    final Ref<PsiElement> elementRef = Ref.create();
     PsiElement currentElement = file.findElementAt(currentPosition.getOffset());
 
     if (currentElement == null) {
     PsiElement currentElement = file.findElementAt(currentPosition.getOffset());
 
     if (currentElement == null) {
-      return null;
+      return elementRef;
     }
 
     }
 
-    final Ref<PsiElement> elementRef = Ref.create();
 
     PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() {
       @Override
 
     PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() {
       @Override
@@ -888,9 +917,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
 
       }
     }, currentElement, name, null);
 
       }
     }, currentElement, name, null);
-
-    return elementRef.isNull() ? null
-                               : XSourcePositionImpl.createByElement(elementRef.get());
+    return elementRef;
   }
 
   @Nullable
   }
 
   @Nullable
@@ -913,35 +940,44 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
     if (file == null || typeName == null || !(file instanceof PyFile)) return null;
 
 
     if (file == null || typeName == null || !(file instanceof PyFile)) return null;
 
 
-    typeName = typeName.replace("__builtin__.", "");
-    if (!typeName.contains(".")) {
-      PyType type = PyTypeParser.getTypeByName(file, typeName);
-
-      if (type instanceof PyClassType) {
-        return XSourcePositionImpl.createByElement(((PyClassType)type).getPyClass());
-      }
-    }
+    final PyType pyType = resolveTypeFromString(typeName, file);
+    return pyType == null? null : typeToPosition(pyType);
 
 
-    PyElementGenerator generator = PyElementGenerator.getInstance(getProject());
-    PyPsiFacade psiFacade = PyPsiFacade.getInstance(getProject());
-    PyType pyType = psiFacade.parseTypeAnnotation(typeName, generator.createDummyFile(((PyFile)file).getLanguageLevel(), ""));
+  }
 
 
-    if (pyType != null) {
-      final PyClassType classType = PyUtil.as(pyType, PyClassType.class);
+  @Nullable
+  private static XSourcePosition typeToPosition(PyType pyType) {
+    final PyClassType classType = PyUtil.as(pyType, PyClassType.class);
 
 
-      if (classType != null) {
-        return XSourcePositionImpl.createByElement(classType.getPyClass());
-      }
+    if (classType != null) {
+      return XSourcePositionImpl.createByElement(classType.getPyClass());
+    }
 
 
-      final PyModuleType moduleType = PyUtil.as(pyType, PyModuleType.class);
-      if (moduleType != null) {
-        return XSourcePositionImpl.createByElement(moduleType.getModule());
-      }
+    final PyModuleType moduleType = PyUtil.as(pyType, PyModuleType.class);
+    if (moduleType != null) {
+      return XSourcePositionImpl.createByElement(moduleType.getModule());
     }
     }
+    return null;
+  }
 
 
+  private PyType resolveTypeFromString(String typeName, PsiFile file) {
+    typeName = typeName.replace("__builtin__.", "");
+    PyType pyType = null;
+    if (!typeName.contains(".")) {
 
 
+      pyType = PyTypeParser.getTypeByName(file, typeName);
+    }
+    if (pyType == null)
+    {
+      PyElementGenerator generator = PyElementGenerator.getInstance(getProject());
+      PyPsiFacade psiFacade = PyPsiFacade.getInstance(getProject());
+      PsiFile dummyFile = generator.createDummyFile( ((PyFile)file).getLanguageLevel() , "");
+      Module moduleForFile = ModuleUtilCore.findModuleForPsiElement(file);
+      dummyFile.putUserData(ModuleUtilCore.KEY_MODULE, moduleForFile);
 
 
+      pyType = psiFacade.parseTypeAnnotation(typeName, dummyFile);
 
 
-    return null;
+    }
+    return pyType;
   }
 }
   }
 }