completion of tag names in epydoc and sphinx docstrings

This commit is contained in:
Dmitry Jemerov
2011-04-20 21:17:18 +02:00
parent a04d5b85bc
commit cb2e4d4e9b
9 changed files with 112 additions and 9 deletions
@@ -288,6 +288,7 @@
<projectService serviceInterface="com.jetbrains.python.documentation.PyDocumentationSettings"
serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings"/>
<psi.referenceContributor implementation="com.jetbrains.python.documentation.DocStringReferenceContributor"/>
<completion.contributor language="Python" implementationClass="com.jetbrains.python.documentation.DocStringTagCompletionContributor"/>
<!-- Django -->
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.django.annotator.ViewMethodLineMarkerProvider"/>
@@ -2,9 +2,6 @@ package com.jetbrains.python.documentation;
import com.intellij.psi.PsiReferenceContributor;
import com.intellij.psi.PsiReferenceRegistrar;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author yole
@@ -12,7 +9,7 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
public class DocStringReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class),
registrar.registerReferenceProvider(DocStringTagCompletionContributor.DOCSTRING_PATTERN,
new DocStringReferenceProvider());
}
}
@@ -0,0 +1,68 @@
package com.jetbrains.python.documentation;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.PyDocStringOwner;
import com.jetbrains.python.psi.PyExpressionStatement;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author yole
*/
public class DocStringTagCompletionContributor extends CompletionContributor {
public static final PsiElementPattern.Capture<PyStringLiteralExpression> DOCSTRING_PATTERN = psiElement(PyStringLiteralExpression.class)
.withParent(psiElement(PyExpressionStatement.class).inside(PyDocStringOwner.class));
public DocStringTagCompletionContributor() {
extend(CompletionType.BASIC, psiElement().withParent(DOCSTRING_PATTERN),
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(parameters.getPosition().getProject());
if (settings.isEpydocFormat() || settings.isReSTFormat()) {
int offset = parameters.getOffset();
final PsiFile file = parameters.getOriginalFile();
final String text = file.getText();
char prefix = settings.isEpydocFormat() ? '@' : ':';
if (offset > 0) {
offset--;
}
StringBuilder prefixBuilder = new StringBuilder();
while(offset > 0 && (Character.isLetterOrDigit(text.charAt(offset)) || text.charAt(offset) == prefix)) {
prefixBuilder.insert(0, text.charAt(offset));
if (text.charAt(offset) == prefix) {
offset--;
break;
}
offset--;
}
while(offset > 0) {
offset--;
if (text.charAt(offset) == '\n' || text.charAt(offset) == '\"' || text.charAt(offset) == '\'') {
break;
}
if (!Character.isWhitespace(text.charAt(offset))) {
return;
}
}
String[] allTags = settings.isEpydocFormat() ? EpydocString.ALL_TAGS : SphinxDocString.ALL_TAGS;
if (prefixBuilder.length() > 0) {
result = result.withPrefixMatcher(prefixBuilder.toString());
}
for (String tag : allTags) {
result.addElement(LookupElementBuilder.create(tag));
}
}
}
}
);
}
}
@@ -16,6 +16,12 @@ public class EpydocString extends StructuredDocString {
public static String[] RTYPE_TAGS = new String[] { "rtype", "returntype" };
public static String[] KEYWORD_ARGUMENT_TAGS = new String[] { "keyword", "kwarg", "kwparam" };
public static String[] ALL_TAGS = new String[] {
"@param", "@type", "@return", "@rtype", "@keyword", "@raise", "@ivar", "@cvar", "@var", "@group", "@sort", "@note", "@attention",
"@bug", "@warning", "@version", "@todo", "@deprecated", "@since", "@status", "@change", "@permission", "@requires",
"@precondition", "@postcondition", "@invariant", "@author", "@organization", "@copyright", "@license", "@contact", "@summary", "@see"
};
public EpydocString(String docstringText) {
super(docstringText, "@");
}
@@ -7,6 +7,7 @@ import java.util.List;
*/
public class SphinxDocString extends StructuredDocString {
public static String[] KEYWORD_ARGUMENT_TAGS = new String[] { "keyword", "key" };
public static String[] ALL_TAGS = new String[] { ":param", ":keyword", ":type", ":raises", ":var", ":cvar", ":ivar", ":returns", ":rtype" };
public SphinxDocString(String docstringText) {
super(docstringText, ":");
@@ -44,7 +45,7 @@ public class SphinxDocString extends StructuredDocString {
@Override
public String getReturnDescription() {
return getTagValue("return");
return getTagValue(EpydocString.RETURN_TAGS);
}
@Override
+2
View File
@@ -0,0 +1,2 @@
def foo(bar):
""" <caret> """
@@ -0,0 +1,2 @@
def foo(bar):
""" @param """
@@ -0,0 +1,2 @@
def foo(bar):
""" @pa<caret> """
@@ -1,10 +1,8 @@
/*
* User: anna
* Date: 06-Mar-2008
*/
package com.jetbrains.python;
import com.intellij.codeInsight.lookup.LookupElement;
import com.jetbrains.python.documentation.DocStringFormat;
import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
@@ -324,4 +322,30 @@ public class PythonCompletionTest extends PyLightFixtureTestCase {
public void testEpydocParamTag() {
doTest();
}
public void testEpydocTags() {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getProject());
settings.setFormat(DocStringFormat.EPYTEXT);
try {
myFixture.configureByFile("completion/epydocTags.py");
myFixture.completeBasic();
assertTrue(myFixture.getLookupElementStrings().contains("@param"));
}
finally {
settings.setFormat(DocStringFormat.PLAIN);
}
}
public void testEpydocTagsMiddle() {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getProject());
settings.setFormat(DocStringFormat.EPYTEXT);
try {
myFixture.configureByFile("completion/epydocTagsMiddle.py");
myFixture.completeBasic();
myFixture.checkResultByFile("completion/epydocTagsMiddle.after.py");
}
finally {
settings.setFormat(DocStringFormat.PLAIN);
}
}
}