Skip to content

Conversation

@ntBre
Copy link
Contributor

@ntBre ntBre commented Apr 9, 2025

Summary

Based on the discussion in #17298 (comment), we decided to move the scope handling out of the SemanticSyntaxChecker and into the SemanticSyntaxContext trait. This PR implements that refactor by:

  • Reverting all of the Checkpoint and in_async_context code in the SemanticSyntaxChecker
  • Adding four new methods to the SemanticSyntaxContext trait
    • in_async_context: matches SemanticModel::in_async_context and only detects the nearest enclosing function
    • in_sync_comprehension: uses the new is_async tracking on Generator scopes to detect any enclosing sync comprehension
    • in_module_scope: reports whether we're at the top-level scope
    • in_notebook: reports whether we're in a Jupyter notebook
  • In-lining the TestContext directly into the SemanticSyntaxCheckerVisitor
    • This allows modifying the context as the visitor traverses the AST, which wasn't possible before

One potential question here is "why not add a single method returning a Scope or Scopes to the context?" The main reason is that the Scope type is defined in the ruff_python_semantic crate, which is not currently a dependency of the parser. It also doesn't appear to be used in red-knot. So it seemed best to use these more granular methods instead of trying to access Scope in ruff_python_parser (and red-knot).

Test Plan

Existing parser and linter tests.

@ntBre ntBre added the internal An internal refactor or improvement label Apr 9, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Apr 9, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@ntBre ntBre marked this pull request as ready for review April 9, 2025 14:25
Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only skimmed through the changes. I like it, it simplifies the visitor a good deal and I think we have all the necessary information in red knot too


#[derive(Default)]
pub struct SemanticSyntaxCheckerVisitor<Ctx> {
pub struct SemanticSyntaxCheckerVisitor<'a> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a docblock stating that this visitor is only for testing?

Or should we move it to the tests module, considering that it isn't used anywhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think moving it to the tests module makes sense. I can't remember why we separated it from the context and kept it here originally, but we haven't used it anywhere else yet.

I guess this wasn't affecting any test results, but `visit_expr` was missing
early returns after the `Lambda` and `Comp` visits, so it would have been
traversing these nodes twice. I moved the default `walk_expr` call into the
final arm of the match to avoid needing early returns in each other branch.
@ntBre ntBre merged commit 144484d into main Apr 9, 2025
22 checks passed
@ntBre ntBre deleted the brent/syn-scope-context branch April 9, 2025 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal An internal refactor or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants