Skip to content

Commit 1d0b3a2

Browse files
committed
Add better documentation for classes, fixes #164
1 parent 590f37c commit 1d0b3a2

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

crates/zuban_python/src/lib.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ use matching::invalidate_protocol_cache;
5757
pub use name::{Name, NameSymbol, ValueName};
5858
pub use semantic_tokens::{SemanticToken, SemanticTokenProperties};
5959

60-
use crate::select_files::all_typechecked_files;
60+
use crate::{
61+
select_files::all_typechecked_files,
62+
type_::{CallableLike, Type},
63+
};
6164

6265
pub struct Project {
6366
db: Database,
@@ -392,11 +395,17 @@ impl<'project> Document<'project> {
392395
only_docstrings: bool,
393396
) -> anyhow::Result<Option<DocumentationResult<'_>>> {
394397
let mut types = vec![];
398+
let mut class_t = None;
395399
let mut resolver = GotoResolver::new(
396400
self.positional_document(position)?,
397401
GotoGoal::Indifferent,
398402
|n: ValueName| {
399403
if !only_docstrings {
404+
if class_t.is_none()
405+
&& let Type::Type(_) = n.type_
406+
{
407+
class_t = Some(n.type_.clone())
408+
}
400409
types.push(
401410
n.maybe_pretty_function_type()
402411
.unwrap_or_else(|| n.type_description())
@@ -456,7 +465,19 @@ impl<'project> Document<'project> {
456465
}
457466
}
458467
}
459-
out += &types.join(" | ");
468+
let db = &self.project.db;
469+
if let [description] = types.as_slice()
470+
&& let Some(class_t) = class_t
471+
&& let Some(CallableLike::Callable(callable)) =
472+
class_t.maybe_callable(&InferenceState::new_in_unknown_file(db))
473+
{
474+
out += description;
475+
let formatted = callable.format_pretty(&format_data::FormatData::new_short(db));
476+
out += "(";
477+
out += formatted.split_once('(').unwrap().1;
478+
} else {
479+
out += &types.join(" | ");
480+
}
460481
out += "\n```";
461482
if !results.is_empty() {
462483
out += "\n---\n";

crates/zuban_python/tests/mypylike/tests/documentation.test

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ WithGeneric
4545
WithoutGeneric
4646

4747
[out]
48-
__main__.py:2:documentation -> "```python\n(class) WithGeneric\n```\n---\nwith docs"
49-
__main__.py:7:documentation -> "```python\n(class) WithoutGeneric\n```\n---\nwithout docs"
50-
__main__.py:13:documentation -> "```python\n(class) WithGeneric\n```\n---\nwith docs"
51-
__main__.py:15:documentation -> "```python\n(class) WithoutGeneric\n```\n---\nwithout docs"
48+
__main__.py:2:documentation -> "```python\n(class) WithGeneric() -> WithGeneric[T]\n```\n---\nwith docs"
49+
__main__.py:7:documentation -> "```python\n(class) WithoutGeneric() -> WithoutGeneric\n```\n---\nwithout docs"
50+
__main__.py:13:documentation -> "```python\n(class) WithGeneric() -> WithGeneric[T]\n```\n---\nwith docs"
51+
__main__.py:15:documentation -> "```python\n(class) WithoutGeneric() -> WithoutGeneric\n```\n---\nwithout docs"
5252

5353
[case docs_alias]
5454

@@ -212,3 +212,26 @@ f(1)
212212

213213
[out]
214214
__main__.py:12:documentation -> "```python\n(function) Overload(def f(x: int) -> int, def f(x: str) -> str)\n```"
215+
216+
[case docs_on_type_of_class]
217+
from dataclasses import dataclass
218+
class A:
219+
""" a doc """
220+
def __init__(self, a: int, *, a2: str): ...
221+
class B: pass
222+
@dataclass
223+
class D:
224+
x: int
225+
y: str = ""
226+
227+
#? documentation
228+
A
229+
#? documentation
230+
B
231+
#? documentation
232+
D
233+
234+
[out]
235+
__main__.py:12:documentation -> "```python\n(class) A(a, *, a2: str) -> A\n```\n---\na doc"
236+
__main__.py:14:documentation -> "```python\n(class) B() -> B\n```"
237+
__main__.py:16:documentation -> "```python\n(class) D(x: int, y: str = ...) -> D\n```"

0 commit comments

Comments
 (0)