Skip to content

Commit e548ce1

Browse files
RasmusNygrenBurntSushi
authored andcommitted
[ty] Enrich function argument auto-complete suggestions with annotated types
1 parent eac8a90 commit e548ce1

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

crates/ty_ide/src/completion.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ fn detect_function_arg_completions<'db>(
489489
name,
490490
qualified: None,
491491
insert,
492-
ty: None,
492+
ty: p.ty,
493493
kind: Some(CompletionKind::Variable),
494494
module_name: None,
495495
import: None,
@@ -3243,8 +3243,6 @@ abc(okay=1, ba<CURSOR> baz=5
32433243
);
32443244
}
32453245

3246-
3247-
32483246
#[test]
32493247
fn call_positional_only_argument() {
32503248
// If the parameter is positional only we don't

crates/ty_ide/src/signature_help.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,24 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
1717
use ty_python_semantic::ResolvedDefinition;
1818
use ty_python_semantic::SemanticModel;
1919
use ty_python_semantic::semantic_index::definition::Definition;
20-
use ty_python_semantic::types::ParameterKind;
2120
use ty_python_semantic::types::ide_support::{
2221
CallSignatureDetails, call_signature_details, find_active_signature_from_details,
2322
};
23+
use ty_python_semantic::types::{ParameterKind, Type};
2424

2525
// TODO: We may want to add special-case handling for calls to constructors
2626
// so the class docstring is used in place of (or inaddition to) any docstring
2727
// associated with the __new__ or __init__ call.
2828

2929
/// Information about a function parameter
3030
#[derive(Debug, Clone, PartialEq, Eq)]
31-
pub struct ParameterDetails {
31+
pub struct ParameterDetails<'db> {
3232
/// The parameter name (e.g., "param1")
3333
pub name: String,
3434
/// The parameter label in the signature (e.g., "param1: str")
3535
pub label: String,
36+
/// The annotated type of the parameter, if any
37+
pub ty: Option<Type<'db>>,
3638
/// Documentation specific to the parameter, typically extracted from the
3739
/// function's docstring
3840
pub documentation: Option<String>,
@@ -42,32 +44,32 @@ pub struct ParameterDetails {
4244

4345
/// Information about a function signature
4446
#[derive(Debug, Clone, PartialEq, Eq)]
45-
pub struct SignatureDetails {
47+
pub struct SignatureDetails<'db> {
4648
/// Text representation of the full signature (including input parameters and return type).
4749
pub label: String,
4850
/// Documentation for the signature, typically from the function's docstring.
4951
pub documentation: Option<Docstring>,
5052
/// Information about each of the parameters in left-to-right order.
51-
pub parameters: Vec<ParameterDetails>,
53+
pub parameters: Vec<ParameterDetails<'db>>,
5254
/// Index of the parameter that corresponds to the argument where the
5355
/// user's cursor is currently positioned.
5456
pub active_parameter: Option<usize>,
5557
}
5658

5759
/// Signature help information for function calls
5860
#[derive(Debug, Clone, PartialEq, Eq)]
59-
pub struct SignatureHelpInfo {
61+
pub struct SignatureHelpInfo<'db> {
6062
/// Information about each of the signatures for the function call. We
6163
/// need to handle multiple because of unions, overloads, and composite
6264
/// calls like constructors (which invoke both __new__ and __init__).
63-
pub signatures: Vec<SignatureDetails>,
65+
pub signatures: Vec<SignatureDetails<'db>>,
6466
/// Index of the "active signature" which is the first signature where
6567
/// all arguments that are currently present in the code map to parameters.
6668
pub active_signature: Option<usize>,
6769
}
6870

6971
/// Signature help information for function calls at the given position
70-
pub fn signature_help(db: &dyn Db, file: File, offset: TextSize) -> Option<SignatureHelpInfo> {
72+
pub fn signature_help(db: &dyn Db, file: File, offset: TextSize) -> Option<SignatureHelpInfo<'_>> {
7173
let parsed = parsed_module(db, file).load(db);
7274

7375
// Get the call expression at the given position.
@@ -169,11 +171,11 @@ fn get_argument_index(call_expr: &ast::ExprCall, offset: TextSize) -> usize {
169171
}
170172

171173
/// Create signature details from `CallSignatureDetails`.
172-
fn create_signature_details_from_call_signature_details(
174+
fn create_signature_details_from_call_signature_details<'db>(
173175
db: &dyn crate::Db,
174-
details: &CallSignatureDetails,
176+
details: &CallSignatureDetails<'db>,
175177
current_arg_index: usize,
176-
) -> SignatureDetails {
178+
) -> SignatureDetails<'db> {
177179
let signature_label = details.label.clone();
178180

179181
let documentation = get_callable_documentation(db, details.definition);
@@ -204,6 +206,7 @@ fn create_signature_details_from_call_signature_details(
204206
documentation.as_ref(),
205207
&details.parameter_names,
206208
&details.parameter_kinds,
209+
&details.parameter_types,
207210
);
208211
SignatureDetails {
209212
label: signature_label,
@@ -222,13 +225,14 @@ fn get_callable_documentation(
222225
}
223226

224227
/// Create `ParameterDetails` objects from parameter label offsets.
225-
fn create_parameters_from_offsets(
228+
fn create_parameters_from_offsets<'db>(
226229
parameter_offsets: &[TextRange],
227230
signature_label: &str,
228231
docstring: Option<&Docstring>,
229232
parameter_names: &[String],
230233
parameter_kinds: &[ParameterKind],
231-
) -> Vec<ParameterDetails> {
234+
parameter_types: &[Option<Type<'db>>],
235+
) -> Vec<ParameterDetails<'db>> {
232236
// Extract parameter documentation from the function's docstring if available.
233237
let param_docs = if let Some(docstring) = docstring {
234238
docstring.parameter_documentation()
@@ -254,10 +258,12 @@ fn create_parameters_from_offsets(
254258
parameter_kinds.get(i),
255259
Some(ParameterKind::PositionalOnly { .. })
256260
);
261+
let ty = parameter_types.get(i).copied().flatten();
257262

258263
ParameterDetails {
259264
name: param_name.to_string(),
260265
label,
266+
ty,
261267
documentation: param_docs.get(param_name).cloned(),
262268
is_positional_only,
263269
}
@@ -1183,7 +1189,7 @@ def ab(a: int, *, c: int):
11831189
}
11841190

11851191
impl CursorTest {
1186-
fn signature_help(&self) -> Option<SignatureHelpInfo> {
1192+
fn signature_help(&self) -> Option<SignatureHelpInfo<'_>> {
11871193
crate::signature_help::signature_help(&self.db, self.cursor.file, self.cursor.offset)
11881194
}
11891195

crates/ty_python_semantic/src/types/ide_support.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ pub struct CallSignatureDetails<'db> {
462462
/// Parameter kinds, useful to determine correct autocomplete suggestions.
463463
pub parameter_kinds: Vec<ParameterKind<'db>>,
464464

465+
/// Parameter kinds, useful to determine correct autocomplete suggestions.
466+
pub parameter_types: Vec<Option<Type<'db>>>,
467+
465468
/// The definition where this callable was originally defined (useful for
466469
/// extracting docstrings).
467470
pub definition: Option<Definition<'db>>,
@@ -520,11 +523,12 @@ pub fn call_signature_details<'db>(
520523
let display_details = signature.display(model.db()).to_string_parts();
521524
let parameter_label_offsets = display_details.parameter_ranges;
522525
let parameter_names = display_details.parameter_names;
523-
let parameter_kinds = signature
524-
.parameters()
525-
.iter()
526-
.map(|param| param.kind().clone())
527-
.collect();
526+
let (parameter_kinds, parameter_types): (Vec<ParameterKind>, Vec<Option<Type>>) =
527+
signature
528+
.parameters()
529+
.iter()
530+
.map(|param| (param.kind().clone(), param.annotated_type()))
531+
.unzip();
528532

529533
CallSignatureDetails {
530534
definition: signature.definition(),
@@ -533,6 +537,7 @@ pub fn call_signature_details<'db>(
533537
parameter_label_offsets,
534538
parameter_names,
535539
parameter_kinds,
540+
parameter_types,
536541
argument_to_parameter_mapping,
537542
}
538543
})

0 commit comments

Comments
 (0)