mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
[ty] add docstrings to completions based on type (#20008)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
This is a fairly simple but effective way to add docstrings to like 95% of completions from initial experimentation. Fixes https://github.com/astral-sh/ty/issues/1036 Although ironically this approach *does not* work specifically for `print` and I haven't looked into why.
This commit is contained in:
parent
7b75aee21d
commit
859475f017
5 changed files with 64 additions and 9 deletions
|
@ -8,9 +8,11 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
|
|||
use ty_python_semantic::{Completion, NameKind, SemanticModel};
|
||||
|
||||
use crate::Db;
|
||||
use crate::docstring::Docstring;
|
||||
use crate::find_node::covering_node;
|
||||
use crate::goto::DefinitionsOrTargets;
|
||||
|
||||
pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<Completion<'_>> {
|
||||
pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<DetailedCompletion<'_>> {
|
||||
let parsed = parsed_module(db, file).load(db);
|
||||
|
||||
let Some(target_token) = CompletionTargetTokens::find(&parsed, offset) else {
|
||||
|
@ -40,6 +42,27 @@ pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<Completion<'
|
|||
completions.sort_by(compare_suggestions);
|
||||
completions.dedup_by(|c1, c2| c1.name == c2.name);
|
||||
completions
|
||||
.into_iter()
|
||||
.map(|completion| {
|
||||
let definition = DefinitionsOrTargets::from_ty(db, completion.ty);
|
||||
let documentation = definition.and_then(|def| def.docstring(db));
|
||||
DetailedCompletion {
|
||||
inner: completion,
|
||||
documentation,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub struct DetailedCompletion<'db> {
|
||||
pub inner: Completion<'db>,
|
||||
pub documentation: Option<Docstring>,
|
||||
}
|
||||
impl<'db> std::ops::Deref for DetailedCompletion<'db> {
|
||||
type Target = Completion<'db>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
/// The kind of tokens identified under the cursor.
|
||||
|
@ -478,9 +501,8 @@ fn compare_suggestions(c1: &Completion, c2: &Completion) -> Ordering {
|
|||
mod tests {
|
||||
use insta::assert_snapshot;
|
||||
use ruff_python_parser::{Mode, ParseOptions, TokenKind, Tokens};
|
||||
use ty_python_semantic::Completion;
|
||||
|
||||
use crate::completion;
|
||||
use crate::completion::{DetailedCompletion, completion};
|
||||
use crate::tests::{CursorTest, cursor_test};
|
||||
|
||||
use super::token_suffix_by_kinds;
|
||||
|
@ -3022,14 +3044,14 @@ from os.<CURSOR>
|
|||
)
|
||||
}
|
||||
|
||||
fn completions_if(&self, predicate: impl Fn(&Completion) -> bool) -> String {
|
||||
fn completions_if(&self, predicate: impl Fn(&DetailedCompletion) -> bool) -> String {
|
||||
self.completions_if_snapshot(predicate, |c| c.name.as_str().to_string())
|
||||
}
|
||||
|
||||
fn completions_if_snapshot(
|
||||
&self,
|
||||
predicate: impl Fn(&Completion) -> bool,
|
||||
snapshot: impl Fn(&Completion) -> String,
|
||||
predicate: impl Fn(&DetailedCompletion) -> bool,
|
||||
snapshot: impl Fn(&DetailedCompletion) -> String,
|
||||
) -> String {
|
||||
let completions = completion(&self.db, self.cursor.file, self.cursor.offset);
|
||||
if completions.is_empty() {
|
||||
|
|
|
@ -159,6 +159,28 @@ pub(crate) enum DefinitionsOrTargets<'db> {
|
|||
}
|
||||
|
||||
impl<'db> DefinitionsOrTargets<'db> {
|
||||
pub(crate) fn from_ty(db: &'db dyn crate::Db, ty: Type<'db>) -> Option<Self> {
|
||||
let ty_def = ty.definition(db)?;
|
||||
let resolved = match ty_def {
|
||||
ty_python_semantic::types::TypeDefinition::Module(module) => {
|
||||
ResolvedDefinition::Module(module.file(db)?)
|
||||
}
|
||||
ty_python_semantic::types::TypeDefinition::Class(definition) => {
|
||||
ResolvedDefinition::Definition(definition)
|
||||
}
|
||||
ty_python_semantic::types::TypeDefinition::Function(definition) => {
|
||||
ResolvedDefinition::Definition(definition)
|
||||
}
|
||||
ty_python_semantic::types::TypeDefinition::TypeVar(definition) => {
|
||||
ResolvedDefinition::Definition(definition)
|
||||
}
|
||||
ty_python_semantic::types::TypeDefinition::TypeAlias(definition) => {
|
||||
ResolvedDefinition::Definition(definition)
|
||||
}
|
||||
};
|
||||
Some(DefinitionsOrTargets::Definitions(vec![resolved]))
|
||||
}
|
||||
|
||||
/// Get the "goto-declaration" interpretation of this definition
|
||||
///
|
||||
/// In this case it basically returns exactly what was found.
|
||||
|
|
|
@ -2,7 +2,9 @@ use std::borrow::Cow;
|
|||
use std::time::Instant;
|
||||
|
||||
use lsp_types::request::Completion;
|
||||
use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, Url};
|
||||
use lsp_types::{
|
||||
CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, Documentation, Url,
|
||||
};
|
||||
use ruff_db::source::{line_index, source_text};
|
||||
use ty_ide::completion;
|
||||
use ty_project::ProjectDatabase;
|
||||
|
@ -64,9 +66,12 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler {
|
|||
.map(|(i, comp)| {
|
||||
let kind = comp.kind(db).map(ty_kind_to_lsp_kind);
|
||||
CompletionItem {
|
||||
label: comp.name.into(),
|
||||
label: comp.inner.name.into(),
|
||||
kind,
|
||||
sort_text: Some(format!("{i:-max_index_len$}")),
|
||||
documentation: comp
|
||||
.documentation
|
||||
.map(|docstring| Documentation::String(docstring.render_plaintext())),
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
|
|
|
@ -421,7 +421,10 @@ impl Workspace {
|
|||
.into_iter()
|
||||
.map(|completion| Completion {
|
||||
kind: completion.kind(&self.db).map(CompletionKind::from),
|
||||
name: completion.name.into(),
|
||||
name: completion.inner.name.into(),
|
||||
documentation: completion
|
||||
.documentation
|
||||
.map(|documentation| documentation.render_plaintext()),
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
@ -908,6 +911,8 @@ pub struct Completion {
|
|||
#[wasm_bindgen(getter_with_clone)]
|
||||
pub name: String,
|
||||
pub kind: Option<CompletionKind>,
|
||||
#[wasm_bindgen(getter_with_clone)]
|
||||
pub documentation: Option<String>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
|
|
@ -319,6 +319,7 @@ class PlaygroundServer
|
|||
? CompletionItemKind.Variable
|
||||
: mapCompletionKind(completion.kind),
|
||||
insertText: completion.name,
|
||||
documentation: completion.documentation,
|
||||
// TODO(micha): It's unclear why this field is required for monaco but not VS Code.
|
||||
// and omitting it works just fine? The LSP doesn't expose this information right now
|
||||
// which is why we go with undefined for now.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue