mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 15:27:13 +03:00
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.
This commit is contained in:
parent
5da75dff02
commit
45e9c21bc0
@ -472,3 +472,73 @@ class basealiasrules(object):
|
||||
a = cls.build(decl, defn)
|
||||
aliases[a.name] = a
|
||||
return aliases
|
||||
|
||||
@classmethod
|
||||
def _getalias(cls, aliases, tree):
|
||||
"""If tree looks like an unexpanded alias, return it. Return None
|
||||
otherwise.
|
||||
"""
|
||||
if not isinstance(tree, tuple):
|
||||
return None
|
||||
if tree[0] == cls._symbolnode:
|
||||
name = tree[1]
|
||||
a = aliases.get(name)
|
||||
if a and a.args is None and a.tree == tree:
|
||||
return a
|
||||
if tree[0] == cls._funcnode and tree[1][0] == cls._symbolnode:
|
||||
name = tree[1][1]
|
||||
a = aliases.get(name)
|
||||
if a and a.args is not None and a.tree == tree[:2]:
|
||||
return a
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _expandargs(cls, tree, args):
|
||||
"""Replace _aliasarg instances with the substitution value of the
|
||||
same name in args, recursively.
|
||||
"""
|
||||
if not isinstance(tree, tuple):
|
||||
return tree
|
||||
if tree[0] == '_aliasarg':
|
||||
sym = tree[1]
|
||||
return args[sym]
|
||||
return tuple(cls._expandargs(t, args) for t in tree)
|
||||
|
||||
@classmethod
|
||||
def _expand(cls, aliases, tree, expanding, cache):
|
||||
if not isinstance(tree, tuple):
|
||||
return tree
|
||||
a = cls._getalias(aliases, tree)
|
||||
if a is not None:
|
||||
if a.error:
|
||||
raise error.Abort(a.error)
|
||||
if a in expanding:
|
||||
raise error.ParseError(_('infinite expansion of %(section)s '
|
||||
'"%(name)s" detected')
|
||||
% {'section': cls._section,
|
||||
'name': a.name})
|
||||
expanding.append(a)
|
||||
if a.name not in cache:
|
||||
cache[a.name] = cls._expand(aliases, a.replacement, expanding,
|
||||
cache)
|
||||
result = cache[a.name]
|
||||
expanding.pop()
|
||||
if a.args is not None:
|
||||
l = cls._getlist(tree[2])
|
||||
if len(l) != len(a.args):
|
||||
raise error.ParseError(_('invalid number of arguments: %d')
|
||||
% len(l))
|
||||
l = [cls._expand(aliases, t, [], cache) for t in l]
|
||||
result = cls._expandargs(result, dict(zip(a.args, l)))
|
||||
else:
|
||||
result = tuple(cls._expand(aliases, t, expanding, cache)
|
||||
for t in tree)
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def expand(cls, aliases, tree):
|
||||
"""Expand aliases in tree, recursively.
|
||||
|
||||
'aliases' is a dictionary mapping user defined aliases to alias objects.
|
||||
"""
|
||||
return cls._expand(aliases, tree, [], {})
|
||||
|
@ -2256,72 +2256,9 @@ class _aliasrules(parser.basealiasrules):
|
||||
_parse = staticmethod(_parsealias)
|
||||
_getlist = staticmethod(getlist)
|
||||
|
||||
def _getalias(aliases, tree):
|
||||
"""If tree looks like an unexpanded alias, return it. Return None
|
||||
otherwise.
|
||||
"""
|
||||
if not isinstance(tree, tuple):
|
||||
return None
|
||||
if tree[0] == 'symbol':
|
||||
name = tree[1]
|
||||
alias = aliases.get(name)
|
||||
if alias and alias.args is None and alias.tree == tree:
|
||||
return alias
|
||||
if tree[0] == 'func' and tree[1][0] == 'symbol':
|
||||
name = tree[1][1]
|
||||
alias = aliases.get(name)
|
||||
if alias and alias.args is not None and alias.tree == tree[:2]:
|
||||
return alias
|
||||
return None
|
||||
|
||||
def _expandargs(tree, args):
|
||||
"""Replace _aliasarg instances with the substitution value of the
|
||||
same name in args, recursively.
|
||||
"""
|
||||
if not isinstance(tree, tuple):
|
||||
return tree
|
||||
if tree[0] == '_aliasarg':
|
||||
sym = tree[1]
|
||||
return args[sym]
|
||||
return tuple(_expandargs(t, args) for t in tree)
|
||||
|
||||
def _expandaliases(aliases, tree, expanding, cache):
|
||||
"""Expand aliases in tree, recursively.
|
||||
|
||||
'aliases' is a dictionary mapping user defined aliases to
|
||||
alias objects.
|
||||
"""
|
||||
if not isinstance(tree, tuple):
|
||||
# Do not expand raw strings
|
||||
return tree
|
||||
alias = _getalias(aliases, tree)
|
||||
if alias is not None:
|
||||
if alias.error:
|
||||
raise error.Abort(alias.error)
|
||||
if alias in expanding:
|
||||
raise error.ParseError(_('infinite expansion of revset alias "%s" '
|
||||
'detected') % alias.name)
|
||||
expanding.append(alias)
|
||||
if alias.name not in cache:
|
||||
cache[alias.name] = _expandaliases(aliases, alias.replacement,
|
||||
expanding, cache)
|
||||
result = cache[alias.name]
|
||||
expanding.pop()
|
||||
if alias.args is not None:
|
||||
l = getlist(tree[2])
|
||||
if len(l) != len(alias.args):
|
||||
raise error.ParseError(
|
||||
_('invalid number of arguments: %d') % len(l))
|
||||
l = [_expandaliases(aliases, a, [], cache) for a in l]
|
||||
result = _expandargs(result, dict(zip(alias.args, l)))
|
||||
else:
|
||||
result = tuple(_expandaliases(aliases, t, expanding, cache)
|
||||
for t in tree)
|
||||
return result
|
||||
|
||||
def findaliases(ui, tree, showwarning=None):
|
||||
aliases = _aliasrules.buildmap(ui.configitems('revsetalias'))
|
||||
tree = _expandaliases(aliases, tree, [], {})
|
||||
tree = _aliasrules.expand(aliases, tree)
|
||||
if showwarning:
|
||||
# warn about problematic (but not referred) aliases
|
||||
for name, alias in sorted(aliases.iteritems()):
|
||||
|
Loading…
Reference in New Issue
Block a user