forked from pkp/ojs
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclassref.py
90 lines (82 loc) · 3.26 KB
/
classref.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
85
86
87
88
89
90
#!/bin/python3
import sys
import re
codefiles = [l.strip() for l in open(sys.argv[1])]
funcs = dict()
staticcalls = set()
for cf in codefiles:
curclass = None
incomment = False
for line in open(cf, 'r'):
if m := re.match(r'\s*class[^\w]+([\w_]+)', line):
curclass = m.group(1)
#print(f"class: {curclass}")
if m := re.search(r'\bfunction[^\w]+([\w_]+)', line):
funcname = m.group(1)
fullname = f"{curclass}::{funcname}"
if funcname == curclass:
print(f"Warning: probable old-style constructor {fullname}")
funcs[fullname.lower()] = 'static' if re.search('static', line) else 'regular'
if '/*' in line:
incomment = True
if '*/' in line:
incomment = False
if m := re.search(r'\b([\w_]+::[\w_]+)\s*\(', line):
if funcname == "__construct" and 'parent::' in m.group(1) and '__construct' not in m.group(1):
print(f"{cf}: {fullname}: Suspicious call to parent function in constructor: {line.strip()}")
if (not '@see' in line and not re.match(r'^\s*#',line)
and not re.match(r'^\s*//',line)
and not incomment
and not re.search(r'parent::|self::|static::', line)):
staticcalls.add(m.group(1))
# Fix old-style constructors
for cf in codefiles:
curclass = None
newcode = []
nchanges = 0
for line in open(cf, 'r'):
if m := re.match(r'\s*class[^\w]+([\w_]+)', line):
curclass = m.group(1)
elif m := re.search(r'\bfunction[^\w]+([\w_]+)', line):
funcname = m.group(1)
fullname = f"{curclass}::{funcname}"
if funcname == curclass:
print(f"Fixing old-style constructor {fullname}")
line = re.sub(r'\b(function[^\w]+)([\w_]+)', 'function __construct', line)
nchanges += 1
newcode.append(line)
if nchanges > 0:
with open(cf, 'w') as io:
for line in newcode:
io.write(line)
statictofix = set()
for c in sorted(list(staticcalls)):
if not c.lower() in funcs:
pass # print(f"hmm, static call to missing func {c}")
elif funcs[c.lower()] != 'static':
statictofix.add(c.lower())
# Fix static functions
for cf in codefiles:
curclass = None
newcode = []
nchanges = 0
for line in open(cf, 'r'):
if m := re.match(r'\s*class[^\w]+([\w_]+)', line):
curclass = m.group(1)
elif m := re.search(r'\bfunction[^\w]+([\w_]+)', line):
funcname = m.group(1)
fullname = f"{curclass}::{funcname}"
if fullname.lower() in statictofix and not('static' in line):
print(f"Fixing should-be-static function {fullname}")
line = re.sub(r'\bfunction\b', 'static function', line)
nchanges += 1
newcode.append(line)
if nchanges > 0:
with open(cf, 'w') as io:
for line in newcode:
io.write(line)
# for c in sorted(list(staticcalls)):
# if not c.lower() in funcs:
# print(f"hmm, static call to missing func {c}")
# elif funcs[c.lower()] != 'static':
# print(f"Warning: static call to non-static func {c}")