Skip to content

Commit

Permalink
[refactor] Move function with UI strings into core/ui.py
Browse files Browse the repository at this point in the history
Also add some tests.
  • Loading branch information
Andy Chu committed Oct 4, 2021
1 parent c812033 commit 1ff3eab
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 24 deletions.
18 changes: 0 additions & 18 deletions core/alloc.py
Expand Up @@ -114,24 +114,6 @@ def GetLineSource(self, line_id):
# type: (int) -> source_t
return self.line_srcs[line_id]

def GetLineSourceString(self, line_id):
# type: (int) -> str
"""Returns a human-readable string for dev tools."""
src = self.line_srcs[line_id]
UP_src = src

# TODO: Make it look nicer, like core/ui.py.
tag = src.tag_()
if tag == source_e.CFlag:
return '-c flag'
if tag == source_e.MainFile:
src = cast(source__MainFile, UP_src)
return src.path
if tag == source_e.SourcedFile:
src = cast(source__SourcedFile, UP_src)
return src.path
return repr(src)

def AddLineSpan(self, line_id, col, length):
# type: (int, int, int) -> int
"""Save a line_span and return a new span ID for later retrieval."""
Expand Down
3 changes: 2 additions & 1 deletion core/dev.py
Expand Up @@ -15,6 +15,7 @@
from core import error
from core import optview
from core import state
from core import ui
from qsn_ import qsn
from core.pyerror import log
from osh import word_
Expand Down Expand Up @@ -104,7 +105,7 @@ def MaybeCollect(self, cmd_ev, err):

# Could also do msg % args separately, but JavaScript won't be able to
# render that.
self.error['source'] = cmd_ev.arena.GetLineSourceString(line_id)
self.error['source'] = ui.GetLineSourceString(cmd_ev.arena, line_id)
self.error['line_num'] = cmd_ev.arena.GetLineNumber(line_id)
self.error['line'] = cmd_ev.arena.GetLine(line_id)

Expand Down
6 changes: 3 additions & 3 deletions core/state.py
Expand Up @@ -1068,7 +1068,7 @@ def Dump(self):
if frame.call_spid != runtime.NO_SPID: # first frame has this issue
span = self.arena.GetLineSpan(frame.call_spid)
line_id = span.line_id
d['call_source'] = self.arena.GetLineSourceString(line_id)
d['call_source'] = ui.GetLineSourceString(self.arena, line_id)
d['call_line_num'] = self.arena.GetLineNumber(line_id)
d['call_line'] = self.arena.GetLine(line_id)

Expand Down Expand Up @@ -1136,7 +1136,7 @@ def PushCall(self, func_name, def_spid, argv):
self.var_stack.append({})

span = self.arena.GetLineSpan(def_spid)
source_str = self.arena.GetLineSourceString(span.line_id)
source_str = ui.GetLineSourceString(self.arena, span.line_id)

# bash uses this order: top of stack first.
self._PushDebugStack(source_str, func_name, None)
Expand Down Expand Up @@ -1698,7 +1698,7 @@ def GetValue(self, name, which_scopes=scope_e.Shopt):
strs.append('-') # Bash does this to line up with main?
continue
span = self.arena.GetLineSpan(frame.call_spid)
source_str = self.arena.GetLineSourceString(span.line_id)
source_str = ui.GetLineSourceString(self.arena, span.line_id)
strs.append(source_str)
return value.MaybeStrArray(strs) # TODO: Reuse this object too?

Expand Down
36 changes: 34 additions & 2 deletions core/ui.py
Expand Up @@ -94,6 +94,25 @@ def _PrintCodeExcerpt(line, col, length, f):
f.write('\n')


def GetLineSourceString(arena, line_id):
# type: (Arena, int) -> str
"""Returns a human-readable string for dev tools."""
src = arena.GetLineSource(line_id)
UP_src = src

# TODO: Make it look nicer, like core/ui.py.
tag = src.tag_()
if tag == source_e.CFlag:
return '-c flag'
if tag == source_e.MainFile:
src = cast(source__MainFile, UP_src)
return src.path
if tag == source_e.SourcedFile:
src = cast(source__SourcedFile, UP_src)
return src.path
return repr(src)


def _PrintWithSpanId(prefix, msg, span_id, arena, f):
# type: (str, str, int, Arena, Writer) -> None
line_span = arena.GetLineSpan(span_id)
Expand Down Expand Up @@ -136,7 +155,7 @@ def _PrintWithSpanId(prefix, msg, span_id, arena, f):
else:
span = arena.GetLineSpan(src.span_id)
line_num = arena.GetLineNumber(span.line_id)
outer_source = arena.GetLineSourceString(span.line_id)
outer_source = GetLineSourceString(arena, span.line_id)
source_str = '[ word at line %d of %s ]' % (line_num, outer_source)
# NOTE: not using _PrintCodeExcerpt

Expand All @@ -150,14 +169,27 @@ def _PrintWithSpanId(prefix, msg, span_id, arena, f):
elif case(source_e.Alias):
src = cast(source__Alias, UP_src)
source_str = '[ expansion of alias %r ]' % src.argv0

# TODO:
# - Consolidate Backticks and LValue into source.Reparsed(string comment)
# - ArgvWord should have string comment for 'eval', 'trap', etc.
# - This function should use arena.GetLineSourceString(), which is also
# used by core/state.py

# - should you have multiple line formats?
# - LValue calls _PrintCodeExcerpt
# - ArgvWord could do that
# - Variable could if we kept track of last assignment
# - Source too

elif case(source_e.Backticks):
#src = cast(source__Backticks, UP_src)
source_str = '[ backticks at ... ]'
elif case(source_e.LValue):
src = cast(source__LValue, UP_src)
span2 = arena.GetLineSpan(src.left_spid)
line2 = arena.GetLine(span2.line_id)
outer_source = arena.GetLineSourceString(span2.line_id)
outer_source = GetLineSourceString(arena, span2.line_id)
source_str = '[ array LValue in %s ]' % outer_source
# NOTE: The inner line number is always 1 because of reparsing. We
# overwrite it with the original span.
Expand Down
27 changes: 27 additions & 0 deletions test/parse-errors.sh
Expand Up @@ -970,6 +970,32 @@ oil_place_mutation() {
'
}

#
# Different source_t variants
#

nested_source_argvword() {
# source.ArgvWord
_runtime-parse-error '
code="printf % x"
eval $code
'
}

eval_parse_error() {
_runtime-parse-error '
x="echo )"
eval $x
'
}

trap_parse_error() {
_runtime-parse-error '
trap "echo )" EXIT
'
}
# Note: PROMPT_COMAND and PS1 are hard to trigger in this framework

cases-in-strings() {
set +o errexit

Expand Down Expand Up @@ -1020,6 +1046,7 @@ cases-in-strings() {
oil_var_decl
oil_place_mutation
parse_at
nested_source_argvword
}

# Cases in their own file
Expand Down

0 comments on commit 1ff3eab

Please sign in to comment.