Skip to content

Commit ccbcb3b

Browse files
author
whitequark
committedMay 8, 2015
Extend grammar coverage, adding branch coverage.
1 parent 18a5e59 commit ccbcb3b

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed
 

Diff for: ‎pyparser/coverage/__init__.py

+36-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ def instrument():
1515
rewriter = source.Rewriter(_buf)
1616
lex = lexer.Lexer(_buf, (3, 4))
1717
in_grammar = False
18-
stack = []
18+
paren_stack = []
19+
stmt_stack = [None]
20+
all_stmt_list = []
21+
in_square = 0
1922
for token in lex:
2023
if token.kind == 'from':
2124
token = lex.next()
@@ -45,19 +48,37 @@ def instrument():
4548
rewriter.insert_before(rparen.loc,
4649
"loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))
4750
else:
48-
stack.append(", loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))
51+
paren_stack.append(", loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))
4952

5053
if token.kind == '(':
51-
stack.append(None)
54+
paren_stack.append(None)
5255

5356
if token.kind == ')':
54-
data = stack.pop()
57+
data = paren_stack.pop()
5558
if data is not None:
5659
rewriter.insert_before(token.loc, data)
5760

61+
if token.kind == '[':
62+
in_square += 1
63+
elif token.kind == ']':
64+
in_square -= 1
65+
66+
if token.kind in ('def', 'if', 'elif', 'else', 'for') and in_square == 0:
67+
all_stmt_list.append((token.loc.begin_pos, token.loc.end_pos))
68+
stmt_stack.append("_all_stmts[(%d,%d)] = True\n" %
69+
(token.loc.begin_pos, token.loc.end_pos))
70+
elif token.kind == 'lambda':
71+
stmt_stack.append(None)
72+
73+
if token.kind == 'indent':
74+
data = stmt_stack.pop()
75+
if data is not None:
76+
rewriter.insert_after(token.loc, data + " " * token.loc.column())
77+
5878
with codecs.open(os.path.join(os.path.dirname(__file__), 'parser.py'), 'w',
5979
encoding='utf-8') as f:
6080
f.write(rewriter.rewrite().source)
81+
f.write("\n_all_stmts = {%s}\n" % ', '.join(["(%d,%d): False" % x for x in all_stmt_list]))
6182

6283
# Produce an HTML report for test coverage of parser rules.
6384
def report(parser, name='parser'):
@@ -84,6 +105,17 @@ def report(parser, name='parser'):
84105
total_pts += pts
85106
total_covered += covered
86107

108+
for stmt in parser._all_stmts:
109+
loc = source.Range(_buf, *stmt)
110+
if parser._all_stmts[stmt]:
111+
rewriter.insert_before(loc, r"<span class='covered'>")
112+
else:
113+
rewriter.insert_before(loc, r"<span class='uncovered'>")
114+
rewriter.insert_after(loc, r"</span>")
115+
116+
total_pts += 1
117+
total_covered += (1 if parser._all_stmts[stmt] else 0)
118+
87119
print("GRAMMAR COVERAGE: %.2f%%" % (total_covered / total_pts * 100))
88120

89121
content = rewriter.rewrite().source

Diff for: ‎pyparser/parser.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -436,14 +436,18 @@ def add_flags(self, flags):
436436
SeqN(0, Rule('compound_stmt'), Newline()))))
437437
def single_input(self, body):
438438
"""single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE"""
439-
loc = None if body == [] else body[0].loc
439+
loc = None
440+
if body != []:
441+
loc = body[0].loc
440442
return ast.Interactive(body=body, loc=loc)
441443

442444
@action(Expect(SeqN(0, Star(Alt(Newline(), Rule('stmt'))), Tok('eof'))))
443445
def file_input(parser, body):
444446
"""file_input: (NEWLINE | stmt)* ENDMARKER"""
445447
body = reduce(list.__add__, body, [])
446-
loc = None if body == [] else body[0].loc
448+
loc = None
449+
if body != []:
450+
loc = body[0].loc
447451
return ast.Module(body=body, loc=loc)
448452

449453
@action(Expect(SeqN(0, Rule('testlist'), Star(Tok('newline')), Tok('eof'))))
@@ -623,15 +627,17 @@ def expr_stmt(self, lhs, rhs):
623627

624628
@action(List(Rule('test'), ',', trailing=True))
625629
def print_stmt_1(self, values):
626-
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
627-
nl = False if values.trailing_comma else True
630+
nl, loc = True, values[-1].loc
631+
if values.trailing_comma:
632+
nl, loc = False, values.trailing_comma.loc
628633
return ast.Print(dest=None, values=values, nl=nl,
629634
dest_loc=None, loc=loc)
630635

631636
@action(Seq(Loc('>>'), Rule('test'), Tok(','), List(Rule('test'), ',', trailing=True)))
632637
def print_stmt_2(self, dest_loc, dest, comma_tok, values):
633-
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
634-
nl = False if values.trailing_comma else True
638+
nl, loc = True, values[-1].loc
639+
if values.trailing_comma:
640+
nl, loc = False, values.trailing_comma.loc
635641
return ast.Print(dest=dest, values=values, nl=nl,
636642
dest_loc=dest_loc, loc=loc)
637643

0 commit comments

Comments
 (0)
Please sign in to comment.