mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 03:27:05 +01:00
* port ADMIN_VERB and friends * some renaming * dumb * one more rename * never search and replace this codebase * fix TM issues, more renaming * add a static analysis to shore up user verbs * fix double message on roundstart * remove macro we're not using yet * convert remaining playsounds verbs * convert more verbs i missed somehow * why is this a completely different signature than everything else * fix ui_interact arg * fix logging view and others * buncha issues caught in TM * fix mentor tickets ui * fix bug report viewing * moron
148 lines
4.6 KiB
Python
148 lines
4.6 KiB
Python
import os
|
|
import sys
|
|
import time
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
from avulto import DME, Path as p, ProcDecl
|
|
from avulto.ast import NodeKind, SourceLoc
|
|
|
|
|
|
RED = "\033[0;31m"
|
|
GREEN = "\033[0;32m"
|
|
BLUE = "\033[0;34m"
|
|
NC = "\033[0m" # No Color
|
|
|
|
|
|
def make_error(source_loc: SourceLoc, msg) -> str:
|
|
if os.getenv("GITHUB_ACTIONS") == "true":
|
|
return f"::error file={source_loc.file_path},line={source_loc.line},title=User Verbs::{source_loc.file_path}:{source_loc.line}: {RED}{msg}{NC}"
|
|
else:
|
|
return f"{source_loc.file_path}:{source_loc.line}: {RED}{msg}{NC}"
|
|
|
|
|
|
PROCS_NEED_CLIENT = (
|
|
"alert",
|
|
"tgui_input_list",
|
|
"tgui_input_number",
|
|
"to_chat",
|
|
)
|
|
|
|
BAD_VARS = (
|
|
"usr",
|
|
"src",
|
|
)
|
|
|
|
|
|
class Walker:
|
|
def __init__(self):
|
|
self.bad_names = []
|
|
self.bad_inputs = []
|
|
self.bad_calls = []
|
|
self.bad_clean_inputs = []
|
|
|
|
def visit_Identifier(self, node, source_info):
|
|
if node.name in BAD_VARS:
|
|
self.bad_names.append((node, source_info))
|
|
|
|
def visit_Input(self, node, source_info):
|
|
if node.args[0].kind == NodeKind.CONSTANT:
|
|
self.bad_inputs.append((node, source_info))
|
|
elif str(node.args[0]) in BAD_VARS:
|
|
self.bad_names.append((node.args[0], source_info))
|
|
|
|
def visit_Call(self, node, source_info):
|
|
if (
|
|
str(node.name) in PROCS_NEED_CLIENT
|
|
and node.args[0].kind == NodeKind.CONSTANT
|
|
):
|
|
self.bad_calls.append((node, source_info))
|
|
|
|
if str(node.name) == "clean_input":
|
|
last_arg = node.args[-1]
|
|
if last_arg.kind == NodeKind.ASSIGN_OP:
|
|
if str(last_arg.lhs) != "user" or str(last_arg.rhs) != "client":
|
|
self.bad_clean_inputs.append((node, source_info))
|
|
else:
|
|
self.bad_clean_inputs.append((node, source_info))
|
|
|
|
for arg in node.args:
|
|
if arg.kind == NodeKind.IDENTIFIER:
|
|
self.visit_Identifier(arg, source_info)
|
|
elif arg.kind == NodeKind.CALL:
|
|
self.visit_Call(arg, source_info)
|
|
elif arg.kind == NodeKind.INTERP_STRING:
|
|
# "[key_name(usr)] blah blah"
|
|
#
|
|
# hate we have to nest this so deeply but once we have a
|
|
# visit_Node for any Node, its tree is not going to get
|
|
# visited node by node unless we so do explicitly.
|
|
for expr, _ in arg.token_pairs:
|
|
if expr.kind == NodeKind.CALL:
|
|
self.visit_Call(expr, source_info)
|
|
elif expr.kind == NodeKind.IDENTIFIER:
|
|
self.visit_Identifier(expr, source_info)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("check_user_verb_params started")
|
|
|
|
exit_code = 0
|
|
start = time.time()
|
|
|
|
dme = DME.from_file("paradise.dme", parse_procs=True)
|
|
errors = []
|
|
|
|
for pth in dme.subtypesof("/datum/user_verb"):
|
|
walker = Walker()
|
|
td = dme.types[pth]
|
|
proc = td.proc_decls("__avd_do_verb")[0]
|
|
proc.walk(walker)
|
|
|
|
if walker.bad_names:
|
|
exit_code = 1
|
|
for name, source_loc in walker.bad_names:
|
|
errors.append(
|
|
make_error(
|
|
source_loc,
|
|
f"user verb {td.path} uses `{name}` instead of implicit client/client arg",
|
|
)
|
|
)
|
|
|
|
if walker.bad_inputs:
|
|
exit_code = 1
|
|
for node, source_loc in walker.bad_inputs:
|
|
errors.append(
|
|
make_error(
|
|
source_loc,
|
|
f"input() call in {td.path} missing explicit recipient",
|
|
)
|
|
)
|
|
|
|
if walker.bad_calls:
|
|
exit_code = 1
|
|
for node, source_loc in walker.bad_calls:
|
|
errors.append(
|
|
make_error(
|
|
source_loc,
|
|
f"call {node.name}() in {td.path} missing explicit recipient",
|
|
)
|
|
)
|
|
|
|
if walker.bad_clean_inputs:
|
|
exit_code = 1
|
|
for node, source_loc in walker.bad_clean_inputs:
|
|
errors.append(
|
|
make_error(
|
|
source_loc,
|
|
f"call {node.name}() in {td.path} must have `user = client` as its last arg",
|
|
)
|
|
)
|
|
|
|
for error in sorted(errors):
|
|
print(error)
|
|
|
|
end = time.time()
|
|
print(f"check_user_verb_params tests completed in {end - start:.2f}s\n")
|
|
sys.exit(exit_code)
|