/
check_same_test.py
executable file
·84 lines (61 loc) · 2.12 KB
/
check_same_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#! /usr/bin/env python
"""
This script will detect syntactically identical expressions which are chained
together in a chain of logical operators in the input Ada sources.
"""
import argparse
import libadalang as lal
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('files', help='The files to analyze',
type=str, nargs='+', metavar='F')
def location(node):
return (node.token_start._sloc_range.start.line,
node.token_start._sloc_range.start.column)
def list_tests(ifnode):
"""
List all the tests of `ifnode`.
:type ifnode: lal.IfStmt|lal.IfExpr
"""
return [ifnode.f_cond_expr] + [
f.f_cond_expr for f in ifnode.f_alternatives
]
def tokens_text(node):
return tuple((t.kind, t.text) for t in node.tokens)
def one_liner(node):
return ''.join(map(lambda t: t.text, node.tokens))
def has_same_tests(expr):
"""
For an if-statement or an if-expression, checks whether any combination of
its tests are syntactically equivalent. If duplicate operands are found,
return them.
:rtype: lal.Expr|None
"""
tests = {}
all_tests = list_tests(expr)
if len(all_tests) > 1:
for test in all_tests:
tokens = tokens_text(test)
if tokens in tests:
return (tests[tokens], test)
tests[tokens] = test
def do_file(f):
c = lal.AnalysisContext()
unit = c.get_from_file(f)
if unit.root is None:
print 'Could not parse {}:'.format(f)
for diag in unit.diagnostics:
print ' {}'.format(diag)
return
for ifnode in unit.root.findall(lambda e: isinstance(e, (lal.IfStmt, lal.IfExpr))):
res = has_same_tests(ifnode)
if res is not None:
(fst_test, snd_test) = res
(fst_line,fst_col) = location(fst_test)
(snd_line,snd_col) = location(snd_test)
print ('{}:{}:{}: duplicate test with line {}').format(
f, snd_line, snd_col, fst_line)
def main(args):
for f in args.files:
do_file(f)
if __name__ == '__main__':
main(parser.parse_args())