mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
[ty] Implement global
handling and load-before-global-declaration
syntax error (#17637)
Summary -- This PR resolves both the typing-related and syntax error TODOs added in #17563 by tracking a set of `global` bindings for each scope. As discussed below, we avoid the additional AST traversal from ruff by collecting `Name`s from `global` statements while building the semantic index and emit a syntax error if the `Name` is already bound in the current scope at the point of the `global` statement. This has the downside of separating the error from the `SemanticSyntaxChecker`, but I plan to explore using this approach in the `SemanticSyntaxChecker` itself as a follow-up. It seems like this may be a better approach for ruff as well. Test Plan -- Updated all of the related mdtests to remove the TODOs (and add quotes I forgot on the messages). There is one remaining TODO, but it requires `nonlocal` support, which isn't even incorporated into the `SemanticSyntaxChecker` yet. --------- Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
parent
67cd94ed64
commit
57bf7dfbd9
5 changed files with 174 additions and 48 deletions
|
@ -176,6 +176,9 @@ pub(crate) struct SemanticIndex<'db> {
|
|||
/// Map from the file-local [`FileScopeId`] to the salsa-ingredient [`ScopeId`].
|
||||
scope_ids_by_scope: IndexVec<FileScopeId, ScopeId<'db>>,
|
||||
|
||||
/// Map from the file-local [`FileScopeId`] to the set of explicit-global symbols it contains.
|
||||
globals_by_scope: FxHashMap<FileScopeId, FxHashSet<ScopedSymbolId>>,
|
||||
|
||||
/// Use-def map for each scope in this file.
|
||||
use_def_maps: IndexVec<FileScopeId, Arc<UseDefMap<'db>>>,
|
||||
|
||||
|
@ -255,6 +258,16 @@ impl<'db> SemanticIndex<'db> {
|
|||
self.scope_ids_by_scope.iter().copied()
|
||||
}
|
||||
|
||||
pub(crate) fn symbol_is_global_in_scope(
|
||||
&self,
|
||||
symbol: ScopedSymbolId,
|
||||
scope: FileScopeId,
|
||||
) -> bool {
|
||||
self.globals_by_scope
|
||||
.get(&scope)
|
||||
.is_some_and(|globals| globals.contains(&symbol))
|
||||
}
|
||||
|
||||
/// Returns the id of the parent scope.
|
||||
pub(crate) fn parent_scope_id(&self, scope_id: FileScopeId) -> Option<FileScopeId> {
|
||||
let scope = self.scope(scope_id);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue