diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java b/python/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java index c4d0010cdefc..14157a977fdd 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java @@ -33,6 +33,7 @@ public class PythonCompletionWeigher extends CompletionWeigher { public static final int WEIGHT_DELTA = 5; + @NonNls private static final String SINGLE_UNDER = "_"; @NonNls private static final String DOUBLE_UNDER = "__"; @Override @@ -48,8 +49,11 @@ public class PythonCompletionWeigher extends CompletionWeigher { return element.getLookupString().length(); } if (name.startsWith(DOUBLE_UNDER)) { - if (name.endsWith(DOUBLE_UNDER)) return -2 * WEIGHT_DELTA; // __foo__ is lowest - else return -WEIGHT_DELTA; // __foo is lower than normal + if (name.endsWith(DOUBLE_UNDER)) return -4 * WEIGHT_DELTA; // __foo__ is lowest + else return -2 * WEIGHT_DELTA; // __foo is lower than normal + } + if (name.startsWith(SINGLE_UNDER)) { + return -1 * WEIGHT_DELTA; } return 0; // default } diff --git a/python/testData/completion/underscoredItemsOrderFromModuleImport/a.py b/python/testData/completion/underscoredItemsOrderFromModuleImport/a.py new file mode 100644 index 000000000000..8cb0330a11d8 --- /dev/null +++ b/python/testData/completion/underscoredItemsOrderFromModuleImport/a.py @@ -0,0 +1 @@ +from m1 import diff --git a/python/testData/completion/underscoredItemsOrderFromModuleImport/m1.py b/python/testData/completion/underscoredItemsOrderFromModuleImport/m1.py new file mode 100644 index 000000000000..fd3713f09983 --- /dev/null +++ b/python/testData/completion/underscoredItemsOrderFromModuleImport/m1.py @@ -0,0 +1,23 @@ +class A: + pass + +class _A: + pass + +class __A: + pass + +class B: + pass + +def f(): + pass + +def _f(): + pass + +def __f(): + pass + +def _g(): + pass diff --git a/python/testData/completion/underscoredItemsOrderModuleImport/a.py b/python/testData/completion/underscoredItemsOrderModuleImport/a.py new file mode 100644 index 000000000000..7d8aef0196fe --- /dev/null +++ b/python/testData/completion/underscoredItemsOrderModuleImport/a.py @@ -0,0 +1,2 @@ +import m1 +m1. \ No newline at end of file diff --git a/python/testData/completion/underscoredItemsOrderModuleImport/m1.py b/python/testData/completion/underscoredItemsOrderModuleImport/m1.py new file mode 100644 index 000000000000..fd3713f09983 --- /dev/null +++ b/python/testData/completion/underscoredItemsOrderModuleImport/m1.py @@ -0,0 +1,23 @@ +class A: + pass + +class _A: + pass + +class __A: + pass + +class B: + pass + +def f(): + pass + +def _f(): + pass + +def __f(): + pass + +def _g(): + pass diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index 8f8890f7be6b..e24c215c5c91 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -42,6 +42,15 @@ public class PythonCompletionTest extends PyTestCase { myFixture.checkResultByFile(getTestName(true) + "/a.after.py"); } + private void doMultiFileTestAssertSameOrderedElements(String... variants) { + myFixture.copyDirectoryToProject(getTestName(true), ""); + myFixture.configureByFile("a.py"); + myFixture.completeBasic(); + final List suggested = myFixture.getLookupElementStrings(); + assertNotNull(suggested); + assertOrderedEquals(suggested, variants); + } + @Nullable private List doTestByText(@NotNull String text) { myFixture.configureByText(PythonFileType.INSTANCE, text); @@ -1262,22 +1271,23 @@ public class PythonCompletionTest extends PyTestCase { // PY-28461 public void testImplicitImportsInsidePackage() { runWithLanguageLevel(LanguageLevel.PYTHON37, - () -> doMultiFileAssertSameElements("m1", "pkg2", "pkg3", "bar", "foo", "foo2")); + () -> doMultiFileTestAssertSameOrderedElements("bar", "foo", "foo2", "m1", "pkg2", "pkg3")); } // PY-28461 public void testImplicitImportsInsidePackagePy2() { runWithLanguageLevel(LanguageLevel.PYTHON27, - () -> doMultiFileAssertSameElements("m1", "pkg2", "pkg3", "bar", "foo", "foo2")); + () -> doMultiFileTestAssertSameOrderedElements("bar", "foo", "foo2", "m1", "pkg2", "pkg3")); } - private void doMultiFileAssertSameElements(String... variants) { - myFixture.copyDirectoryToProject(getTestName(true), ""); - myFixture.configureByFile("a.py"); - myFixture.completeBasic(); - final List suggested = myFixture.getLookupElementStrings(); - assertNotNull(suggested); - assertSameElements(suggested, variants); + // PY-3674 + public void testUnderscoredItemsOrderModuleImport() { + doMultiFileTestAssertSameOrderedElements("A", "B", "f", "_A", "_f", "_g", "__A", "__f"); + } + + // PY-3674 + public void testUnderscoredItemsOrderFromModuleImport() { + doMultiFileTestAssertSameOrderedElements("A", "B", "f", "_A", "_f", "_g", "__A", "__f"); } // PY-17810