feat(tools/parser): parse uplevel bodies for formatting and linting
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import io
|
||||
import re
|
||||
from typing import Optional, Tuple
|
||||
from tclint.parser import Parser
|
||||
from tclint.commands import CommandArgError
|
||||
from tclint.commands.checks import eval as eval_script_args
|
||||
from tclint.syntax_tree import (
|
||||
BracedWord,
|
||||
BareWord,
|
||||
@@ -13,9 +15,32 @@ from tclint.syntax_tree import (
|
||||
from tclint.lexer import TclSyntaxError, Lexer, TOK_EOF
|
||||
|
||||
|
||||
_UPLEVEL_LEVEL_RE = re.compile(r"^#?\d+$")
|
||||
|
||||
|
||||
def _uplevel(args, parser):
|
||||
"""uplevel ?level? arg ?arg ...?"""
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/uplevel.html
|
||||
if len(args) == 0:
|
||||
raise CommandArgError("not enough args to 'uplevel': got 0, expected at least 1")
|
||||
|
||||
# The level can only be omitted when the first arg doesn't look like one.
|
||||
# A non-literal first arg (e.g. $level) is treated as a level as well.
|
||||
level = []
|
||||
if len(args) > 1:
|
||||
first = args[0].contents
|
||||
if first is None or _UPLEVEL_LEVEL_RE.match(first):
|
||||
level = args[0:1]
|
||||
|
||||
return level + eval_script_args(args[len(level) :], parser, "uplevel")
|
||||
|
||||
|
||||
class CustomParser(Parser):
|
||||
def __init__(self, debug=False, command_plugins=None):
|
||||
super().__init__(debug, command_plugins)
|
||||
# tclint only checks the arg count of uplevel; parse its body as a script
|
||||
# so it gets formatted and linted like eval/namespace eval bodies.
|
||||
self._commands = {**self._commands, "uplevel": _uplevel}
|
||||
# Used to normalize newlines consistently with open()'s universal newlines mode.
|
||||
self._decoder = io.IncrementalNewlineDecoder(None, True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user