From ece2216f9bdf13f69193accaebe922330644dd6d Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 15:34:06 +0400 Subject: [PATCH 1/9] Don't show statement effect warnings for variable docstrings even if the docstring type isn't set --- .../python/documentation/DocStringUtil.java | 45 ++++++++----------- .../python/PythonInspectionsTest.java | 10 +---- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index dd07c8d84a26..833a897310f6 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -1,7 +1,5 @@ package com.jetbrains.python.documentation; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; @@ -115,31 +113,26 @@ public class DocStringUtil { } public static boolean isVariableDocString(@NotNull PyStringLiteralExpression expr) { - final Module module = ModuleUtilCore.findModuleForPsiElement(expr); - if (module == null) return false; - final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module); - if (settings.isEpydocFormat(expr.getContainingFile()) || settings.isReSTFormat(expr.getContainingFile())) { - final PsiElement parent = expr.getParent(); - if (!(parent instanceof PyExpressionStatement)) { - return false; - } - PsiElement prevElement = parent.getPrevSibling(); - while (prevElement instanceof PsiWhiteSpace || prevElement instanceof PsiComment) { - prevElement = prevElement.getPrevSibling(); - } - if (prevElement instanceof PyAssignmentStatement) { - if (expr.getText().contains("type:")) return true; + final PsiElement parent = expr.getParent(); + if (!(parent instanceof PyExpressionStatement)) { + return false; + } + PsiElement prevElement = parent.getPrevSibling(); + while (prevElement instanceof PsiWhiteSpace || prevElement instanceof PsiComment) { + prevElement = prevElement.getPrevSibling(); + } + if (prevElement instanceof PyAssignmentStatement) { + if (expr.getText().contains("type:")) return true; - final PyAssignmentStatement assignmentStatement = (PyAssignmentStatement)prevElement; - final ScopeOwner scope = PsiTreeUtil.getParentOfType(prevElement, ScopeOwner.class); - if (scope instanceof PyClass || scope instanceof PyFile) { - return true; - } - if (scope instanceof PyFunction) { - for (PyExpression target : assignmentStatement.getTargets()) { - if (PyUtil.isInstanceAttribute(target)) { - return true; - } + final PyAssignmentStatement assignmentStatement = (PyAssignmentStatement)prevElement; + final ScopeOwner scope = PsiTreeUtil.getParentOfType(prevElement, ScopeOwner.class); + if (scope instanceof PyClass || scope instanceof PyFile) { + return true; + } + if (scope instanceof PyFunction) { + for (PyExpression target : assignmentStatement.getTargets()) { + if (PyUtil.isInstanceAttribute(target)) { + return true; } } } diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java index 6bdca7aaf470..ceda9ec399b4 100644 --- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java +++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java @@ -140,15 +140,7 @@ public class PythonInspectionsTest extends PyTestCase { } public void testPyStatementEffectInspection() { - final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule()); - final String oldFormat = documentationSettings.getFormat(); - try { - documentationSettings.setFormat(DocStringFormat.EPYTEXT); - doHighlightingTest(PyStatementEffectInspection.class, LanguageLevel.PYTHON26); - } - finally { - documentationSettings.setFormat(oldFormat); - } + doHighlightingTest(PyStatementEffectInspection.class, LanguageLevel.PYTHON26); } public void testPySimplifyBooleanCheckInspection() { From 9486c83b1623e529beb21b8c344ff1686fbe2b5e Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 15:34:27 +0400 Subject: [PATCH 2/9] Removed unused method --- .../com/jetbrains/python/documentation/DocStringUtil.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index 833a897310f6..5f25e1e2b82a 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -17,12 +17,6 @@ public class DocStringUtil { private DocStringUtil() { } - public static String trimDocString(String s) { - return s.trim() - .replaceFirst("^((:py)?:class:`[~!]?|[A-Z]\\{)", "") - .replaceFirst("(`|\\})?\\.?$", ""); - } - @Nullable public static String getDocStringValue(@NotNull PyDocStringOwner owner) { return PyPsiUtils.strValue(owner.getDocStringExpression()); From 5f5b83d7631240a5c101c837d8ef5994b069f7b1 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 16:09:41 +0400 Subject: [PATCH 3/9] Updated misplaced docstring test --- python/testData/inspections/MoveDocstring.py | 7 +++---- python/testData/inspections/MoveDocstring_after.py | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/python/testData/inspections/MoveDocstring.py b/python/testData/inspections/MoveDocstring.py index 468be246dd68..1db4e3f4d282 100644 --- a/python/testData/inspections/MoveDocstring.py +++ b/python/testData/inspections/MoveDocstring.py @@ -1,9 +1,8 @@ class GetCustomerPaymentProfileRequest(CustomerRequest): - _keys = CustomerRequest._keys + ["customerPaymentProfileId"] + def __init__(self, user, profileid): + CustomerRequest.__init__(self, user, + customerPaymentProfileId=profileid) """ Gets a payment profile by user Account object and authorize.net profileid of the payment profile. """ - def __init__(self, user, profileid): - CustomerRequest.__init__(self, user, - customerPaymentProfileId=profileid) \ No newline at end of file diff --git a/python/testData/inspections/MoveDocstring_after.py b/python/testData/inspections/MoveDocstring_after.py index e262aaa10637..1833c32c75fe 100644 --- a/python/testData/inspections/MoveDocstring_after.py +++ b/python/testData/inspections/MoveDocstring_after.py @@ -3,8 +3,7 @@ class GetCustomerPaymentProfileRequest(CustomerRequest): Gets a payment profile by user Account object and authorize.net profileid of the payment profile. """ - _keys = CustomerRequest._keys + ["customerPaymentProfileId"] def __init__(self, user, profileid): CustomerRequest.__init__(self, user, - customerPaymentProfileId=profileid) \ No newline at end of file + customerPaymentProfileId=profileid) From 74e266886c6adcb50c7913a63d97dc8bb92fa661 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 16:13:16 +0400 Subject: [PATCH 4/9] Made PyUtil.isInstanceAttribute() stub-safe --- python/src/com/jetbrains/python/psi/PyUtil.java | 3 +++ python/src/com/jetbrains/python/psi/impl/PyClassImpl.java | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index e1413a826059..4e95bcf3d29b 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -443,6 +443,9 @@ public class PyUtil { if (owner instanceof PyFunction) { final PyFunction method = (PyFunction)owner; if (method.getContainingClass() != null) { + if (method.getStub() != null) { + return true; + } final PyParameter[] params = method.getParameterList().getParameters(); if (params.length > 0) { final PyTargetExpression targetExpr = (PyTargetExpression)target; diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 829cde42f98e..0cfb00d6223b 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -926,9 +926,8 @@ public class PyClassImpl extends PyPresentableElementImpl implement if (params.length == 0) { return; } - final PyFunctionStub methodStub = method.getStub(); for (PyTargetExpression target : getTargetExpressions(method)) { - if (methodStub != null || PyUtil.isInstanceAttribute(target)) { + if (PyUtil.isInstanceAttribute(target)) { result.put(target.getName(), target); } } From af9d57966361dbda3d6987ce1d2f6ad55615da0b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 16:23:37 +0400 Subject: [PATCH 5/9] Extracted PyUtil.isAttribute() --- .../python/documentation/PyDocumentationBuilder.java | 5 +---- python/src/com/jetbrains/python/psi/PyUtil.java | 4 ++++ .../python/psi/impl/references/PyQualifiedReference.java | 8 ++------ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java index 99aa25356fa6..a54cc473d5d5 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java @@ -14,7 +14,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonFileType; -import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.console.PyConsoleUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; @@ -229,9 +228,7 @@ class PyDocumentationBuilder { } private boolean isAttribute() { - return myElement instanceof PyTargetExpression && - (PyUtil.isInstanceAttribute((PyTargetExpression)myElement) || - PsiTreeUtil.getParentOfType(myElement, ScopeOwner.class) instanceof PyClass); + return myElement instanceof PyTargetExpression && PyUtil.isAttribute((PyTargetExpression)myElement); } @Nullable diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 4e95bcf3d29b..f01213651151 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -435,6 +435,10 @@ public class PyUtil { if (!thing) throw new IncorrectOperationException(); } + public static boolean isAttribute(PyTargetExpression ex) { + return isInstanceAttribute(ex) || isClassAttribute(ex); + } + public static boolean isInstanceAttribute(PyExpression target) { if (!(target instanceof PyTargetExpression)) { return false; diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index 543f6fcb3fd5..68285124ba00 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java @@ -429,8 +429,8 @@ public class PyQualifiedReference extends PyReferenceImpl { if (resolveResult == element) { return true; } - if (resolveResult instanceof PyTargetExpression && isInstanceOrClassAttribute((PyTargetExpression)resolveResult) && - element instanceof PyTargetExpression && isInstanceOrClassAttribute((PyTargetExpression)element) && Comparing.equal( + if (resolveResult instanceof PyTargetExpression && PyUtil.isAttribute((PyTargetExpression)resolveResult) && + element instanceof PyTargetExpression && PyUtil.isAttribute((PyTargetExpression)element) && Comparing.equal( ((PyTargetExpression)resolveResult).getReferencedName(), ((PyTargetExpression)element).getReferencedName())) { PyClass aClass = PsiTreeUtil.getParentOfType(resolveResult, PyClass.class); @@ -448,10 +448,6 @@ public class PyQualifiedReference extends PyReferenceImpl { return false; } - private static boolean isInstanceOrClassAttribute(PyTargetExpression ex) { - return PyUtil.isInstanceAttribute(ex) || PyUtil.isClassAttribute(ex); - } - private static boolean isSubclass(@Nullable PyClass aClass, @Nullable PyClass bClass) { if (aClass == null || bClass == null) { return false; From b040b18c8c4817bd5d327523638eaea8dbf55876 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 15 Aug 2013 16:48:31 +0400 Subject: [PATCH 6/9] Extract attribute type from class docstring (PY-6584) --- .../psi/impl/PyTargetExpressionImpl.java | 24 ++++++++---- .../com/jetbrains/python/PyTypeTest.java | 38 +++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index eb278620b1a4..804c9c1255e2 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -250,19 +250,29 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl Date: Thu, 15 Aug 2013 16:59:46 +0400 Subject: [PATCH 7/9] Pulled getVirtualFileByName() up to PyTestCase --- .../com/jetbrains/python/PyControlFlowBuilderTest.java | 4 +--- .../testSrc/com/jetbrains/python/PyQuickDocTest.java | 4 +--- .../jetbrains/python/fixtures/LightMarkedTestCase.java | 4 +--- .../com/jetbrains/python/fixtures/PyTestCase.java | 7 +++++++ .../python/refactoring/PyCodeFragmentTest.java | 4 +--- .../com/jetbrains/python/refactoring/PyMoveTest.java | 7 ------- .../com/jetbrains/python/refactoring/PyRenameTest.java | 10 +--------- 7 files changed, 12 insertions(+), 28 deletions(-) diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index da0bb6533ef8..09695ea2bcf1 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -3,7 +3,6 @@ package com.jetbrains.python; import com.intellij.codeInsight.controlflow.ControlFlow; import com.intellij.codeInsight.controlflow.Instruction; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; @@ -14,7 +13,6 @@ import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFunction; -import java.io.File; import java.io.IOException; /** @@ -234,7 +232,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { for (Instruction instruction : instructions) { buffer.append(instruction).append("\n"); } - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/')); + final VirtualFile vFile = getVirtualFileByName(fullPath); try { final String fileText = StringUtil.convertLineSeparators(VfsUtil.loadText(vFile), "\n"); assertEquals(fileText.trim(), buffer.toString().trim()); diff --git a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java index de9ea7ff9c04..9747a59c770f 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java @@ -1,7 +1,6 @@ package com.jetbrains.python; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -11,7 +10,6 @@ import com.jetbrains.python.fixtures.LightMarkedTestCase; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; -import java.io.File; import java.io.IOException; import java.util.Map; @@ -35,7 +33,7 @@ public class PyQuickDocTest extends LightMarkedTestCase { private void checkByHTML(String text, @TestDataFile String filePath) { final String fullPath = getTestDataPath() + filePath; - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/')); + final VirtualFile vFile = getVirtualFileByName(fullPath); assertNotNull("file " + fullPath + " not found", vFile); String loadedText; diff --git a/python/testSrc/com/jetbrains/python/fixtures/LightMarkedTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/LightMarkedTestCase.java index ef40041264eb..73a06d79a220 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/LightMarkedTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/LightMarkedTestCase.java @@ -1,7 +1,6 @@ package com.jetbrains.python.fixtures; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -10,7 +9,6 @@ import com.intellij.testFramework.TestDataFile; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; -import java.io.File; import java.io.IOException; import java.util.Map; import java.util.regex.Matcher; @@ -49,7 +47,7 @@ public abstract class LightMarkedTestCase extends PyTestCase { */ protected Map configureByFile(@TestDataFile @NonNls String filePath, @NonNls String markerRegexp) { final String fullPath = getTestDataPath() + filePath; - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/')); + final VirtualFile vFile = getVirtualFileByName(fullPath); assertNotNull("file " + fullPath + " not found", vFile); final String text; diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java index 2e78bb6f40da..7a1d27ddcac9 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java @@ -31,6 +31,8 @@ import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + /** * @author yole */ @@ -46,6 +48,11 @@ public abstract class PyTestCase extends UsefulTestCase { protected CodeInsightTestFixture myFixture; private static boolean ourPlatformPrefixInitialized; + @Nullable + protected static VirtualFile getVirtualFileByName(String fileName) { + return LocalFileSystem.getInstance().findFileByPath(fileName.replace(File.separatorChar, '/')); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java index 8f46ff540429..2b8510418040 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java @@ -4,7 +4,6 @@ import com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException; import com.intellij.codeInsight.codeFragment.CodeFragment; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -15,7 +14,6 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.fixtures.LightMarkedTestCase; import com.jetbrains.python.psi.PyFile; -import java.io.File; import java.util.TreeSet; /** @@ -35,7 +33,7 @@ public class PyCodeFragmentTest extends LightMarkedTestCase { final String testName = getTestName(false).toLowerCase(); final String fullPath = getTestDataPath() + testName + ".test"; - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/')); + final VirtualFile vFile = getVirtualFileByName(fullPath); String fileText = StringUtil.convertLineSeparators(VfsUtil.loadText(vFile), "\n"); final int beginMarker = fileText.indexOf(BEGIN_MARKER); diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index 83da6385f4f3..198285281b9b 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -1,7 +1,6 @@ package com.jetbrains.python.refactoring; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor; @@ -16,7 +15,6 @@ import com.jetbrains.python.psi.stubs.PyFunctionNameIndex; import com.jetbrains.python.refactoring.move.PyMoveClassOrFunctionProcessor; import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; import java.util.Collection; @@ -178,11 +176,6 @@ public class PyMoveTest extends PyTestCase { } } - @Nullable - private static VirtualFile getVirtualFileByName(String fileName) { - return LocalFileSystem.getInstance().findFileByPath(fileName.replace(File.separatorChar, '/')); - } - @Nullable private PsiNamedElement findFirstNamedElement(String name) { final Collection classes = PyClassNameIndex.find(name, myFixture.getProject(), false); diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java index bc5360ad931d..e0d58067cbb6 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java @@ -1,7 +1,6 @@ package com.jetbrains.python.refactoring; import com.intellij.codeInsight.TargetElementUtilBase; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -10,9 +9,7 @@ import com.intellij.testFramework.PlatformTestUtil; import com.jetbrains.python.PythonTestUtil; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.LanguageLevel; -import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; /** @@ -197,7 +194,7 @@ public class PyRenameTest extends PyTestCase { PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments(); myFixture.configureFromTempProjectFile("a.py"); myFixture.renameElementAtCaret(newName); - VirtualFile dir2 = getVirtualFileByName(PythonTestUtil.getTestDataPath() + "/" + RENAME_DATA_PATH + testName + "/after"); + VirtualFile dir2 = PyTestCase.getVirtualFileByName(PythonTestUtil.getTestDataPath() + "/" + RENAME_DATA_PATH + testName + "/after"); try { PlatformTestUtil.assertDirectoriesEqual(dir2, dir1); } @@ -205,9 +202,4 @@ public class PyRenameTest extends PyTestCase { throw new RuntimeException(e); } } - - @Nullable - private static VirtualFile getVirtualFileByName(String fileName) { - return LocalFileSystem.getInstance().findFileByPath(fileName.replace(File.separatorChar, '/')); - } } From 2e8150a2e97b77410f0052386ee83a7c567d5f4b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 16 Aug 2013 14:07:24 +0400 Subject: [PATCH 8/9] Added stubs for docstrings of target expressions --- .../python/psi/PyTargetExpression.java | 3 +- .../psi/stubs/PyTargetExpressionStub.java | 3 + .../python/documentation/DocStringUtil.java | 18 ----- .../documentation/PyDocumentationBuilder.java | 2 +- .../python/psi/PyFileElementType.java | 3 +- .../psi/impl/PyTargetExpressionImpl.java | 76 +++++++++++++------ .../stubs/PyTargetExpressionElementType.java | 16 +++- .../stubs/PyTargetExpressionStubImpl.java | 16 +++- .../psi/stubs/PyInstanceAttributeIndex.java | 5 ++ .../python/psi/stubs/PyVariableNameIndex.java | 5 ++ .../stubs/TargetExpressionDocString.py | 6 ++ .../com/jetbrains/python/PyStubsTest.java | 8 ++ 12 files changed, 111 insertions(+), 50 deletions(-) create mode 100644 python/testData/stubs/TargetExpressionDocString.py diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyTargetExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyTargetExpression.java index 930a4c310af9..d27d84191bc7 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyTargetExpression.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyTargetExpression.java @@ -12,7 +12,8 @@ import org.jetbrains.annotations.Nullable; /** * @author yole */ -public interface PyTargetExpression extends PyQualifiedExpression, PsiNamedElement, PsiNameIdentifierOwner, StubBasedPsiElement { +public interface PyTargetExpression extends PyQualifiedExpression, PsiNamedElement, PsiNameIdentifierOwner, PyDocStringOwner, + StubBasedPsiElement { PyTargetExpression[] EMPTY_ARRAY = new PyTargetExpression[0]; /** diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java index aedd7d3740e0..7ec0c2e7788e 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java @@ -45,4 +45,7 @@ public interface PyTargetExpressionStub extends NamedStub { @Nullable T getCustomStub(Class stubClass); + + @Nullable + String getDocString(); } diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index 5f25e1e2b82a..812f518963e6 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -73,24 +73,6 @@ public class DocStringUtil { return false; } - @Nullable - public static PyStringLiteralExpression getAttributeDocString(@NotNull PyTargetExpression attr) { - if (attr.getParent() instanceof PyAssignmentStatement) { - final PyAssignmentStatement assignment = (PyAssignmentStatement)attr.getParent(); - PsiElement nextSibling = assignment.getNextSibling(); - while (nextSibling != null && (nextSibling instanceof PsiWhiteSpace || nextSibling instanceof PsiComment)) { - nextSibling = nextSibling.getNextSibling(); - } - if (nextSibling instanceof PyExpressionStatement) { - final PyExpression expression = ((PyExpressionStatement)nextSibling).getExpression(); - if (expression instanceof PyStringLiteralExpression) { - return (PyStringLiteralExpression)expression; - } - } - } - return null; - } - @Nullable public static String getAttributeDocComment(@NotNull PyTargetExpression attr) { if (attr.getParent() instanceof PyAssignmentStatement) { diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java index a54cc473d5d5..281f7b186865 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java @@ -446,7 +446,7 @@ class PyDocumentationBuilder { .addItem(" of class ").addWith(PythonDocumentationProvider.LinkMyClass, $().addWith(TagCode, $(cls.getName()))).addItem(BR) ; - final String docString = PyPsiUtils.strValue(DocStringUtil.getAttributeDocString((PyTargetExpression)myElement)); + final String docString = ((PyTargetExpression)myElement).getDocStringValue(); if (docString != null) { addFormattedDocString(myElement, docString, myBody, myEpilog); } diff --git a/python/src/com/jetbrains/python/psi/PyFileElementType.java b/python/src/com/jetbrains/python/psi/PyFileElementType.java index 355818dede2e..14154f11d6a9 100644 --- a/python/src/com/jetbrains/python/psi/PyFileElementType.java +++ b/python/src/com/jetbrains/python/psi/PyFileElementType.java @@ -47,7 +47,8 @@ public class PyFileElementType extends IStubFileElementType { @Override public int getStubVersion() { - return 47; + // Don't forget to update versions of indexes that use the updated stub-based elements + return 48; } @Nullable diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index 804c9c1255e2..97f0a39be9f2 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -4,10 +4,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiPolyVariantReference; -import com.intellij.psi.PsiReference; -import com.intellij.psi.ResolveResult; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; @@ -25,7 +22,6 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.Scope; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.documentation.DocStringUtil; -import com.jetbrains.python.psi.StructuredDocString; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.references.PyQualifiedReference; import com.jetbrains.python.psi.impl.references.PyTargetReference; @@ -120,10 +116,14 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl imp private final InitializerType myInitializerType; private final PyQualifiedName myInitializer; private final boolean myQualified; + @Nullable private final String myDocString; private final CustomTargetExpressionStub myCustomStub; - public PyTargetExpressionStubImpl(String name, CustomTargetExpressionStub customStub, StubElement parent) { + public PyTargetExpressionStubImpl(String name, + @Nullable String docString, + CustomTargetExpressionStub customStub, + StubElement parent) { super(parent, PyElementTypes.TARGET_EXPRESSION); myName = name; myInitializerType = InitializerType.Custom; myInitializer = null; myQualified = false; myCustomStub = customStub; + myDocString = docString; } - public PyTargetExpressionStubImpl(final String name, final InitializerType initializerType, + public PyTargetExpressionStubImpl(final String name, @Nullable String docString, final InitializerType initializerType, final PyQualifiedName initializer, final boolean qualified, final StubElement parentStub) { @@ -39,6 +44,7 @@ public class PyTargetExpressionStubImpl extends StubBase imp myInitializer = initializer; myQualified = qualified; myCustomStub = null; + myDocString = docString; } public String getName() { @@ -67,6 +73,12 @@ public class PyTargetExpressionStubImpl extends StubBase imp return null; } + @Nullable + @Override + public String getDocString() { + return myDocString; + } + @Override public String toString() { return "PyTargetExpressionStub(name=" + myName + ")"; diff --git a/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java index 408cf5183794..57967b31a39d 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java +++ b/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java @@ -16,6 +16,11 @@ import java.util.Collection; public class PyInstanceAttributeIndex extends StringStubIndexExtension { public static final StubIndexKey KEY = StubIndexKey.createIndexKey("Py.instanceAttribute.name"); + @Override + public int getVersion() { + return super.getVersion() + 1; + } + @NotNull @Override public StubIndexKey getKey() { diff --git a/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java index 392e974ef3cd..162734c51e6d 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java +++ b/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java @@ -16,6 +16,11 @@ import java.util.Collection; public class PyVariableNameIndex extends StringStubIndexExtension { public static final StubIndexKey KEY = StubIndexKey.createIndexKey("Py.variable.shortName"); + @Override + public int getVersion() { + return super.getVersion() + 1; + } + @NotNull public StubIndexKey getKey() { return KEY; diff --git a/python/testData/stubs/TargetExpressionDocString.py b/python/testData/stubs/TargetExpressionDocString.py new file mode 100644 index 000000000000..e6051a8b74e7 --- /dev/null +++ b/python/testData/stubs/TargetExpressionDocString.py @@ -0,0 +1,6 @@ +class C(object): + foo = None + """Foo docstring.""" + + bar = None + diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index fdf34339ee4c..95306b724a08 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -402,6 +402,14 @@ public class PyStubsTest extends PyTestCase { } classes = PyClassNameIndex.find("Foo", project, GlobalSearchScope.allScope(project)); assertEquals(classes.size(), 1); + } + public void testTargetExpressionDocString() { + final PyFile file = getTestFile(); + final PyClass c = file.findTopLevelClass("C"); + assertNotNull(c); + final PyTargetExpression foo = c.findClassAttribute("foo", false); + final String docString = foo.getDocStringValue(); + assertEquals("Foo docstring.", docString); } } From 1393f08bbc9cdcd4c86d93907f0465d0ab9221b6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 15 Aug 2013 13:49:55 +0400 Subject: [PATCH 9/9] notnull --- .../jetbrains/python/refactoring/PyRefactoringProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/refactoring/PyRefactoringProvider.java b/python/src/com/jetbrains/python/refactoring/PyRefactoringProvider.java index caee4384ea5b..84232bde99b1 100644 --- a/python/src/com/jetbrains/python/refactoring/PyRefactoringProvider.java +++ b/python/src/com/jetbrains/python/refactoring/PyRefactoringProvider.java @@ -17,6 +17,7 @@ import com.jetbrains.python.refactoring.introduce.parameter.PyIntroduceParameter import com.jetbrains.python.refactoring.introduce.constant.PyIntroduceConstantHandler; import com.jetbrains.python.refactoring.introduce.field.PyIntroduceFieldHandler; import com.jetbrains.python.refactoring.introduce.variable.PyIntroduceVariableHandler; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -59,7 +60,7 @@ public class PyRefactoringProvider extends RefactoringSupportProvider { } @Override - public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) { + public boolean isInplaceRenameAvailable(@NotNull PsiElement element, PsiElement context) { if (context != null && context.getContainingFile() != element.getContainingFile()) return false; PyFunction containingFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class); if (containingFunction != null) {