diff --git a/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java index 3bea55856ffb..5d0d596fb518 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java @@ -185,12 +185,13 @@ public class PyDocstringGenerator { } /** - * @param alwaysAddReturn by default return declaration is added only if function body contains return statement. Sometimes it's not - * possible, e.g. in {@link com.jetbrains.python.editor.PythonEnterHandler} where unclosed docstring literal - * "captures" whole function body including return statements. + * @param addReturn by default return declaration is added only if function body contains return statement. Sometimes it's not + * possible, e.g. in {@link com.jetbrains.python.editor.PythonEnterHandler} where unclosed docstring literal + * "captures" whole function body including return statements. Keep in mind that declaration for the return value + * won't be added if containing function is __init__ or __new__ method. */ @NotNull - public PyDocstringGenerator withInferredParameters(boolean alwaysAddReturn) { + public PyDocstringGenerator withInferredParameters(boolean addReturn) { if (myDocStringOwner instanceof PyFunction) { for (PyParameter param : ((PyFunction)myDocStringOwner).getParameterList().getParameters()) { if (param.getAsNamed() == null) { @@ -206,7 +207,7 @@ public class PyDocstringGenerator { final RaiseVisitor visitor = new RaiseVisitor(); final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList(); statementList.accept(visitor); - if (visitor.myHasReturn || alwaysAddReturn) { + if (!isConstructor((PyFunction)myDocStringOwner) && (visitor.myHasReturn || addReturn)) { // will add :return: placeholder in Sphinx/Epydoc docstrings myAddedParams.add(new DocstringParam("", null, true)); if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) { @@ -217,6 +218,11 @@ public class PyDocstringGenerator { return this; } + private static boolean isConstructor(@NotNull PyFunction function) { + final String funcName = function.getName(); + return PyNames.INIT.equals(funcName) && function.getContainingClass() != null; + } + @NotNull public String getDocStringIndent() { return myDocStringIndent; diff --git a/python/testData/editing/enterDocstringStubNoReturnTagForInit.after.py b/python/testData/editing/enterDocstringStubNoReturnTagForInit.after.py new file mode 100644 index 000000000000..57014a37203f --- /dev/null +++ b/python/testData/editing/enterDocstringStubNoReturnTagForInit.after.py @@ -0,0 +1,7 @@ +class C: + def __init__(self, x, y): + """ + + :param x: + :param y: + """ \ No newline at end of file diff --git a/python/testData/editing/enterDocstringStubNoReturnTagForInit.py b/python/testData/editing/enterDocstringStubNoReturnTagForInit.py new file mode 100644 index 000000000000..427cb5630d3f --- /dev/null +++ b/python/testData/editing/enterDocstringStubNoReturnTagForInit.py @@ -0,0 +1,3 @@ +class C: + def __init__(self, x, y): + """ \ No newline at end of file diff --git a/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.after.py b/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.after.py new file mode 100644 index 000000000000..3a69569b39fc --- /dev/null +++ b/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.after.py @@ -0,0 +1,7 @@ +class C: + def __init__(self, x, y): + """ + Args: + x (): + y (): + """ \ No newline at end of file diff --git a/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.py b/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.py new file mode 100644 index 000000000000..427cb5630d3f --- /dev/null +++ b/python/testData/editing/spaceDocstringStubNoReturnSectionForInit.py @@ -0,0 +1,3 @@ +class C: + def __init__(self, x, y): + """ \ No newline at end of file diff --git a/python/testData/intentions/afterGoogleNoReturnSectionForInit.py b/python/testData/intentions/afterGoogleNoReturnSectionForInit.py new file mode 100644 index 000000000000..c17a4b8f7ae4 --- /dev/null +++ b/python/testData/intentions/afterGoogleNoReturnSectionForInit.py @@ -0,0 +1,9 @@ +class C: + def __init__(self, x, y): + """ + + Args: + x: + y: + """ + return None \ No newline at end of file diff --git a/python/testData/intentions/afterRestNoReturnTagForInit.py b/python/testData/intentions/afterRestNoReturnTagForInit.py new file mode 100644 index 000000000000..a238e01fd440 --- /dev/null +++ b/python/testData/intentions/afterRestNoReturnTagForInit.py @@ -0,0 +1,8 @@ +class C: + def __init__(self, x, y): + """ + + :param x: + :param y: + """ + return None \ No newline at end of file diff --git a/python/testData/intentions/beforeGoogleNoReturnSectionForInit.py b/python/testData/intentions/beforeGoogleNoReturnSectionForInit.py new file mode 100644 index 000000000000..3fefaa99e0ca --- /dev/null +++ b/python/testData/intentions/beforeGoogleNoReturnSectionForInit.py @@ -0,0 +1,3 @@ +class C: + def __init__(self, x, y): + return None \ No newline at end of file diff --git a/python/testData/intentions/beforeRestNoReturnTagForInit.py b/python/testData/intentions/beforeRestNoReturnTagForInit.py new file mode 100644 index 000000000000..3fefaa99e0ca --- /dev/null +++ b/python/testData/intentions/beforeRestNoReturnTagForInit.py @@ -0,0 +1,3 @@ +class C: + def __init__(self, x, y): + return None \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyEditingTest.java b/python/testSrc/com/jetbrains/python/PyEditingTest.java index c5b0d8ec55de..88aad1427f61 100644 --- a/python/testSrc/com/jetbrains/python/PyEditingTest.java +++ b/python/testSrc/com/jetbrains/python/PyEditingTest.java @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.util.Computable; import com.intellij.psi.PsiFile; +import com.jetbrains.python.codeInsight.PyCodeInsightSettings; import com.jetbrains.python.documentation.docstrings.DocStringFormat; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.LanguageLevel; @@ -271,6 +272,24 @@ public class PyEditingTest extends PyTestCase { public void testEnterNoDocstringStubWhenCodeExampleInDocstring() { doDocStringTypingTest("\n", DocStringFormat.GOOGLE); } + + // PY-15332 + public void testEnterDocstringStubNoReturnTagForInit() { + doDocStringTypingTest("\n", DocStringFormat.REST); + } + + // PY-15532 + public void testSpaceDocstringStubNoReturnSectionForInit() { + final PyCodeInsightSettings codeInsightSettings = PyCodeInsightSettings.getInstance(); + final boolean oldInsertTypeDocStub = codeInsightSettings.INSERT_TYPE_DOCSTUB; + codeInsightSettings.INSERT_TYPE_DOCSTUB = true; + try { + doDocStringTypingTest(" ", DocStringFormat.GOOGLE); + } + finally { + codeInsightSettings.INSERT_TYPE_DOCSTUB = oldInsertTypeDocStub; + } + } public void testEnterInString() { // PY-1738 doTestEnter("a = \"some string\"", "a = \"some \" \\\n" + diff --git a/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java b/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java index 3d218448a462..d200f8b5b43c 100644 --- a/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java +++ b/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java @@ -565,6 +565,16 @@ public class PyIntentionTest extends PyTestCase { } } + // PY-15332 + public void testGoogleNoReturnSectionForInit() { + doDocStubTest(DocStringFormat.GOOGLE); + } + + // PY-15332 + public void testRestNoReturnTagForInit() { + doDocStubTest(DocStringFormat.REST); + } + // PY-16904 public void testNumpyAddMissingParameterPreservesNoneIndent() { doDocAddMissingParamsTest(DocStringFormat.NUMPY);