Merge branch 'origin/master'
authorElizaveta Shashkova <Elizaveta.Shashkova@jetbrains.com>
Wed, 18 Feb 2015 17:41:29 +0000 (20:41 +0300)
committerElizaveta Shashkova <Elizaveta.Shashkova@jetbrains.com>
Wed, 18 Feb 2015 17:41:29 +0000 (20:41 +0300)
python/src/com/jetbrains/python/debugger/PyDebuggerEditorsProvider.java
python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionBuiltins/evaluateExpressionBuiltins.py [new file with mode: 0644]
python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionClass/evaluateExpressionClass.py [new file with mode: 0644]
python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionInsideFunction/evaluateExpressionInsideFunction.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/fixtures/PyInspectionTestCase.java
python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java

index 3b74d4f79decdad2f144f78905833a7151729215..af4b98460e6102872e4dd86cdca68e9acc4db1a9 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.jetbrains.python.debugger;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileTypes.FileType;
@@ -55,7 +56,8 @@ public class PyDebuggerEditorsProvider extends XDebuggerEditorsProvider {
   }
 
   @Nullable
-  private static PsiElement getContextElement(final Project project, XSourcePosition sourcePosition) {
+  @VisibleForTesting
+  public static PsiElement getContextElement(final Project project, XSourcePosition sourcePosition) {
     if (sourcePosition != null) {
       final Document document = FileDocumentManager.getInstance().getDocument(sourcePosition.getFile());
       final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
@@ -68,7 +70,7 @@ public class PyDebuggerEditorsProvider extends XDebuggerEditorsProvider {
             if (element != null && !(element instanceof PsiWhiteSpace || element instanceof PsiComment)) {
               return PyPsiUtils.getStatement(element);
             }
-            offset = element.getTextRange().getEndOffset() + 1;
+            offset = element.getTextRange().getEndOffset();
           }
           while (offset < lineEndOffset);
         }
index 48401ea2afa63ab9515f56778bc74383a3326166..68fea31df070ebe895d4e47b64c9759571510dd2 100644 (file)
@@ -269,8 +269,8 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
             uexpr = null;
           }
           else if (owner == originalOwner && !scope.isGlobal(referencedName)) {
-            final List<ReadWriteInstruction> instructions = PyDefUseUtil.getLatestDefs(owner, referencedName, myElement, false);
-            final ResolveResultList latest = resolveToLatestDefs(instructions, myElement, referencedName);
+            final List<ReadWriteInstruction> instructions = PyDefUseUtil.getLatestDefs(owner, referencedName, realContext, false);
+            final ResolveResultList latest = resolveToLatestDefs(instructions, realContext, referencedName);
             if (!latest.isEmpty()) {
               return latest;
             }
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionBuiltins/evaluateExpressionBuiltins.py b/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionBuiltins/evaluateExpressionBuiltins.py
new file mode 100644 (file)
index 0000000..1bf13ed
--- /dev/null
@@ -0,0 +1,3 @@
+a = [1, 2, 3]
+b = 3
+c = a + b
\ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionClass/evaluateExpressionClass.py b/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionClass/evaluateExpressionClass.py
new file mode 100644 (file)
index 0000000..d602bc5
--- /dev/null
@@ -0,0 +1,5 @@
+s = 1
+class A:
+    def __init__(self):
+        self.a = 2
+        self.b = 3
\ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionInsideFunction/evaluateExpressionInsideFunction.py b/python/testData/inspections/PyUnresolvedReferencesInspection/EvaluateExpressionInsideFunction/evaluateExpressionInsideFunction.py
new file mode 100644 (file)
index 0000000..18f0338
--- /dev/null
@@ -0,0 +1,4 @@
+a = 3
+def f():
+    s = 1
+    return s
\ No newline at end of file
index 717a579ce97b19d5d799ae598b8a343f05b1d888..2f388aa205571f271b1a14448d7ee27613cc2c6c 100644 (file)
@@ -42,7 +42,7 @@ public abstract class PyInspectionTestCase extends PyTestCase {
     myFixture.checkHighlighting(isWarning(), isInfo(), isWeakWarning());
   }
 
-  private String getTestDirectory(boolean lowercaseFirstLetter) {
+  protected String getTestDirectory(boolean lowercaseFirstLetter) {
     return "inspections/" + getInspectionClass().getSimpleName() + "/" + getTestName(lowercaseFirstLetter);
   }
 
index 9013d0952934dee2b42d6a20b52d204c8706b35e..5981c6b74767b36c9c182783d9db6ca0858e5f8d 100644 (file)
@@ -17,9 +17,14 @@ package com.jetbrains.python.inspections;
 
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.xdebugger.impl.XSourcePositionImpl;
+import com.jetbrains.python.debugger.PyDebuggerEditorsProvider;
 import com.jetbrains.python.fixtures.PyInspectionTestCase;
 import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
 import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 
@@ -412,6 +417,41 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
     myFixture.checkHighlighting(isWarning(), isInfo(), isWeakWarning());
   }
 
+  protected VirtualFile prepareFile() {
+    myFixture.copyDirectoryToProject(getTestDirectory(false), "");
+    return myFixture.configureByFile(getTestDirectory(false) + "/" + getTestName(true) + ".py").getVirtualFile();
+  }
+
+  protected void doEvaluateExpressionTest(@NotNull VirtualFile mainFile, @NotNull String expression, int lineNumber) {
+    PsiElement element = PyDebuggerEditorsProvider.getContextElement(myFixture.getProject(),
+                                                                     XSourcePositionImpl.create(mainFile, lineNumber));
+    final PyExpressionCodeFragmentImpl fragment = new PyExpressionCodeFragmentImpl(myFixture.getProject(), "fragment.py", expression, true);
+    fragment.setContext(element);
+    myFixture.configureFromExistingVirtualFile(fragment.getVirtualFile());
+    myFixture.enableInspections(getInspectionClass());
+    myFixture.checkHighlighting(isWarning(), isInfo(), isWeakWarning());
+  }
+
+  public void testEvaluateExpressionBuiltins() {
+    VirtualFile mainFile = prepareFile();
+    doEvaluateExpressionTest(mainFile, "len(a)", 2);
+    doEvaluateExpressionTest(mainFile, "a", 2);
+  }
+
+  public void testEvaluateExpressionInsideFunction() {
+    VirtualFile mainFile = prepareFile();
+    doEvaluateExpressionTest(mainFile, "a", 3);
+    doEvaluateExpressionTest(mainFile, "s", 3);
+  }
+
+  // PY-14309
+  public void testEvaluateExpressionClass() {
+    VirtualFile mainFile = prepareFile();
+    doEvaluateExpressionTest(mainFile, "s", 4);
+    doEvaluateExpressionTest(mainFile, "self", 4);
+    doEvaluateExpressionTest(mainFile, "self.a", 4);
+  }
+
   // PY-13554
   public void testDocstringTypeFromSubModule() {
     doMultiFileTest();