From 0e377b5dc69b7be3868ad2fedb37a51d753e096b Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 16 Jan 2017 15:52:56 +0300 Subject: [PATCH] PY-21651 Fixed: Unresolved reference for attributes created by with statements Visit with-statements while collecting targets inside `__int__` and `__new__` methods --- .../python/psi/impl/PyClassImpl.java | 9 ++++++++ .../a.py | 3 +++ .../foo.py | 4 ++++ ...nceAttributeCreatedThroughWithStatement.py | 7 +++++++ .../PyUnresolvedReferencesInspectionTest.java | 21 ++++++++++++++++++- 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/a.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/foo.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/instanceAttributeCreatedThroughWithStatement.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 978029b0d986..92b824775901 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -1214,6 +1214,15 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } } } + + @Override + public void visitPyWithStatement(PyWithStatement node) { + StreamEx + .of(node.getWithItems()) + .map(PyWithItem::getTarget) + .select(PyTargetExpression.class) + .forEach(result::add); + } }); return result; } diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/a.py new file mode 100644 index 000000000000..e42f927fae25 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/a.py @@ -0,0 +1,3 @@ +from foo import Foo + +print(Foo().scope) \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/foo.py b/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/foo.py new file mode 100644 index 000000000000..c30b201d7ad8 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/InstanceAttributeCreatedThroughWithStatementInAnotherFile/foo.py @@ -0,0 +1,4 @@ +class Foo(object): + def __init__(self): + with open('scope') as self.scope: + pass \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/instanceAttributeCreatedThroughWithStatement.py b/python/testData/inspections/PyUnresolvedReferencesInspection/instanceAttributeCreatedThroughWithStatement.py new file mode 100644 index 000000000000..f36e98df3a33 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/instanceAttributeCreatedThroughWithStatement.py @@ -0,0 +1,7 @@ +class Foo(object): + def __init__(self): + with open('scope') as self.scope: + pass + + def get_scope(self): + return self.scope \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 5c6678d9b5b6..2c4d9e7a47a2 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -19,11 +19,14 @@ 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.psi.PsiFile; +import com.intellij.psi.PsiManager; 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.PyFile; import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -744,6 +747,22 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-21651 + public void testInstanceAttributeCreatedThroughWithStatement() { + doTest(); + } + + // PY-21651 + public void testInstanceAttributeCreatedThroughWithStatementInAnotherFile() { + doMultiFileTest(); + + final VirtualFile fooVFile = myFixture.getFile().getVirtualFile().getParent().getChildren()[1]; + assertEquals("foo.py", fooVFile.getName()); + + final PsiFile fooPsiFile = PsiManager.getInstance(myFixture.getProject()).findFile(fooVFile); + assertNotParsed((PyFile)fooPsiFile); + } + @NotNull @Override protected Class getInspectionClass() {