Improve error message and span calculation.
Change-Id: I2c319e97329bd31eae875ab48eae0476bbf979e2
This commit is contained in:
parent
d543008431
commit
8313692991
|
@ -74,17 +74,21 @@ class JsonEmitter(Emitter):
|
|||
}
|
||||
|
||||
def emit_error(self, span, message):
|
||||
self.result["errors"].append({
|
||||
"line": span.get_lineno(),
|
||||
"col": 0,
|
||||
"byteRange": [span.lo, span.hi],
|
||||
"message": message
|
||||
})
|
||||
error = JsonEmitter._gen_message_structure(span, message)
|
||||
self.result["errors"].append(error)
|
||||
|
||||
def emit_warning(self, span, message):
|
||||
self.result["warnings"].append({
|
||||
"line": span.get_lineno(),
|
||||
"col": 0,
|
||||
warning = JsonEmitter._gen_message_structure(span, message)
|
||||
self.result["warnings"].append(warning)
|
||||
|
||||
@staticmethod
|
||||
def _gen_message_structure(span, message):
|
||||
spanrange = span.get_range()
|
||||
return {
|
||||
"startLineNumber": spanrange[0][0],
|
||||
"startColumn": spanrange[0][1],
|
||||
"endLineNumber": spanrange[1][0],
|
||||
"endColumn": spanrange[1][1],
|
||||
"byteRange": [span.lo, span.hi],
|
||||
"message": message
|
||||
})
|
||||
}
|
||||
|
|
|
@ -128,10 +128,25 @@ class BananaFile(object):
|
|||
|
||||
|
||||
def make_span(s, l, t):
|
||||
|
||||
def compute_hi(init_loc, tokens):
|
||||
hi = init_loc
|
||||
for tok in tokens:
|
||||
if isinstance(tok, ASTNode):
|
||||
hi = max(hi, tok.span.hi)
|
||||
elif isinstance(tok, basestring):
|
||||
hi += len(tok)
|
||||
elif isinstance(tok, p.ParseResults):
|
||||
hi = max(hi, compute_hi(init_loc, tok))
|
||||
else:
|
||||
raise exception.BananaGrammarBug(
|
||||
"Couldn't create span for: {}".format(tok)
|
||||
)
|
||||
return hi
|
||||
|
||||
if len(t) > 0:
|
||||
if isinstance(t[0], ASTNode):
|
||||
return Span(s, l, t[0].span.hi)
|
||||
return Span(s, l, len(t[0]) + l)
|
||||
span_hi = compute_hi(l, t)
|
||||
return Span(s, l, span_hi)
|
||||
else:
|
||||
return Span(s, l, 2)
|
||||
|
||||
|
@ -238,7 +253,7 @@ class DotPath(ASTNode):
|
|||
:return: Returns the next dot path.
|
||||
"""
|
||||
return DotPath(
|
||||
self.span.new_with_offset(len(self.varname.val)),
|
||||
self.span.new_with_lo(self.properties[0].span.lo),
|
||||
self.properties[0],
|
||||
self.properties[1:]
|
||||
)
|
||||
|
@ -415,6 +430,8 @@ class Connection(ASTNode):
|
|||
:type emitter: emit.Emitter
|
||||
:param emitter: Emitter.
|
||||
"""
|
||||
self.span.hi = max(other_con.span.hi, self.span.hi)
|
||||
self.span.lo = min(other_con.span.lo, self.span.lo)
|
||||
old_outputs = self.outputs
|
||||
self.outputs = other_con.outputs
|
||||
|
||||
|
|
|
@ -70,17 +70,17 @@ class Span(object):
|
|||
else:
|
||||
return '?SPAN?'
|
||||
|
||||
def new_with_offset(self, offset):
|
||||
def new_with_lo(self, lo_val):
|
||||
"""
|
||||
Construct a new Span with an offset applied
|
||||
to lo.
|
||||
Construct a new Span with an new value for
|
||||
lo.
|
||||
|
||||
:type offset: int
|
||||
:param offset: Offset to apply to lo.
|
||||
:type lo_val: int
|
||||
:param lo_val: New value for lo.
|
||||
:rtype: Span
|
||||
:return: Returns a new span
|
||||
"""
|
||||
return Span(self._text, self.lo + offset, self.hi)
|
||||
return Span(self._text, lo_val, self.hi)
|
||||
|
||||
def str_from_to(self, to_span):
|
||||
"""
|
||||
|
@ -107,6 +107,30 @@ class Span(object):
|
|||
else:
|
||||
return '?LINE?'
|
||||
|
||||
def get_range(self):
|
||||
"""
|
||||
Returns the start and end (line number, column number) of this span.
|
||||
"""
|
||||
if self._text is not None:
|
||||
splitted = self._text.splitlines()
|
||||
current_pos = 0
|
||||
startlineno = 0
|
||||
startcolno = 0
|
||||
endlineno = 0
|
||||
endcolno = 0
|
||||
for lineno in xrange(0, len(splitted)):
|
||||
line = splitted[lineno]
|
||||
if current_pos <= self.lo <= len(line) + current_pos:
|
||||
startlineno = lineno + 1
|
||||
startcolno = self.lo - current_pos + 1
|
||||
if current_pos <= self.hi <= len(line) + current_pos:
|
||||
endlineno = lineno + 1
|
||||
endcolno = self.hi - current_pos + 1
|
||||
current_pos += len(line) + 1
|
||||
return (startlineno, startcolno), (endlineno, endcolno)
|
||||
else:
|
||||
return (0, 0), (0, 0)
|
||||
|
||||
def get_lineno(self):
|
||||
"""
|
||||
Returns the line number of this span.
|
||||
|
|
|
@ -55,5 +55,6 @@ def typeck_connections(connection, type_table):
|
|||
possible_types = map(lambda x: x.__name__,
|
||||
valid_connections_types[type(type_from)])
|
||||
raise exception.BananaConnectionError(
|
||||
connection.span,
|
||||
ident_from, ident_to, type_from, possible_types
|
||||
)
|
||||
|
|
|
@ -77,11 +77,10 @@ class BananaArgumentTypeError(BananaException):
|
|||
def __init__(self, where, expected_type, received_type):
|
||||
if isinstance(where, ast.ASTNode):
|
||||
self._span = where.span
|
||||
where = where.span
|
||||
else:
|
||||
self._span = where
|
||||
self._value = "'{}': Wrong type of argument. Expected '{}' got '{}'"\
|
||||
.format(where.get_line(), expected_type, received_type)
|
||||
self._value = "Wrong type of argument. Expected '{}' got '{}'."\
|
||||
.format(expected_type, received_type)
|
||||
|
||||
def __str__(self):
|
||||
return self._value
|
||||
|
@ -93,7 +92,7 @@ class BananaArgumentTypeError(BananaException):
|
|||
class BananaComponentTooManyParams(BananaException):
|
||||
def __init__(self, span):
|
||||
self._span = span
|
||||
self._value = "Too many params provided to '{}' (line {})".format(
|
||||
self._value = "Too many params provided to '{}'.".format(
|
||||
span, span.get_lineno()
|
||||
)
|
||||
|
||||
|
@ -145,7 +144,7 @@ class BananaComponentAlreadyDefined(BananaException):
|
|||
def __init__(self, first_def, second_def):
|
||||
self._value = "Component already defined!\n" \
|
||||
" First definition: '{}'\n" \
|
||||
" Second definition: '{}'"\
|
||||
" Second definition: '{}'."\
|
||||
.format(first_def, second_def)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -171,7 +170,7 @@ class BananaShadowingComponentError(BananaException):
|
|||
|
||||
class BananaAssignmentError(BananaException):
|
||||
def __init__(self, lhs, rhs):
|
||||
self._value = "You can't assign '{}' to '{}'".format(lhs, rhs)
|
||||
self._value = "You can't assign '{}' to '{}'.".format(lhs, rhs)
|
||||
|
||||
def __str__(self):
|
||||
return self._value
|
||||
|
@ -196,7 +195,7 @@ class BananaGrammarBug(BananaException, p.ParseFatalException):
|
|||
class BananaJsonObjShadowingError(BananaException, p.ParseFatalException):
|
||||
def __init__(self, span, error):
|
||||
self._span = span
|
||||
error = "Can't shadow property already defined in {}".format(error)
|
||||
error = "Can't shadow property already defined in {}.".format(error)
|
||||
super(BananaJsonObjShadowingError, self).__init__(pstr=error)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -233,7 +232,7 @@ class BananaEvalBug(BananaException):
|
|||
class BananaUnknown(BananaException):
|
||||
def __init__(self, ident):
|
||||
self._span = ident.span
|
||||
self._value = "Unknown '{}'".format(
|
||||
self._value = "Unknown '{}'.".format(
|
||||
ident.into_unmodified_str()
|
||||
)
|
||||
|
||||
|
@ -247,7 +246,7 @@ class BananaUnknown(BananaException):
|
|||
class BananaUnknownOperator(BananaException):
|
||||
def __init__(self, span, operator, for_type):
|
||||
self._span = span
|
||||
self._value = "Unknown operator '{}' for type '{}'".format(
|
||||
self._value = "Unknown operator '{}' for type '{}'.".format(
|
||||
operator,
|
||||
for_type
|
||||
)
|
||||
|
@ -263,17 +262,15 @@ class BananaPropertyDoesNotExists(BananaException):
|
|||
def __init__(self, dotpath, on_type=None):
|
||||
self._span = dotpath.span
|
||||
if on_type is None:
|
||||
self._value = "Error at '{}': Property '{}' " \
|
||||
"does not exists"\
|
||||
self._value = "Property '{}' " \
|
||||
"does not exists."\
|
||||
.format(
|
||||
dotpath.span.get_line(),
|
||||
dotpath.into_unmodified_str()
|
||||
)
|
||||
else:
|
||||
self._value = "Error at '{}': Property '{}' " \
|
||||
"does not exists on type '{}'"\
|
||||
self._value = "Property '{}' " \
|
||||
"does not exists on type '{}'."\
|
||||
.format(
|
||||
dotpath.span.get_line(),
|
||||
dotpath.into_unmodified_str(),
|
||||
str(on_type)
|
||||
)
|
||||
|
@ -296,21 +293,21 @@ class BananaTypeError(BananaException):
|
|||
if found_type is None:
|
||||
if isinstance(expected_type, list):
|
||||
self._value = "Type error found. Expected" \
|
||||
" one among '{}'"\
|
||||
" one among '{}'."\
|
||||
.format(', '.join(map(lambda x: str(x), expected_type)))
|
||||
else:
|
||||
self._value = "Type error found. Expected '{}'".format(
|
||||
self._value = "Type error found. Expected '{}'.".format(
|
||||
str(expected_type)
|
||||
)
|
||||
else:
|
||||
if isinstance(expected_type, list):
|
||||
self._value = "Type error found. Expected" \
|
||||
" one among '{}', found '{}'"\
|
||||
" one among '{}', found '{}'."\
|
||||
.format(', '.join(map(lambda x: str(x), expected_type)),
|
||||
str(found_type))
|
||||
else:
|
||||
self._value = "Type error found. Expected" \
|
||||
" '{}', found '{}'"\
|
||||
" '{}', found '{}'."\
|
||||
.format(str(expected_type), str(found_type))
|
||||
|
||||
def __str__(self):
|
||||
|
@ -327,7 +324,7 @@ class BananaAssignCompError(BananaException):
|
|||
self._span = span
|
||||
self._value = "Component objects " \
|
||||
"can't be assigned to " \
|
||||
"properties of other objects"
|
||||
"properties of other objects."
|
||||
|
||||
def __str__(self):
|
||||
return self._value
|
||||
|
@ -338,15 +335,16 @@ class BananaAssignCompError(BananaException):
|
|||
|
||||
class BananaConnectionError(BananaException):
|
||||
|
||||
def __init__(self, ident_from, ident_to, type_from, possible_connections):
|
||||
self._span = ident_to.span
|
||||
self._value = "Can't connect '{}' (line:{})" \
|
||||
" to '{}' (line:{})," \
|
||||
" '{}' can only be connected to {}"\
|
||||
def __init__(self, span, ident_from, ident_to, type_from,
|
||||
possible_connections):
|
||||
self._value = "Can't connect '{}'" \
|
||||
" to '{}'," \
|
||||
" '{}' can only be connected to a {}."\
|
||||
.format(
|
||||
ident_from.val, ident_from.span.get_lineno(),
|
||||
ident_to.val, ident_to.span.get_lineno(),
|
||||
type_from, possible_connections)
|
||||
ident_from.val,
|
||||
ident_to.val,
|
||||
type_from.class_name, ' or a '.join(possible_connections))
|
||||
self._span = span
|
||||
|
||||
def __str__(self):
|
||||
return self._value
|
||||
|
|
Loading…
Reference in New Issue