mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
references to parameters in docstrings, with rename and completion support
This commit is contained in:
@@ -287,6 +287,7 @@
|
||||
<applicationConfigurable implementation="com.jetbrains.python.documentation.PythonDocumentationConfigurable"/>
|
||||
<projectService serviceInterface="com.jetbrains.python.documentation.PyDocumentationSettings"
|
||||
serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings"/>
|
||||
<psi.referenceContributor implementation="com.jetbrains.python.documentation.DocStringReferenceContributor"/>
|
||||
|
||||
<!-- Django -->
|
||||
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.django.annotator.ViewMethodLineMarkerProvider"/>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.jetbrains.python.documentation;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReferenceBase;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.psi.PyDocStringOwner;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyNamedParameter;
|
||||
import com.jetbrains.python.psi.impl.ParamHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class DocStringParameterReference extends PsiReferenceBase<PsiElement> {
|
||||
public DocStringParameterReference(PsiElement element, TextRange range) {
|
||||
super(element, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
PyDocStringOwner owner = PsiTreeUtil.getParentOfType(getElement(), PyDocStringOwner.class);
|
||||
if (owner instanceof PyFunction) {
|
||||
final String paramName = getCanonicalText();
|
||||
return ((PyFunction) owner).getParameterList().getElementNamed(paramName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
PyDocStringOwner owner = PsiTreeUtil.getParentOfType(getElement(), PyDocStringOwner.class);
|
||||
if (owner instanceof PyFunction) {
|
||||
final List<PyNamedParameter> namedParameters = ParamHelper.collectNamedParameters(((PyFunction)owner).getParameterList());
|
||||
return ArrayUtil.toObjectArray(namedParameters);
|
||||
}
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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
|
||||
*/
|
||||
public class DocStringReferenceContributor extends PsiReferenceContributor {
|
||||
@Override
|
||||
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
|
||||
registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class),
|
||||
new DocStringReferenceProvider());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.jetbrains.python.documentation;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceProvider;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.psi.PyDocStringOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class DocStringReferenceProvider extends PsiReferenceProvider {
|
||||
private final String[] ALL_PARAM_TAGS;
|
||||
|
||||
public DocStringReferenceProvider() {
|
||||
List<String> allParamTags = new ArrayList<String>();
|
||||
for (String tag : EpydocString.PARAM_TAGS) {
|
||||
allParamTags.add("@" + tag);
|
||||
allParamTags.add(":" + tag);
|
||||
}
|
||||
ALL_PARAM_TAGS = ArrayUtil.toStringArray(allParamTags);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(element, PyDocStringOwner.class);
|
||||
if (docStringOwner != null && element == docStringOwner.getDocStringExpression()) {
|
||||
List<PsiReference> result = new ArrayList<PsiReference>();
|
||||
String docString = element.getText();
|
||||
int pos = 0;
|
||||
while (pos < docString.length()) {
|
||||
pos = findNextTag(docString, pos, ALL_PARAM_TAGS);
|
||||
if (pos < 0) {
|
||||
break;
|
||||
}
|
||||
pos = CharMatcher.anyOf(" \t*").negate().indexIn(docString, pos);
|
||||
int endPos = CharMatcher.JAVA_LETTER_OR_DIGIT.negate().indexIn(docString, pos);
|
||||
if (endPos < 0) {
|
||||
endPos = docString.length();
|
||||
}
|
||||
result.add(new DocStringParameterReference(element, new TextRange(pos, endPos)));
|
||||
pos = endPos;
|
||||
}
|
||||
|
||||
return result.toArray(new PsiReference[result.size()]);
|
||||
}
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static int findNextTag(String docString, int pos, String[] paramTags) {
|
||||
int result = Integer.MAX_VALUE;
|
||||
String foundTag = null;
|
||||
for (String paramTag : paramTags) {
|
||||
int tagPos = docString.indexOf(paramTag + " ", pos);
|
||||
if (tagPos >= 0 && tagPos < result) {
|
||||
foundTag = paramTag;
|
||||
result = tagPos;
|
||||
}
|
||||
}
|
||||
return foundTag == null ? -1 : result + foundTag.length();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
def foo(bar):
|
||||
""" @param bar """
|
||||
@@ -0,0 +1,2 @@
|
||||
def foo(bar):
|
||||
""" @param <caret> """
|
||||
@@ -0,0 +1,3 @@
|
||||
def func(fo<caret>o):
|
||||
""" @param foo: The parameter value."""
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
def func(bar):
|
||||
""" @param bar: The parameter value."""
|
||||
pass
|
||||
@@ -320,4 +320,8 @@ public class PythonCompletionTest extends PyLightFixtureTestCase {
|
||||
public void testReexportModules() { // PY-2385
|
||||
doMultiFileTest();
|
||||
}
|
||||
|
||||
public void testEpydocParamTag() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,10 @@ public class PyRenameTest extends PyLightFixtureTestCase {
|
||||
doTest("bar");
|
||||
}
|
||||
|
||||
public void testEpydocRenameParameter() {
|
||||
doTest("bar");
|
||||
}
|
||||
|
||||
public void testClassNameConflict() { // PY-2390
|
||||
doRenameConflictTest("Foo", "A class named 'Foo' is already defined in classNameConflict.py");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user