diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java index 55955e0622b4..53dea09e4f5c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java @@ -24,23 +24,34 @@ import com.intellij.util.ArrayUtil; import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.psi.*; + import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.regex.Pattern; /** * @author yole */ public class PyFunctionBuilder { + private static final String COMMENTS_BOUNDARY = "\"\"\""; + private static final Pattern INDENT_REMOVE_PATTERN = Pattern.compile("^\\s+", Pattern.MULTILINE); private final String myName; private final List myParameters = new ArrayList(); private final List myStatements = new ArrayList(); private final List myDecorators = new ArrayList(); private String myAnnotation = null; + private String[] myDocStringLines = null; - //TODO: Doc + /** + * Creates builder copying signature and doc from another one. + * @param source what to copy + * @param decoratorsToCopyIfExist list of decorator names to be copied to new function. + * @return builder configured by this function + */ @NotNull public static PyFunctionBuilder copySignature(@NotNull final PyFunction source, @NotNull final String... decoratorsToCopyIfExist) { final String name = source.getName(); @@ -62,9 +73,26 @@ public class PyFunctionBuilder { } } } + final String docString = source.getDocStringValue(); + if (docString != null) { + functionBuilder.docString(docString); + } return functionBuilder; } + /** + * Adds docstring to function. Provide doc with out of comment blocks. + * @param docString doc + */ + public void docString(@NotNull final String docString) { + myDocStringLines = StringUtil.splitByLines(removeIndent(docString)); + } + + @NotNull + private String removeIndent(@NotNull final String string) { + return INDENT_REMOVE_PATTERN.matcher(string).replaceAll(""); + } + public PyFunctionBuilder(String name) { myName = name; } @@ -118,6 +146,16 @@ public class PyFunctionBuilder { } builder.append(":"); List statements = myStatements.isEmpty() ? Collections.singletonList(PyNames.PASS) : myStatements; + + if (myDocStringLines != null) { + final List comments = new ArrayList(myDocStringLines.length + 2); + comments.add(COMMENTS_BOUNDARY); + comments.addAll(Arrays.asList(myDocStringLines)); + comments.add(COMMENTS_BOUNDARY); + statements = new ArrayList(statements); + statements.addAll(0, comments); + } + final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); int indentSize = codeStyleSettings.getIndentOptions(PythonFileType.INSTANCE).INDENT_SIZE; String indent = StringUtil.repeatSymbol(' ', indentSize); @@ -130,4 +168,11 @@ public class PyFunctionBuilder { public void decorate(String decoratorName) { myDecorators.add("@" + decoratorName); } + + @NotNull + private static String getIndent(@NotNull final Project project) { + final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); + final int indentSize = codeStyleSettings.getIndentOptions(PythonFileType.INSTANCE).INDENT_SIZE; + return StringUtil.repeatSymbol(' ', indentSize); + } } diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py index 9b1670daef11..bbf726c919ae 100644 --- a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py +++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py @@ -7,4 +7,7 @@ class NewParent(object): @abstractmethod def foo_method(self): + """ + Foo + """ pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py index 2da9618b43f0..6e71752a511d 100644 --- a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py +++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py @@ -3,4 +3,7 @@ from dest_module import NewParent class MyClass(NewParent): def foo_method(self): + """ + Foo + """ spam = "eggs" \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py index ed2d3668c71e..f4a7c42a7df4 100644 --- a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py +++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py @@ -1,3 +1,6 @@ class MyClass(object): def foo_method(self): + """ + Foo + """ spam = "eggs" \ No newline at end of file diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py index 91ab0b1c2b02..c0e75fa98646 100644 --- a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py +++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py @@ -1,6 +1,10 @@ from SuperClass import Parent class Child(Parent): def my_method(self, foo): + """ + Eats eggs + :param foo: eggs + """ bar = foo @classmethod diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py index 91ab0b1c2b02..c0e75fa98646 100644 --- a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py +++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py @@ -1,6 +1,10 @@ from SuperClass import Parent class Child(Parent): def my_method(self, foo): + """ + Eats eggs + :param foo: eggs + """ bar = foo @classmethod diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py index 8311ea6a630a..ded9ea669c57 100644 --- a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py +++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py @@ -4,6 +4,10 @@ from abc import object class Parent(object, metaclass=ABCMeta): @abstractmethod def my_method(self, foo): + """ + Eats eggs + :param foo: eggs + """ pass @classmethod