Fixed generation of type in docstring in case of it already presents as @param (PY-8930).

This commit is contained in:
Dmitry Trofimov
2013-02-21 13:26:02 +04:00
parent 9dfd89fe97
commit 3d9c6a7585
5 changed files with 56 additions and 21 deletions
@@ -112,19 +112,22 @@ public class PyDocstringGenerator {
throw new IllegalArgumentException("TemplateBuilder can be created only for one parameter");
}
builder.replaceRange(TextRange.create(getStartOffset(), getEndOffset()), getDefaultType());
int offset = getStartOffset();
if (offset > 0) {
builder.replaceRange(TextRange.create(offset, getEndOffset()), getDefaultType());
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
OpenFileDescriptor descriptor = new OpenFileDescriptor(
myProject,
myFile.getVirtualFile(),
myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
);
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
if (targetEditor != null) {
targetEditor.getCaretModel().moveToOffset(myDocStringExpression.getTextOffset());
TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
OpenFileDescriptor descriptor = new OpenFileDescriptor(
myProject,
myFile.getVirtualFile(),
myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
);
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
if (targetEditor != null) {
targetEditor.getCaretModel().moveToOffset(myDocStringExpression.getTextOffset());
TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
}
}
}
@@ -177,14 +180,13 @@ public class PyDocstringGenerator {
return docstring != null ? docstring.getText() : "\"\"\"\"\"\"";
}
public static Collection<DocstringParam> getParamsToAdd(StructuredDocString structuredDocString,
public static Collection<DocstringParam> getParamsToAdd(final StructuredDocString structuredDocString,
List<DocstringParam> params) {
final List<String> existingParameters =
structuredDocString != null ? structuredDocString.getParameters() : Lists.<String>newArrayList();
return Collections2.filter(params, new Predicate<DocstringParam>() {
@Override
public boolean apply(DocstringParam input) {
return !existingParameters.contains(input.getName());
Substring s = structuredDocString != null ? structuredDocString.getParamByNameAndKind(input.getName(), input.getKind()) : null;
return s == null;
}
});
}
@@ -309,9 +311,14 @@ public class PyDocstringGenerator {
}
public int getStartOffset() {
Pair<Integer, Integer> offsets = getOffsets();
return offsets != null ? offsets.first : -1;
}
private Pair<Integer, Integer> getOffsets() {
DocstringParam paramToEdit = getParamToEdit();
String paramName = paramToEdit.getName();
return myParamTypesOffset.get(paramName).first;
return myParamTypesOffset.get(paramName);
}
private DocstringParam getParamToEdit() {
@@ -322,12 +329,11 @@ public class PyDocstringGenerator {
}
public int getEndOffset() {
DocstringParam paramToEdit = getParamToEdit();
String paramName = paramToEdit.getName();
return myParamTypesOffset.get(paramName).second;
Pair<Integer, Integer> offsets = getOffsets();
return offsets != null ? offsets.second : -1;
}
private static class DocstringParam {
public static class DocstringParam {
private String myKind;
private String myName;
private String myType;
@@ -203,6 +203,16 @@ public abstract class StructuredDocString {
return results;
}
@Nullable
public Substring getParamByNameAndKind(@NotNull String name, String kind) {
for (Substring s: getTagArguments(kind)) {
if (name.equals(s.getValue())) {
return s;
}
}
return null;
}
public abstract List<String> getParameters();
public abstract List<String> getKeywordArguments();
@@ -0,0 +1,7 @@
def foo(bar, baz):
"""Do foo.
:type bar: object<caret>
:param bar: something
:return: something else
"""
return bar + baz
@@ -0,0 +1,6 @@
def foo(b<caret>ar, baz):
"""Do foo.
:param bar: something
:return: something else
"""
return bar + baz
@@ -41,6 +41,7 @@ public class PyIntentionTest extends PyTestCase {
/**
* Ensures that intention with given hint <i>is not</i> active.
*
* @param hint
*/
private void doNegativeTest(String hint) {
@@ -201,6 +202,7 @@ public class PyIntentionTest extends PyTestCase {
final IntentionAction action = myFixture.getAvailableIntention(PyBundle.message("INTN.convert.dict.literal.to.dict.constructor"));
assertNull(action);
}
public void testDictLiteralFormToConstructor3() {
myFixture.configureByFile("intentions/beforeDictLiteralFormToConstructor3" + ".py");
final IntentionAction action = myFixture.getAvailableIntention(PyBundle.message("INTN.convert.dict.literal.to.dict.constructor"));
@@ -254,7 +256,7 @@ public class PyIntentionTest extends PyTestCase {
public void testTransformConditionalExpression() { //PY-3094
doTest(PyBundle.message("INTN.transform.into.if.else.statement"));
}
public void testImportFromToImport() {
doTest("Convert to 'import sys'");
}
@@ -279,6 +281,10 @@ public class PyIntentionTest extends PyTestCase {
doNegativeTest(PyBundle.message("INTN.specify.return.type"));
}
public void testTypeInDocstring7() { //PY-8930
doDocReferenceTest();
}
private void doDocReferenceTest() {
doTest(PyBundle.message("INTN.specify.type"));
}