Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/parser.py @ 28895:4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
They will be commonly used by revset and templater. It isn't easy to understand
how _expand() works, so I'll add comments by a follow-up patch.
The local variable 'alias' is renamed to 'a' to avoid shadowing the global
'alias' class.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Mon, 29 Feb 2016 22:15:44 +0900 |
parents | ee11167fe1da |
children | 4c76a032ec7e |
comparison
equal
deleted
inserted
replaced
28894:0f59674dc9ff | 28895:4bf9ed7a260e |
---|---|
470 aliases = {} | 470 aliases = {} |
471 for decl, defn in items: | 471 for decl, defn in items: |
472 a = cls.build(decl, defn) | 472 a = cls.build(decl, defn) |
473 aliases[a.name] = a | 473 aliases[a.name] = a |
474 return aliases | 474 return aliases |
475 | |
476 @classmethod | |
477 def _getalias(cls, aliases, tree): | |
478 """If tree looks like an unexpanded alias, return it. Return None | |
479 otherwise. | |
480 """ | |
481 if not isinstance(tree, tuple): | |
482 return None | |
483 if tree[0] == cls._symbolnode: | |
484 name = tree[1] | |
485 a = aliases.get(name) | |
486 if a and a.args is None and a.tree == tree: | |
487 return a | |
488 if tree[0] == cls._funcnode and tree[1][0] == cls._symbolnode: | |
489 name = tree[1][1] | |
490 a = aliases.get(name) | |
491 if a and a.args is not None and a.tree == tree[:2]: | |
492 return a | |
493 return None | |
494 | |
495 @classmethod | |
496 def _expandargs(cls, tree, args): | |
497 """Replace _aliasarg instances with the substitution value of the | |
498 same name in args, recursively. | |
499 """ | |
500 if not isinstance(tree, tuple): | |
501 return tree | |
502 if tree[0] == '_aliasarg': | |
503 sym = tree[1] | |
504 return args[sym] | |
505 return tuple(cls._expandargs(t, args) for t in tree) | |
506 | |
507 @classmethod | |
508 def _expand(cls, aliases, tree, expanding, cache): | |
509 if not isinstance(tree, tuple): | |
510 return tree | |
511 a = cls._getalias(aliases, tree) | |
512 if a is not None: | |
513 if a.error: | |
514 raise error.Abort(a.error) | |
515 if a in expanding: | |
516 raise error.ParseError(_('infinite expansion of %(section)s ' | |
517 '"%(name)s" detected') | |
518 % {'section': cls._section, | |
519 'name': a.name}) | |
520 expanding.append(a) | |
521 if a.name not in cache: | |
522 cache[a.name] = cls._expand(aliases, a.replacement, expanding, | |
523 cache) | |
524 result = cache[a.name] | |
525 expanding.pop() | |
526 if a.args is not None: | |
527 l = cls._getlist(tree[2]) | |
528 if len(l) != len(a.args): | |
529 raise error.ParseError(_('invalid number of arguments: %d') | |
530 % len(l)) | |
531 l = [cls._expand(aliases, t, [], cache) for t in l] | |
532 result = cls._expandargs(result, dict(zip(a.args, l))) | |
533 else: | |
534 result = tuple(cls._expand(aliases, t, expanding, cache) | |
535 for t in tree) | |
536 return result | |
537 | |
538 @classmethod | |
539 def expand(cls, aliases, tree): | |
540 """Expand aliases in tree, recursively. | |
541 | |
542 'aliases' is a dictionary mapping user defined aliases to alias objects. | |
543 """ | |
544 return cls._expand(aliases, tree, [], {}) |