mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-18 17:40:37 +00:00
Add support for global and nonlocal symbol renames (#5134)
## Summary In #5074, we introduced an abstraction to support local symbol renames ("local" here refers to "within a module"). However, that abstraction didn't support `global` and `nonlocal` symbols. This PR extends it to those cases. Broadly, there are considerations. First, if we're renaming a symbol in a scope in which it is declared `global` or `nonlocal`. For example, given: ```python x = 1 def foo(): global x ``` Then when renaming `x` in `foo`, we need to detect that it's `global` and instead perform the rename starting from the module scope. Second, when renaming a symbol, we need to determine the scopes in which it is declared `global` or `nonlocal`. This is effectively the inverse of the above: when renaming `x` in the module scope, we need to detect that we should _also_ rename `x` in `foo`. To support these cases, the renaming algorithm was adjusted as follows: - When we start a rename in a scope, determine whether the symbol is declared `global` or `nonlocal` by looking for a `global` or `nonlocal` binding. If it is, start the rename in the defining scope. (This requires storing the defining scope on the `nonlocal` binding, which is new.) - We then perform the rename in the defining scope. - We then check whether the symbol was declared as `global` or `nonlocal` in any scopes, and perform the rename in those scopes too. (Thankfully, this doesn't need to be done recursively.) Closes #5092. ## Test Plan Added some additional snapshot tests.
This commit is contained in:
parent
b9754bd5c5
commit
fd1dfc3bfa
7 changed files with 305 additions and 81 deletions
|
@ -10,6 +10,7 @@ use crate::context::ExecutionContext;
|
|||
use crate::model::SemanticModel;
|
||||
use crate::node::NodeId;
|
||||
use crate::reference::ReferenceId;
|
||||
use crate::ScopeId;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Binding<'a> {
|
||||
|
@ -336,7 +337,7 @@ pub enum BindingKind<'a> {
|
|||
/// def foo():
|
||||
/// nonlocal x
|
||||
/// ```
|
||||
Nonlocal,
|
||||
Nonlocal(ScopeId),
|
||||
|
||||
/// A binding for a builtin, like `print` or `bool`.
|
||||
Builtin,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue