mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] Add "kind" to completion suggestions
This makes use of the new `Type` field on `Completion` to figure out the "kind" of a `Completion`. The mapping here is perhaps a little suspect for some cases. Closes astral-sh/ty#775
This commit is contained in:
parent
fea84e8777
commit
1eff0300d3
3 changed files with 134 additions and 6 deletions
|
@ -15,7 +15,7 @@ pub use program::{
|
||||||
PythonVersionWithSource, SearchPathSettings,
|
PythonVersionWithSource, SearchPathSettings,
|
||||||
};
|
};
|
||||||
pub use python_platform::PythonPlatform;
|
pub use python_platform::PythonPlatform;
|
||||||
pub use semantic_model::{Completion, HasType, NameKind, SemanticModel};
|
pub use semantic_model::{Completion, CompletionKind, HasType, NameKind, SemanticModel};
|
||||||
pub use site_packages::{PythonEnvironment, SitePackagesPaths, SysPrefixPathOrigin};
|
pub use site_packages::{PythonEnvironment, SitePackagesPaths, SysPrefixPathOrigin};
|
||||||
pub use util::diagnostics::add_inferred_python_version_hint_to_diagnostic;
|
pub use util::diagnostics::add_inferred_python_version_hint_to_diagnostic;
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,94 @@ pub struct Completion<'db> {
|
||||||
pub builtin: bool,
|
pub builtin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'db> Completion<'db> {
|
||||||
|
/// Returns the "kind" of this completion.
|
||||||
|
///
|
||||||
|
/// This is meant to be a very general classification of this completion.
|
||||||
|
/// Typically, this is communicated from the LSP server to a client, and
|
||||||
|
/// the client uses this information to help improve the UX (perhaps by
|
||||||
|
/// assigning an icon of some kind to the completion).
|
||||||
|
pub fn kind(&self, db: &'db dyn Db) -> Option<CompletionKind> {
|
||||||
|
fn imp<'db>(db: &'db dyn Db, ty: Type<'db>) -> Option<CompletionKind> {
|
||||||
|
Some(match ty {
|
||||||
|
Type::FunctionLiteral(_)
|
||||||
|
| Type::DataclassDecorator(_)
|
||||||
|
| Type::WrapperDescriptor(_)
|
||||||
|
| Type::DataclassTransformer(_)
|
||||||
|
| Type::Callable(_) => CompletionKind::Function,
|
||||||
|
Type::BoundMethod(_) | Type::MethodWrapper(_) => CompletionKind::Method,
|
||||||
|
Type::ModuleLiteral(_) => CompletionKind::Module,
|
||||||
|
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::SubclassOf(_) => {
|
||||||
|
CompletionKind::Class
|
||||||
|
}
|
||||||
|
// This is a little weird for "struct." I'm mostly interpreting
|
||||||
|
// "struct" here as a more general "object." ---AG
|
||||||
|
Type::NominalInstance(_)
|
||||||
|
| Type::PropertyInstance(_)
|
||||||
|
| Type::Tuple(_)
|
||||||
|
| Type::BoundSuper(_) => CompletionKind::Struct,
|
||||||
|
Type::IntLiteral(_)
|
||||||
|
| Type::BooleanLiteral(_)
|
||||||
|
| Type::TypeIs(_)
|
||||||
|
| Type::StringLiteral(_)
|
||||||
|
| Type::LiteralString
|
||||||
|
| Type::BytesLiteral(_) => CompletionKind::Value,
|
||||||
|
Type::ProtocolInstance(_) => CompletionKind::Interface,
|
||||||
|
Type::TypeVar(_) => CompletionKind::TypeParameter,
|
||||||
|
Type::Union(union) => union.elements(db).iter().find_map(|&ty| imp(db, ty))?,
|
||||||
|
Type::Intersection(intersection) => {
|
||||||
|
intersection.iter_positive(db).find_map(|ty| imp(db, ty))?
|
||||||
|
}
|
||||||
|
Type::Dynamic(_)
|
||||||
|
| Type::Never
|
||||||
|
| Type::SpecialForm(_)
|
||||||
|
| Type::KnownInstance(_)
|
||||||
|
| Type::AlwaysTruthy
|
||||||
|
| Type::AlwaysFalsy => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
imp(db, self.ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The "kind" of a completion.
|
||||||
|
///
|
||||||
|
/// This is taken directly from the LSP completion specification:
|
||||||
|
/// <https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemKind>
|
||||||
|
///
|
||||||
|
/// The idea here is that `Completion::kind` defines the mapping to this from
|
||||||
|
/// `Type` (and possibly other information), which might be interesting and
|
||||||
|
/// contentious. Then the outer edges map this to the LSP types, which is
|
||||||
|
/// expected to be mundane and boring.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum CompletionKind {
|
||||||
|
Text,
|
||||||
|
Method,
|
||||||
|
Function,
|
||||||
|
Constructor,
|
||||||
|
Field,
|
||||||
|
Variable,
|
||||||
|
Class,
|
||||||
|
Interface,
|
||||||
|
Module,
|
||||||
|
Property,
|
||||||
|
Unit,
|
||||||
|
Value,
|
||||||
|
Enum,
|
||||||
|
Keyword,
|
||||||
|
Snippet,
|
||||||
|
Color,
|
||||||
|
File,
|
||||||
|
Reference,
|
||||||
|
Folder,
|
||||||
|
EnumMember,
|
||||||
|
Constant,
|
||||||
|
Struct,
|
||||||
|
Event,
|
||||||
|
Operator,
|
||||||
|
TypeParameter,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait HasType {
|
pub trait HasType {
|
||||||
/// Returns the inferred type of `self`.
|
/// Returns the inferred type of `self`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use lsp_types::request::Completion;
|
use lsp_types::request::Completion;
|
||||||
use lsp_types::{CompletionItem, CompletionParams, CompletionResponse, Url};
|
use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, Url};
|
||||||
use ruff_db::source::{line_index, source_text};
|
use ruff_db::source::{line_index, source_text};
|
||||||
use ty_ide::completion;
|
use ty_ide::completion;
|
||||||
use ty_project::ProjectDatabase;
|
use ty_project::ProjectDatabase;
|
||||||
|
use ty_python_semantic::CompletionKind;
|
||||||
|
|
||||||
use crate::DocumentSnapshot;
|
use crate::DocumentSnapshot;
|
||||||
use crate::document::PositionExt;
|
use crate::document::PositionExt;
|
||||||
|
@ -55,10 +56,14 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler {
|
||||||
let items: Vec<CompletionItem> = completions
|
let items: Vec<CompletionItem> = completions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, comp)| CompletionItem {
|
.map(|(i, comp)| {
|
||||||
label: comp.name.into(),
|
let kind = comp.kind(db).map(ty_kind_to_lsp_kind);
|
||||||
sort_text: Some(format!("{i:-max_index_len$}")),
|
CompletionItem {
|
||||||
..Default::default()
|
label: comp.name.into(),
|
||||||
|
kind,
|
||||||
|
sort_text: Some(format!("{i:-max_index_len$}")),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let response = CompletionResponse::Array(items);
|
let response = CompletionResponse::Array(items);
|
||||||
|
@ -69,3 +74,38 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler {
|
||||||
impl RetriableRequestHandler for CompletionRequestHandler {
|
impl RetriableRequestHandler for CompletionRequestHandler {
|
||||||
const RETRY_ON_CANCELLATION: bool = true;
|
const RETRY_ON_CANCELLATION: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ty_kind_to_lsp_kind(kind: CompletionKind) -> CompletionItemKind {
|
||||||
|
// Gimme my dang globs in tight scopes!
|
||||||
|
#[allow(clippy::enum_glob_use)]
|
||||||
|
use self::CompletionKind::*;
|
||||||
|
|
||||||
|
// ref https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemKind
|
||||||
|
match kind {
|
||||||
|
Text => CompletionItemKind::TEXT,
|
||||||
|
Method => CompletionItemKind::METHOD,
|
||||||
|
Function => CompletionItemKind::FUNCTION,
|
||||||
|
Constructor => CompletionItemKind::CONSTRUCTOR,
|
||||||
|
Field => CompletionItemKind::FIELD,
|
||||||
|
Variable => CompletionItemKind::VARIABLE,
|
||||||
|
Class => CompletionItemKind::CLASS,
|
||||||
|
Interface => CompletionItemKind::INTERFACE,
|
||||||
|
Module => CompletionItemKind::MODULE,
|
||||||
|
Property => CompletionItemKind::PROPERTY,
|
||||||
|
Unit => CompletionItemKind::UNIT,
|
||||||
|
Value => CompletionItemKind::VALUE,
|
||||||
|
Enum => CompletionItemKind::ENUM,
|
||||||
|
Keyword => CompletionItemKind::KEYWORD,
|
||||||
|
Snippet => CompletionItemKind::SNIPPET,
|
||||||
|
Color => CompletionItemKind::COLOR,
|
||||||
|
File => CompletionItemKind::FILE,
|
||||||
|
Reference => CompletionItemKind::REFERENCE,
|
||||||
|
Folder => CompletionItemKind::FOLDER,
|
||||||
|
EnumMember => CompletionItemKind::ENUM_MEMBER,
|
||||||
|
Constant => CompletionItemKind::CONSTANT,
|
||||||
|
Struct => CompletionItemKind::STRUCT,
|
||||||
|
Event => CompletionItemKind::EVENT,
|
||||||
|
Operator => CompletionItemKind::OPERATOR,
|
||||||
|
TypeParameter => CompletionItemKind::TYPE_PARAMETER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue