Skip to content

Commit c7640a4

Browse files
UnboundVariableUnboundVariable
andauthored
[ty] Fixed bug in semantic token provider for parameters. (#19418)
This fixes astral-sh/ty#832. New tests were added to prevent future regressions. --------- Co-authored-by: UnboundVariable <[email protected]>
1 parent 1765014 commit c7640a4

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

crates/ty_ide/src/semantic_tokens.rs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -482,25 +482,40 @@ impl<'db> SemanticTokenVisitor<'db> {
482482
parameters: &ast::Parameters,
483483
func: Option<&ast::StmtFunctionDef>,
484484
) {
485-
// Parameters
486-
for (i, param) in parameters.args.iter().enumerate() {
487-
let token_type = if let Some(func) = func {
488-
// For function definitions, use the classification logic to determine
489-
// whether this is a self/cls parameter or just a regular parameter
490-
self.classify_parameter(&param.parameter, i == 0, func)
491-
} else {
492-
// For lambdas, all parameters are just parameters (no self/cls)
493-
SemanticTokenType::Parameter
485+
let mut param_index = 0;
486+
487+
for any_param in parameters {
488+
let parameter = any_param.as_parameter();
489+
490+
let token_type = match any_param {
491+
ast::AnyParameterRef::NonVariadic(_) => {
492+
// For non-variadic parameters (positional-only, regular, keyword-only),
493+
// check if this should be classified as self/cls parameter
494+
if let Some(func) = func {
495+
let result = self.classify_parameter(parameter, param_index == 0, func);
496+
param_index += 1;
497+
result
498+
} else {
499+
// For lambdas, all parameters are just parameters (no self/cls)
500+
param_index += 1;
501+
SemanticTokenType::Parameter
502+
}
503+
}
504+
ast::AnyParameterRef::Variadic(_) => {
505+
// Variadic parameters (*args, **kwargs) are always just parameters
506+
param_index += 1;
507+
SemanticTokenType::Parameter
508+
}
494509
};
495510

496511
self.add_token(
497-
param.parameter.name.range(),
512+
parameter.name.range(),
498513
token_type,
499514
SemanticTokenModifier::empty(),
500515
);
501516

502517
// Handle parameter type annotations
503-
if let Some(annotation) = &param.parameter.annotation {
518+
if let Some(annotation) = &parameter.annotation {
504519
self.visit_type_annotation(annotation);
505520
}
506521
}
@@ -977,7 +992,8 @@ class MyClass:
977992
class MyClass:
978993
def method(instance, x): pass
979994
@classmethod
980-
def other(klass, y): pass<CURSOR>
995+
def other(klass, y): pass
996+
def complex_method(instance, posonly, /, regular, *args, kwonly, **kwargs): pass<CURSOR>
981997
",
982998
);
983999

@@ -992,6 +1008,13 @@ class MyClass:
9921008
"other" @ 75..80: Method [definition]
9931009
"klass" @ 81..86: ClsParameter
9941010
"y" @ 88..89: Parameter
1011+
"complex_method" @ 105..119: Method [definition]
1012+
"instance" @ 120..128: SelfParameter
1013+
"posonly" @ 130..137: Parameter
1014+
"regular" @ 142..149: Parameter
1015+
"args" @ 152..156: Parameter
1016+
"kwonly" @ 158..164: Parameter
1017+
"kwargs" @ 168..174: Parameter
9951018
"#);
9961019
}
9971020

@@ -1665,6 +1688,12 @@ class BoundedContainer[T: int, U = str]:
16651688
"P" @ 324..325: Variable
16661689
"str" @ 327..330: Class
16671690
"wrapper" @ 341..348: Function [definition]
1691+
"args" @ 350..354: Parameter
1692+
"P" @ 356..357: Variable
1693+
"args" @ 358..362: Variable
1694+
"kwargs" @ 366..372: Parameter
1695+
"P" @ 374..375: Variable
1696+
"kwargs" @ 376..382: Variable
16681697
"str" @ 387..390: Class
16691698
"str" @ 407..410: Class
16701699
"func" @ 411..415: Variable

0 commit comments

Comments
 (0)