[ty] Visit class arguments in source order for semantic tokens (#22063)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
RasmusNygren 2025-12-19 14:19:49 +01:00 committed by GitHub
parent e177cc2a5a
commit 58d25129aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 20 additions and 12 deletions

View File

@ -37,13 +37,12 @@ use bitflags::bitflags;
use itertools::Itertools; use itertools::Itertools;
use ruff_db::files::File; use ruff_db::files::File;
use ruff_db::parsed::parsed_module; use ruff_db::parsed::parsed_module;
use ruff_python_ast as ast;
use ruff_python_ast::visitor::source_order::{ use ruff_python_ast::visitor::source_order::{
SourceOrderVisitor, TraversalSignal, walk_expr, walk_stmt, SourceOrderVisitor, TraversalSignal, walk_arguments, walk_expr, walk_stmt,
}; };
use ruff_python_ast::{ use ruff_python_ast::{
AnyNodeRef, BytesLiteral, Expr, FString, InterpolatedStringElement, Stmt, StringLiteral, self as ast, AnyNodeRef, BytesLiteral, Expr, FString, InterpolatedStringElement, Stmt,
TypeParam, StringLiteral, TypeParam,
}; };
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use std::ops::Deref; use std::ops::Deref;
@ -668,14 +667,7 @@ impl SourceOrderVisitor<'_> for SemanticTokenVisitor<'_> {
// Handle base classes and type annotations in inheritance // Handle base classes and type annotations in inheritance
if let Some(arguments) = &class.arguments { if let Some(arguments) = &class.arguments {
// Visit base class arguments walk_arguments(self, arguments);
for arg in &arguments.args {
self.visit_expr(arg);
}
// Visit keyword arguments (for metaclass, etc.)
for keyword in &arguments.keywords {
self.visit_expr(&keyword.value);
}
} }
let prev_in_class = self.in_class_scope; let prev_in_class = self.in_class_scope;
@ -1138,6 +1130,22 @@ mod tests {
"###); "###);
} }
#[test]
fn test_semantic_tokens_class_args() {
// This used to cause a panic because of an incorrect
// insertion-order when visiting arguments inside
// class definitions.
let test = SemanticTokenTest::new("class Foo(m=x, m)");
let tokens = test.highlight_file();
assert_snapshot!(test.to_snapshot(&tokens), @r###"
"Foo" @ 6..9: Class [definition]
"x" @ 12..13: Variable
"m" @ 15..16: Variable
"###);
}
#[test] #[test]
fn test_semantic_tokens_variables() { fn test_semantic_tokens_variables() {
let test = SemanticTokenTest::new( let test = SemanticTokenTest::new(