From eef403f6cf0f4ca54c53ab76f3bade7651d4f5e7 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 24 Dec 2025 17:27:21 +0100 Subject: [PATCH] Revert "[ty] Fix completion in decorator without class or function definition" (#22176) --- .../src/parser/statement.rs | 36 ++++----- ...yntax@decorator_missing_expression.py.snap | 39 +--------- ..._syntax@decorator_unexpected_token.py.snap | 77 +------------------ crates/ty_ide/src/completion.rs | 19 +---- crates/ty_wasm/src/lib.rs | 14 +--- playground/ty/src/Editor/Editor.tsx | 2 +- 6 files changed, 22 insertions(+), 165 deletions(-) diff --git a/crates/ruff_python_parser/src/parser/statement.rs b/crates/ruff_python_parser/src/parser/statement.rs index 98626d9f67..07e5816a9c 100644 --- a/crates/ruff_python_parser/src/parser/statement.rs +++ b/crates/ruff_python_parser/src/parser/statement.rs @@ -2914,27 +2914,21 @@ impl<'src> Parser<'src> { self.current_token_range(), ); - let range = self.node_range(start); - - ast::StmtFunctionDef { - node_index: Default::default(), - range, - is_async: false, - decorator_list: decorators, - name: ast::Identifier { - id: Name::empty(), - range: self.missing_node_range(), - node_index: AtomicNodeIndex::NONE, - }, - type_params: None, - parameters: Box::new(ast::Parameters { - range: self.missing_node_range(), - ..ast::Parameters::default() - }), - returns: None, - body: vec![], - } - .into() + // TODO(dhruvmanila): It seems that this recovery drops all the parsed + // decorators. Maybe we could convert them into statement expression + // with a flag indicating that this expression is part of a decorator. + // It's only possible to keep them if it's a function or class definition. + // We could possibly keep them if there's indentation error: + // + // ```python + // @decorator + // @decorator + // def foo(): ... + // ``` + // + // Or, parse it as a binary expression where the left side is missing. + // We would need to convert each decorator into a binary expression. + self.parse_statement() } } } diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_missing_expression.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_missing_expression.py.snap index bec68a40f3..dd7225493f 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_missing_expression.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_missing_expression.py.snap @@ -1,5 +1,6 @@ --- source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/err/decorator_missing_expression.py --- ## AST @@ -9,44 +10,6 @@ Module( node_index: NodeIndex(None), range: 0..51, body: [ - FunctionDef( - StmtFunctionDef { - node_index: NodeIndex(None), - range: 0..4, - is_async: false, - decorator_list: [ - Decorator { - range: 0..4, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 1..4, - id: Name("def"), - ctx: Load, - }, - ), - }, - ], - name: Identifier { - id: Name(""), - range: 4..4, - node_index: NodeIndex(None), - }, - type_params: None, - parameters: Parameters { - range: 4..4, - node_index: NodeIndex(None), - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: None, - body: [], - }, - ), AnnAssign( StmtAnnAssign { node_index: NodeIndex(None), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_unexpected_token.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_unexpected_token.py.snap index 83fd68468b..a2e7b51517 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_unexpected_token.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@decorator_unexpected_token.py.snap @@ -1,5 +1,6 @@ --- source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/err/decorator_unexpected_token.py --- ## AST @@ -9,44 +10,6 @@ Module( node_index: NodeIndex(None), range: 0..34, body: [ - FunctionDef( - StmtFunctionDef { - node_index: NodeIndex(None), - range: 0..4, - is_async: false, - decorator_list: [ - Decorator { - range: 0..4, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 1..4, - id: Name("foo"), - ctx: Load, - }, - ), - }, - ], - name: Identifier { - id: Name(""), - range: 4..4, - node_index: NodeIndex(None), - }, - type_params: None, - parameters: Parameters { - range: 4..4, - node_index: NodeIndex(None), - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: None, - body: [], - }, - ), With( StmtWith { node_index: NodeIndex(None), @@ -83,44 +46,6 @@ Module( ], }, ), - FunctionDef( - StmtFunctionDef { - node_index: NodeIndex(None), - range: 23..27, - is_async: false, - decorator_list: [ - Decorator { - range: 23..27, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 24..27, - id: Name("foo"), - ctx: Load, - }, - ), - }, - ], - name: Identifier { - id: Name(""), - range: 27..27, - node_index: NodeIndex(None), - }, - type_params: None, - parameters: Parameters { - range: 27..27, - node_index: NodeIndex(None), - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: None, - body: [], - }, - ), Assign( StmtAssign { node_index: NodeIndex(None), diff --git a/crates/ty_ide/src/completion.rs b/crates/ty_ide/src/completion.rs index 0a25cfb00e..d8dabbf413 100644 --- a/crates/ty_ide/src/completion.rs +++ b/crates/ty_ide/src/completion.rs @@ -48,7 +48,6 @@ pub fn completion<'db>( } ContextKind::NonImport(ref non_import) => { let model = SemanticModel::new(db, file); - dbg!(&non_import.target); let (semantic_completions, scoped) = match non_import.target { CompletionTargetAst::ObjectDot { expr } => { (model.attribute_completions(expr), None) @@ -521,7 +520,7 @@ impl<'m> Context<'m> { ContextKind::Import(import) } else { let target_token = CompletionTargetTokens::find(&cursor)?; - let target = dbg!(target_token.ast(&cursor)?); + let target = target_token.ast(&cursor)?; ContextKind::NonImport(ContextNonImport { target }) }; @@ -560,7 +559,6 @@ impl<'m> Context<'m> { /// The lifetime parameter `'m` refers to the shorter of the following /// lifetimes: the parsed module the cursor is in and the actual bytes /// making up the source file containing the cursor. - struct ContextCursor<'m> { /// The parsed module containing the cursor. parsed: &'m ParsedModuleRef, @@ -1463,7 +1461,7 @@ impl<'t> CompletionTargetTokens<'t> { } } CompletionTargetTokens::Generic { token } => { - let node = dbg!(cursor.covering_node(dbg!(token.range()))).node(); + let node = cursor.covering_node(token.range()).node(); Some(CompletionTargetAst::Scoped(ScopedTarget { node })) } CompletionTargetTokens::Unknown => { @@ -6688,19 +6686,6 @@ def func(): .not_contains("False"); } - #[test] - fn decorator_without_class_or_function() { - completion_test_builder( - "\ -from dataclasses import dataclass - -@dataclass(froz -", - ) - .build() - .contains("frozen"); - } - #[test] fn statement_keywords_in_if_body() { completion_test_builder( diff --git a/crates/ty_wasm/src/lib.rs b/crates/ty_wasm/src/lib.rs index f0ceacc7f1..addc3897de 100644 --- a/crates/ty_wasm/src/lib.rs +++ b/crates/ty_wasm/src/lib.rs @@ -442,18 +442,8 @@ impl Workspace { new_text: edit.content().map(ToString::to_string).unwrap_or_default(), } }); - - let name = comp.insert.as_deref().unwrap_or(&comp.name).to_string(); - let import_suffix = comp - .module_name - .and_then(|name| import_edit.is_some().then(|| format!(" (import {name})"))); - - let label = import_suffix - .map(|suffix| format!("{name}{suffix}")) - .unwrap_or_else(|| name); - Completion { - label, + name: comp.name.into(), kind, detail: type_display, module_name: comp.module_name.map(ToString::to_string), @@ -1080,7 +1070,7 @@ pub struct Hover { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Completion { #[wasm_bindgen(getter_with_clone)] - pub label: String, + pub name: String, pub kind: Option, #[wasm_bindgen(getter_with_clone)] pub insert_text: Option, diff --git a/playground/ty/src/Editor/Editor.tsx b/playground/ty/src/Editor/Editor.tsx index df58877ded..c104a93c63 100644 --- a/playground/ty/src/Editor/Editor.tsx +++ b/playground/ty/src/Editor/Editor.tsx @@ -336,7 +336,7 @@ class PlaygroundServer return { suggestions: completions.map((completion, i) => ({ label: { - label: completion.label, + label: completion.name, detail: completion.module_name == null ? undefined