mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-29717 Display qualified name/path of a module for a top-level definition
This commit is contained in:
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.LineTokenizer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
@@ -309,6 +310,16 @@ public class PyDocumentationBuilder {
|
||||
myContent.add(formatDocString(myElement, docStringExpression.getStringValue()));
|
||||
}
|
||||
|
||||
if (PyUtil.isTopLevel(elementDefinition)) {
|
||||
final PsiFile containing = elementDefinition.getContainingFile();
|
||||
if (containing instanceof PyFile) {
|
||||
final String link = getLinkToModule((PyFile)containing);
|
||||
if (link != null) {
|
||||
myProlog.addItem(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (elementDefinition instanceof PyClass) {
|
||||
pyClass = (PyClass)elementDefinition;
|
||||
myBody.add(PythonDocumentationProvider.describeDecorators(pyClass, WRAP_IN_ITALIC, ESCAPE_AND_SAVE_NEW_LINES_AND_SPACES, BR, BR));
|
||||
@@ -502,12 +513,22 @@ public class PyDocumentationBuilder {
|
||||
.addWith(TagBold, $(ObjectUtils.chooseNotNull(QualifiedNameFinder.canonizeQualifiedName(name, null), name).toString()));
|
||||
}
|
||||
else {
|
||||
String path = file.getPath();
|
||||
myProlog.addWith(TagSpan.withAttribute("path", path), $("").addWith(TagSmall, $(path)));
|
||||
final String path = file.getPath();
|
||||
myProlog.addWith(TagSpan.withAttribute("path", path), $(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getLinkToModule(@NotNull PyFile module) {
|
||||
final QualifiedName name = QualifiedNameFinder.findCanonicalImportPath(module, null);
|
||||
if (name != null) {
|
||||
return PyDocumentationLink.toModule(name.toString(), name.toString());
|
||||
}
|
||||
final VirtualFile vFile = module.getVirtualFile();
|
||||
return vFile != null ? vFile.getPath() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getLinkToClass(@NotNull PyClass pyClass, boolean preferQualifiedName) {
|
||||
final String qualifiedName = pyClass.getQualifiedName();
|
||||
|
||||
@@ -17,12 +17,10 @@ package com.jetbrains.python.documentation
|
||||
|
||||
import com.intellij.codeInsight.documentation.DocumentationManagerProtocol
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFileSystemItem
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.util.QualifiedName
|
||||
import com.jetbrains.python.psi.PyClass
|
||||
import com.jetbrains.python.psi.PyFunction
|
||||
import com.jetbrains.python.psi.PyNamedParameter
|
||||
import com.jetbrains.python.psi.PyPsiFacade
|
||||
import com.jetbrains.python.psi.*
|
||||
import com.jetbrains.python.psi.types.PyClassType
|
||||
import com.jetbrains.python.psi.types.PyTypeParser
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext
|
||||
@@ -33,6 +31,7 @@ object PyDocumentationLink {
|
||||
private const val LINK_TYPE_PARAM = "#param#"
|
||||
private const val LINK_TYPE_TYPENAME = "#typename#"
|
||||
private const val LINK_TYPE_FUNC = "#func#"
|
||||
private const val LINK_TYPE_MODULE = "#module#"
|
||||
|
||||
@JvmStatic
|
||||
fun toContainingClass(content: String?): String {
|
||||
@@ -72,6 +71,11 @@ object PyDocumentationLink {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toModule(content: String, qualifiedName: String): String {
|
||||
return "<a href=\"${DocumentationManagerProtocol.PSI_ELEMENT_PROTOCOL}$LINK_TYPE_MODULE$qualifiedName\">$content</a>"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun elementForLink(link: String, element: PsiElement, context: TypeEvalContext): PsiElement? {
|
||||
return when {
|
||||
@@ -79,10 +83,23 @@ object PyDocumentationLink {
|
||||
link == LINK_TYPE_PARAM -> parameterPossibleClass(element, context)
|
||||
link.startsWith(LINK_TYPE_TYPENAME) -> possibleClass(link.substring(LINK_TYPE_TYPENAME.length), element, context)
|
||||
link.startsWith(LINK_TYPE_FUNC) -> possibleFunction(link.substring(LINK_TYPE_FUNC.length), element)
|
||||
link.startsWith(LINK_TYPE_MODULE) -> possibleModule(link.substring(LINK_TYPE_MODULE.length), element)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun possibleModule(qualifiedName: String, element: PsiElement): PyFile? {
|
||||
val facade = PyPsiFacade.getInstance(element.project)
|
||||
val qName = QualifiedName.fromDottedString(qualifiedName)
|
||||
|
||||
val resolveContext = facade.createResolveContextFromFoothold(element)
|
||||
return facade.resolveQualifiedName(qName, resolveContext)
|
||||
.filterIsInstance<PsiFileSystemItem>()
|
||||
.map { PyUtil.turnDirIntoInit(it) }
|
||||
.filterIsInstance<PyFile>()
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun possibleFunction(qualifiedName: String, element: PsiElement): PyFunction? {
|
||||
// TODO a better, more general way to resolve qualified names of function
|
||||
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#ArgumentList">ArgumentList</a><br>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>len</b>(o: Sized) -> <a href="psi_element://#typename#int">int</a></pre></div><div class='content'>len(object) -> integer<br><br>Return the number of items of a sequence or collection.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#__builtin__">__builtin__</a><br>def <b>len</b>(o: Sized) -> <a href="psi_element://#typename#int">int</a></pre></div><div class='content'>len(object) -> integer<br><br>Return the number of items of a sequence or collection.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#CallFunc">CallFunc</a><br>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>class <b>Foo</b>(<a href="psi_element://#typename#object">object</a>)</pre></div><div class='content'>Doc of Foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#ClassConstructor">ClassConstructor</a><br>class <b>Foo</b>(<a href="psi_element://#typename#object">object</a>)</pre></div><div class='content'>Doc of Foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>class <b>A</b>(metaclass=<a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Meta1">Meta1</a>, six.with_metaclass(<a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Meta2">Meta2</a>, <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base1">Base1</a>), <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base2">Base2</a>[<a href="psi_element://#typename#int">int</a>], <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base3">Base3</a>, Base4)</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#ClassWithAllKindSuperClassExpressions">ClassWithAllKindSuperClassExpressions</a><br>class <b>A</b>(metaclass=<a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Meta1">Meta1</a>, six.with_metaclass(<a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Meta2">Meta2</a>, <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base1">Base1</a>), <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base2">Base2</a>[<a href="psi_element://#typename#int">int</a>], <a href="psi_element://#typename#ClassWithAllKindSuperClassExpressions.Base3">Base3</a>, Base4)</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>class <b>Foo</b>(<a href="psi_element://#typename#object">object</a>)</pre></div><div class='content'>Doc of Foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#DirectClass">DirectClass</a><br>class <b>Foo</b>(<a href="psi_element://#typename#object">object</a>)</pre></div><div class='content'>Doc of Foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#DirectFunc">DirectFunc</a><br>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>(param: <a href="psi_element://#typename#bool">bool</a>) -> <a href="psi_element://#typename#bool">bool</a><br>Possible types:<br>• (param: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a><br>• (param: <a href="psi_element://#typename#int">int</a>) -> <a href="psi_element://#typename#int">int</a></pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#DocOnImplementationWithOverloads">DocOnImplementationWithOverloads</a><br>def <b>foo</b>(param: <a href="psi_element://#typename#bool">bool</a>) -> <a href="psi_element://#typename#bool">bool</a><br>Possible types:<br>• (param: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a><br>• (param: <a href="psi_element://#typename#int">int</a>) -> <a href="psi_element://#typename#int">int</a></pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#Docstring">Docstring</a><br>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>func</b>() -> Tuple</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#EmptyTupleType">EmptyTupleType</a><br>def <b>func</b>() -> Tuple</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>get_tuple</b>() -> Tuple[<a href="psi_element://#typename#int">int</a>, <a href="psi_element://#typename#int">int</a>, <a href="psi_element://#typename#str">str</a>]</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#HeterogeneousTuple">HeterogeneousTuple</a><br>def <b>get_tuple</b>() -> Tuple[<a href="psi_element://#typename#int">int</a>, <a href="psi_element://#typename#int">int</a>, <a href="psi_element://#typename#str">str</a>]</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>get_tuple</b>() -> Tuple[<a href="psi_element://#typename#str">str</a>, ...]</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#HomogeneousTuple">HomogeneousTuple</a><br>def <b>get_tuple</b>() -> Tuple[<a href="psi_element://#typename#str">str</a>, ...]</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.<br>It has two lines.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#Indented">Indented</a><br>def <b>foo</b>() -> None</pre></div><div class='content'>Doc of foo.<br>It has two lines.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>@<i>decorator1</i><br>@<i>decorator2</i><br>class <b>A</b></pre></div><div class='content'>Doc of A</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#ManyDecoratorsClass">ManyDecoratorsClass</a><br>@<i>decorator1</i><br>@<i>decorator2</i><br>class <b>A</b></pre></div><div class='content'>Doc of A</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>@<i>decorator1</i><br>@<i>decorator2</i><br>def <b>foo</b>(param: Any) -> Optional[Any]</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#ManyDecoratorsFunction">ManyDecoratorsFunction</a><br>@<i>decorator1</i><br>@<i>decorator2</i><br>def <b>foo</b>(param: Any) -> Optional[Any]</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>var: List[<a href="psi_element://#typename#int">int</a>] = [1,...</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#MultilineAssignedValueForTarget">MultilineAssignedValueForTarget</a><br>var: List[<a href="psi_element://#typename#int">int</a>] = [1,...</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>@<i>decorator</i><br>class <b>A</b></pre></div><div class='content'>Doc of A</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#OneDecoratorClass">OneDecoratorClass</a><br>@<i>decorator</i><br>class <b>A</b></pre></div><div class='content'>Doc of A</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>@<i>decorator</i><br>def <b>foo</b>(param: Any) -> Optional[Any]</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#OneDecoratorFunction">OneDecoratorFunction</a><br>@<i>decorator</i><br>def <b>foo</b>(param: Any) -> Optional[Any]</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>f</b>(x1: Optional[T], x2: Union[T, Tuple[Any, Any]]) -> None</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#OptionalAndUnionTypesContainingTypeVars">OptionalAndUnionTypesContainingTypeVars</a><br>def <b>f</b>(x1: Optional[T], x2: Union[T, Tuple[Any, Any]]) -> None</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>open</b>(encoding: Optional[<a href="psi_element://#typename#str">str</a>], errors: Optional[<a href="psi_element://#typename#str">str</a>]) -> None</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#OptionalParameterType">OptionalParameterType</a><br>def <b>open</b>(encoding: Optional[<a href="psi_element://#typename#str">str</a>], errors: Optional[<a href="psi_element://#typename#str">str</a>]) -> None</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>@<i>typing.overload</i><br>def <b>foo</b>(p: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a></pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#Overloads">Overloads</a><br>@<i>typing.overload</i><br>def <b>foo</b>(p: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a></pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>foo</b>(param: <a href="psi_element://#typename#bool">bool</a>) -> <a href="psi_element://#typename#bool">bool</a><br>Possible types:<br>• (param: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a><br>• (param: <a href="psi_element://#typename#int">int</a>) -> <a href="psi_element://#typename#int">int</a></pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#OverloadsAndImplementation">OverloadsAndImplementation</a><br>def <b>foo</b>(param: <a href="psi_element://#typename#bool">bool</a>) -> <a href="psi_element://#typename#bool">bool</a><br>Possible types:<br>• (param: <a href="psi_element://#typename#str">str</a>) -> <a href="psi_element://#typename#str">str</a><br>• (param: <a href="psi_element://#typename#int">int</a>) -> <a href="psi_element://#typename#int">int</a></pre></div></body></html>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>func</b>() -> None</pre></div><div class='content'>Docstring.</div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#PlainTextDocstringsQuotesPlacementDoesntAffectFormatting">PlainTextDocstringsQuotesPlacementDoesntAffectFormatting</a><br>def <b>func</b>() -> None</pre></div><div class='content'>Docstring.</div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>var: <a href="psi_element://#typename#int">int</a> = 42</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#SingleLineAssignedValueForTarget">SingleLineAssignedValueForTarget</a><br>var: <a href="psi_element://#typename#int">int</a> = 42</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>f</b>(p1: T1, p2: T2, p3: T3) -> None</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#TypeVars">TypeVars</a><br>def <b>f</b>(p1: T1, p2: T2, p3: T3) -> None</pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>def <b>get_tuple</b>() -> <a href="psi_element://#typename#tuple">tuple</a></pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#UnknownTuple">UnknownTuple</a><br>def <b>get_tuple</b>() -> <a href="psi_element://#typename#tuple">tuple</a></pre></div></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><div class='definition'><pre>var: Any = func()[0]</pre></div></body></html>
|
||||
<html><body><div class='definition'><pre><a href="psi_element://#module#UnmatchedAssignedValueForTarget">UnmatchedAssignedValueForTarget</a><br>var: Any = func()[0]</pre></div></body></html>
|
||||
Reference in New Issue
Block a user