/
parameter_values.upy
129 lines (115 loc) · 3.39 KB
/
parameter_values.upy
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Interactive Report for showing the values for the given parameter passed
# in at each call reference
import understand
def name():
"""
Required, the name of the ireport.
"""
return "Parameter Values"
def test_entity(ent):
"""
Optional method, return true if report is valid for the entity
"""
# Valid for parameters whose parent exists and has callby references
return ent.kind().check("c parameter") and ent.parent() and len(ent.parent().refs("callby")) > 0
# Report generation
def generate(report, ent):
"""
Required, generate the report
"""
report.print("Values for ")
report.entity(ent)
report.print(ent.name())
report.entity()
if ent.value():
report.print(" (")
report.bold()
report.print("Default Value: ")
report.nobold()
report.print(ent.value() + ")")
report.print(":\n")
params = ent.parent().parameters().split(",");
idx = -1
for i in range(len(params)):
if params[i].endswith(ent.name()):
idx = i
break
if idx == -1:
report.print("Error: Unable to determine parameter position\n")
return
values = {}
lexercache = {} # cache lexers for speed
for ref in ent.parent().refs("callby"):
values.setdefault(paramValue(ref, idx, lexercache), []).append(ref)
for val in values.keys():
report.tree(1, True)
if val is None:
report.italic()
report.print("No Value")
report.noitalic()
elif isinstance(val, understand.Ent):
report.entity(val)
report.print(val.name())
report.entity()
else:
report.print(val)
for ref in values[val]:
report.tree(2, True)
report.entity(ref.file())
report.print(ref.file().name())
report.entity()
report.syncfile(ref.file().longname(), ref.line(), ref.column())
report.print("(" + str(ref.line()) + ")")
report.syncfile()
report.tree()
def paramValue(ref, pos, lexercache):
lexer = findlexer(ref.file(), lexercache)
val = None
ents = []
if lexer:
lexeme = lexer.lexeme(ref.line(), ref.column())
parens = None
curPos = 0
while lexeme and (parens is None or parens > 0) and curPos <= pos:
if lexeme.token() == "Punctuation":
if lexeme.text() == ')':
parens -= 1
elif lexeme.text() == '(':
if parens:
parens += 1
else:
parens = 1
lexeme = lexeme.next()
continue
if lexeme.token() == "Operator" and parens and parens == 1 and lexeme.text() == ',':
# Only increment current position if we're at parentheses level
# 1, to handle nested functions with their own parameters
curPos += 1
lexeme = lexeme.next()
continue
if parens and curPos == pos:
# If this lexeme is inside the range mapped to this parameter
if not val:
val = ""
val = val + lexeme.text()
if lexeme.ent():
ents.append(lexeme.ent())
lexeme = lexeme.next()
if val:
val = val.strip()
if len(ents) == 1 and val and val.endswith(ents[0].name()):
val = ents[0]
return val
def findlexer(file, lexercache):
# Lexer creation takes significant time, so keep track of lexers already
# created instead of recreating them each time
lexer = None
if file in lexercache:
lexer = lexercache[file]
else:
try:
lexer = file.lexer()
lexercache[file] = lexer
except:
pass
return lexer