|
83 | 83 | from mcpyrate.core import Done
|
84 | 84 | from mcpyrate.walkers import ASTTransformer, ASTVisitor
|
85 | 85 |
|
86 |
| -from .astcompat import TryStar |
| 86 | +from .astcompat import TryStar, MatchStar, MatchMapping, MatchClass, MatchAs |
87 | 87 |
|
88 | 88 | from ..it import uniqify
|
89 | 89 |
|
@@ -313,6 +313,12 @@ def get_names_in_store_context(tree):
|
313 | 313 | by ``get_lexical_variables`` for the nearest lexically surrounding parent
|
314 | 314 | tree that represents a scope.
|
315 | 315 | """
|
| 316 | + class MatchCapturesCollector(ASTVisitor): # Python 3.10+: `match`/`case` |
| 317 | + def examine(self, tree): |
| 318 | + if type(tree) is Name: |
| 319 | + self.collect(tree.id) |
| 320 | + self.generic_visit(tree) |
| 321 | + |
316 | 322 | class StoreNamesCollector(ASTVisitor):
|
317 | 323 | # def _collect_name_or_list(self, t):
|
318 | 324 | # if type(t) is Name:
|
@@ -346,6 +352,29 @@ def examine(self, tree):
|
346 | 352 | # TODO: `try`, even inside the `except` blocks, will be bound in the whole parent scope.
|
347 | 353 | for h in tree.handlers:
|
348 | 354 | self.collect(h.name)
|
| 355 | + # Python 3.10+: `match`/`case` uses names in `Load` context to denote captures. |
| 356 | + # Also there are some bare strings, and sometimes `None` actually means "_" (but doesn't capture). |
| 357 | + # So we special-case all of this. |
| 358 | + elif type(tree) in (MatchAs, MatchStar): # a `MatchSequence` also consists of these |
| 359 | + if tree.name is not None: |
| 360 | + self.collect(tree.name) |
| 361 | + elif type(tree) is MatchMapping: |
| 362 | + mcc = MatchCapturesCollector(tree.patterns) |
| 363 | + mcc.visit() |
| 364 | + for name in mcc.collected: |
| 365 | + self.collect(name) |
| 366 | + if tree.rest is not None: # `rest` is a capture if present |
| 367 | + self.collect(tree.rest) |
| 368 | + elif type(tree) is MatchClass: |
| 369 | + mcc = MatchCapturesCollector(tree.patterns) |
| 370 | + mcc.visit() |
| 371 | + for name in mcc.collected: |
| 372 | + self.collect(name) |
| 373 | + mcc = MatchCapturesCollector(tree.kwd_patterns) |
| 374 | + mcc.visit() |
| 375 | + for name in mcc.collected: |
| 376 | + self.collect(name) |
| 377 | + |
349 | 378 | # Python 3.12+: `TypeAlias` uses a name in `Store` context on its LHS so it needs no special handling here.
|
350 | 379 |
|
351 | 380 | # Same note as for for loops.
|
|
0 commit comments