mirror of https://github.com/astral-sh/ruff
[ty] Enrich function argument auto-complete suggestions with annotated types
This commit is contained in:
parent
eac8a90cc4
commit
e548ce1ca9
|
|
@ -489,7 +489,7 @@ fn detect_function_arg_completions<'db>(
|
||||||
name,
|
name,
|
||||||
qualified: None,
|
qualified: None,
|
||||||
insert,
|
insert,
|
||||||
ty: None,
|
ty: p.ty,
|
||||||
kind: Some(CompletionKind::Variable),
|
kind: Some(CompletionKind::Variable),
|
||||||
module_name: None,
|
module_name: None,
|
||||||
import: None,
|
import: None,
|
||||||
|
|
@ -3243,8 +3243,6 @@ abc(okay=1, ba<CURSOR> baz=5
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn call_positional_only_argument() {
|
fn call_positional_only_argument() {
|
||||||
// If the parameter is positional only we don't
|
// If the parameter is positional only we don't
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||||
use ty_python_semantic::ResolvedDefinition;
|
use ty_python_semantic::ResolvedDefinition;
|
||||||
use ty_python_semantic::SemanticModel;
|
use ty_python_semantic::SemanticModel;
|
||||||
use ty_python_semantic::semantic_index::definition::Definition;
|
use ty_python_semantic::semantic_index::definition::Definition;
|
||||||
use ty_python_semantic::types::ParameterKind;
|
|
||||||
use ty_python_semantic::types::ide_support::{
|
use ty_python_semantic::types::ide_support::{
|
||||||
CallSignatureDetails, call_signature_details, find_active_signature_from_details,
|
CallSignatureDetails, call_signature_details, find_active_signature_from_details,
|
||||||
};
|
};
|
||||||
|
use ty_python_semantic::types::{ParameterKind, Type};
|
||||||
|
|
||||||
// TODO: We may want to add special-case handling for calls to constructors
|
// TODO: We may want to add special-case handling for calls to constructors
|
||||||
// so the class docstring is used in place of (or inaddition to) any docstring
|
// so the class docstring is used in place of (or inaddition to) any docstring
|
||||||
|
|
@ -28,11 +28,13 @@ use ty_python_semantic::types::ide_support::{
|
||||||
|
|
||||||
/// Information about a function parameter
|
/// Information about a function parameter
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ParameterDetails {
|
pub struct ParameterDetails<'db> {
|
||||||
/// The parameter name (e.g., "param1")
|
/// The parameter name (e.g., "param1")
|
||||||
pub name: String,
|
pub name: String,
|
||||||
/// The parameter label in the signature (e.g., "param1: str")
|
/// The parameter label in the signature (e.g., "param1: str")
|
||||||
pub label: String,
|
pub label: String,
|
||||||
|
/// The annotated type of the parameter, if any
|
||||||
|
pub ty: Option<Type<'db>>,
|
||||||
/// Documentation specific to the parameter, typically extracted from the
|
/// Documentation specific to the parameter, typically extracted from the
|
||||||
/// function's docstring
|
/// function's docstring
|
||||||
pub documentation: Option<String>,
|
pub documentation: Option<String>,
|
||||||
|
|
@ -42,13 +44,13 @@ pub struct ParameterDetails {
|
||||||
|
|
||||||
/// Information about a function signature
|
/// Information about a function signature
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct SignatureDetails {
|
pub struct SignatureDetails<'db> {
|
||||||
/// Text representation of the full signature (including input parameters and return type).
|
/// Text representation of the full signature (including input parameters and return type).
|
||||||
pub label: String,
|
pub label: String,
|
||||||
/// Documentation for the signature, typically from the function's docstring.
|
/// Documentation for the signature, typically from the function's docstring.
|
||||||
pub documentation: Option<Docstring>,
|
pub documentation: Option<Docstring>,
|
||||||
/// Information about each of the parameters in left-to-right order.
|
/// Information about each of the parameters in left-to-right order.
|
||||||
pub parameters: Vec<ParameterDetails>,
|
pub parameters: Vec<ParameterDetails<'db>>,
|
||||||
/// Index of the parameter that corresponds to the argument where the
|
/// Index of the parameter that corresponds to the argument where the
|
||||||
/// user's cursor is currently positioned.
|
/// user's cursor is currently positioned.
|
||||||
pub active_parameter: Option<usize>,
|
pub active_parameter: Option<usize>,
|
||||||
|
|
@ -56,18 +58,18 @@ pub struct SignatureDetails {
|
||||||
|
|
||||||
/// Signature help information for function calls
|
/// Signature help information for function calls
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct SignatureHelpInfo {
|
pub struct SignatureHelpInfo<'db> {
|
||||||
/// Information about each of the signatures for the function call. We
|
/// Information about each of the signatures for the function call. We
|
||||||
/// need to handle multiple because of unions, overloads, and composite
|
/// need to handle multiple because of unions, overloads, and composite
|
||||||
/// calls like constructors (which invoke both __new__ and __init__).
|
/// calls like constructors (which invoke both __new__ and __init__).
|
||||||
pub signatures: Vec<SignatureDetails>,
|
pub signatures: Vec<SignatureDetails<'db>>,
|
||||||
/// Index of the "active signature" which is the first signature where
|
/// Index of the "active signature" which is the first signature where
|
||||||
/// all arguments that are currently present in the code map to parameters.
|
/// all arguments that are currently present in the code map to parameters.
|
||||||
pub active_signature: Option<usize>,
|
pub active_signature: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature help information for function calls at the given position
|
/// Signature help information for function calls at the given position
|
||||||
pub fn signature_help(db: &dyn Db, file: File, offset: TextSize) -> Option<SignatureHelpInfo> {
|
pub fn signature_help(db: &dyn Db, file: File, offset: TextSize) -> Option<SignatureHelpInfo<'_>> {
|
||||||
let parsed = parsed_module(db, file).load(db);
|
let parsed = parsed_module(db, file).load(db);
|
||||||
|
|
||||||
// Get the call expression at the given position.
|
// Get the call expression at the given position.
|
||||||
|
|
@ -169,11 +171,11 @@ fn get_argument_index(call_expr: &ast::ExprCall, offset: TextSize) -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create signature details from `CallSignatureDetails`.
|
/// Create signature details from `CallSignatureDetails`.
|
||||||
fn create_signature_details_from_call_signature_details(
|
fn create_signature_details_from_call_signature_details<'db>(
|
||||||
db: &dyn crate::Db,
|
db: &dyn crate::Db,
|
||||||
details: &CallSignatureDetails,
|
details: &CallSignatureDetails<'db>,
|
||||||
current_arg_index: usize,
|
current_arg_index: usize,
|
||||||
) -> SignatureDetails {
|
) -> SignatureDetails<'db> {
|
||||||
let signature_label = details.label.clone();
|
let signature_label = details.label.clone();
|
||||||
|
|
||||||
let documentation = get_callable_documentation(db, details.definition);
|
let documentation = get_callable_documentation(db, details.definition);
|
||||||
|
|
@ -204,6 +206,7 @@ fn create_signature_details_from_call_signature_details(
|
||||||
documentation.as_ref(),
|
documentation.as_ref(),
|
||||||
&details.parameter_names,
|
&details.parameter_names,
|
||||||
&details.parameter_kinds,
|
&details.parameter_kinds,
|
||||||
|
&details.parameter_types,
|
||||||
);
|
);
|
||||||
SignatureDetails {
|
SignatureDetails {
|
||||||
label: signature_label,
|
label: signature_label,
|
||||||
|
|
@ -222,13 +225,14 @@ fn get_callable_documentation(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create `ParameterDetails` objects from parameter label offsets.
|
/// Create `ParameterDetails` objects from parameter label offsets.
|
||||||
fn create_parameters_from_offsets(
|
fn create_parameters_from_offsets<'db>(
|
||||||
parameter_offsets: &[TextRange],
|
parameter_offsets: &[TextRange],
|
||||||
signature_label: &str,
|
signature_label: &str,
|
||||||
docstring: Option<&Docstring>,
|
docstring: Option<&Docstring>,
|
||||||
parameter_names: &[String],
|
parameter_names: &[String],
|
||||||
parameter_kinds: &[ParameterKind],
|
parameter_kinds: &[ParameterKind],
|
||||||
) -> Vec<ParameterDetails> {
|
parameter_types: &[Option<Type<'db>>],
|
||||||
|
) -> Vec<ParameterDetails<'db>> {
|
||||||
// Extract parameter documentation from the function's docstring if available.
|
// Extract parameter documentation from the function's docstring if available.
|
||||||
let param_docs = if let Some(docstring) = docstring {
|
let param_docs = if let Some(docstring) = docstring {
|
||||||
docstring.parameter_documentation()
|
docstring.parameter_documentation()
|
||||||
|
|
@ -254,10 +258,12 @@ fn create_parameters_from_offsets(
|
||||||
parameter_kinds.get(i),
|
parameter_kinds.get(i),
|
||||||
Some(ParameterKind::PositionalOnly { .. })
|
Some(ParameterKind::PositionalOnly { .. })
|
||||||
);
|
);
|
||||||
|
let ty = parameter_types.get(i).copied().flatten();
|
||||||
|
|
||||||
ParameterDetails {
|
ParameterDetails {
|
||||||
name: param_name.to_string(),
|
name: param_name.to_string(),
|
||||||
label,
|
label,
|
||||||
|
ty,
|
||||||
documentation: param_docs.get(param_name).cloned(),
|
documentation: param_docs.get(param_name).cloned(),
|
||||||
is_positional_only,
|
is_positional_only,
|
||||||
}
|
}
|
||||||
|
|
@ -1183,7 +1189,7 @@ def ab(a: int, *, c: int):
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CursorTest {
|
impl CursorTest {
|
||||||
fn signature_help(&self) -> Option<SignatureHelpInfo> {
|
fn signature_help(&self) -> Option<SignatureHelpInfo<'_>> {
|
||||||
crate::signature_help::signature_help(&self.db, self.cursor.file, self.cursor.offset)
|
crate::signature_help::signature_help(&self.db, self.cursor.file, self.cursor.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,9 @@ pub struct CallSignatureDetails<'db> {
|
||||||
/// Parameter kinds, useful to determine correct autocomplete suggestions.
|
/// Parameter kinds, useful to determine correct autocomplete suggestions.
|
||||||
pub parameter_kinds: Vec<ParameterKind<'db>>,
|
pub parameter_kinds: Vec<ParameterKind<'db>>,
|
||||||
|
|
||||||
|
/// Parameter kinds, useful to determine correct autocomplete suggestions.
|
||||||
|
pub parameter_types: Vec<Option<Type<'db>>>,
|
||||||
|
|
||||||
/// The definition where this callable was originally defined (useful for
|
/// The definition where this callable was originally defined (useful for
|
||||||
/// extracting docstrings).
|
/// extracting docstrings).
|
||||||
pub definition: Option<Definition<'db>>,
|
pub definition: Option<Definition<'db>>,
|
||||||
|
|
@ -520,11 +523,12 @@ pub fn call_signature_details<'db>(
|
||||||
let display_details = signature.display(model.db()).to_string_parts();
|
let display_details = signature.display(model.db()).to_string_parts();
|
||||||
let parameter_label_offsets = display_details.parameter_ranges;
|
let parameter_label_offsets = display_details.parameter_ranges;
|
||||||
let parameter_names = display_details.parameter_names;
|
let parameter_names = display_details.parameter_names;
|
||||||
let parameter_kinds = signature
|
let (parameter_kinds, parameter_types): (Vec<ParameterKind>, Vec<Option<Type>>) =
|
||||||
|
signature
|
||||||
.parameters()
|
.parameters()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| param.kind().clone())
|
.map(|param| (param.kind().clone(), param.annotated_type()))
|
||||||
.collect();
|
.unzip();
|
||||||
|
|
||||||
CallSignatureDetails {
|
CallSignatureDetails {
|
||||||
definition: signature.definition(),
|
definition: signature.definition(),
|
||||||
|
|
@ -533,6 +537,7 @@ pub fn call_signature_details<'db>(
|
||||||
parameter_label_offsets,
|
parameter_label_offsets,
|
||||||
parameter_names,
|
parameter_names,
|
||||||
parameter_kinds,
|
parameter_kinds,
|
||||||
|
parameter_types,
|
||||||
argument_to_parameter_mapping,
|
argument_to_parameter_mapping,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue