def test_assign_to_global(self): code = 'AA(x) = 2' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'AA(x,y) = 2' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, [])
def test_change_types(self): code = 'private _x = ""; private _m = handgunMagazine player; _x = _m select 0; _x' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'isNull attachedTo player;' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, [])
def test_some_cases(self): code = 'call {\n#ifndef A\nx=2\n#endif\n}' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = '{\nx=1;\n\n #ifdef A\nx=1;\n#endif\n} forEach z;\nz\n' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, [])
def test_code_not_executed_in_loop(self): code = '{if ((_x select 0) == r && {(_x select 1) == r}) exitWith {};} forEach t;' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = '(allVariables _this) select {!(isNil {x getVariable _x})};' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, [])
def test_wrong_sum(self): code = 'y = x + z' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'y = x + do' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 2)
def test_if_else_private(self): code = 'private _a = ""; if (_a == "") then {_a = {true};} else {_a = compile _a;};' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Anything, type(analyzer['_a'])) code = 'private _a = ""; if (_a == "") then {_a = {true};} else {_a = compile _a;};' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Anything, type(analyzer['_a']))
def test_if_then_private(self): code = 'private _x = 1; if (y) then {_x = ""}; _x' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Anything, type(analyzer['_x'])) code = 'private "_x"; if (y) then {_x = ""}; _x' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Anything, type(analyzer['_x']))
def test_define_of_define(self): code = "#define A (call y)\n#define B (A==2)\nx=B;" analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Boolean, type(analyzer['x'])) code = "#define A(y) (call y)\n#define B (2==A({}))\nx=B;" analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Boolean, type(analyzer['x']))
def test_while(self): # undefined -> do not iterate analyzer = analyze(parse('while {x != 0} do {x = 1}')) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Anything(), analyzer['x']) # undefined -> test analyzer = analyze(parse('while {x != 0} do {! 1}')) errors = analyzer.exceptions self.assertEqual(len(errors), 1)
def test_assign_to_global(self): code = 'AA(x) = 2' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) code = 'AA(x,y) = 2' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0)
def test_undef_else(self): code = '\n#ifndef A\nx=1;\n#else\nx="";\n#endif\n' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(type(analyzer['x']), Number) code = '#define A\n' + code analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(type(analyzer['x']), String)
def test_wrong_types(self): code = 'private _x = ""; private _m = handgunMagazine player; _x = _m select 0;' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) code = 'isNull attachedTo player;' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0)
def test_simple(self): code = "#define A true\nprivate _x = A;" analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) self.assertEqual(type(analyzer['_x']), Boolean) code = "#define __CHECK_CATEGORY 2\nx = __CHECK_CATEGORY" analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) self.assertEqual(analyzer['x'], Number())
def test_forspecs(self): # undefined -> do not execute analyzer = analyze( parse('y = 0; for [{x = 1},{x <= z},{x = x + 1}] do {y = y + 1}')) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Number(), analyzer['y']) # undefined -> test analyzer = analyze( parse('y = 0; for [{x = 1},{x <= z},{x = x + 1}] do {!1}')) errors = analyzer.exceptions self.assertEqual(len(errors), 1)
def test_if1(self): # undefined -> do neither and invalidate any assigment analyzer = analyze(parse('x=2; if (y) then {x=1} else {x=2}')) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Number(), analyzer['x']) # undefined -> test then analyzer = analyze(parse('if (y) then {!1}')) errors = analyzer.exceptions self.assertEqual(len(errors), 1) # undefined -> test both analyzer = analyze(parse('if (y) then {!1} else {!2}')) errors = analyzer.exceptions self.assertEqual(len(errors), 2)
def test_if_missing_then(self): code = 'if (true) {1}' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 2) self.assertEqual((1, 11), errors[0].position) self.assertEqual((1, 1), errors[1].position)
def test_if(self): # assign in one branch is independent of the other code = 'if (a == "") then {a = {true};} else {a = compile a;};' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) self.assertEqual(Anything(), analyzer['a'])
def test_anything_for_undecided(self): # x could be different things and select would return different types, so select returns Anything code = 'y = (x select 0)' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) self.assertEqual(Anything(), analyzer['y'])
def analyze(filename, writer=sys.stdout): warnings = 0 errors = 0 print("Trying To Read {}".format(filename)) with open(filename, 'r') as file: code = file.read() try: result = parse(code) except SQFParserError as e: print("{}:".format(filename)) writer.write(' [%d,%d]:%s\n' % (e.position[0], e.position[1] - 1, e.message)) return 0, 1 exceptions = sqf.analyzer.analyze(result).exceptions if (exceptions): print("{}:".format(filename)) for e in exceptions: if (e.message.startswith("error")): errors = errors + 1 else: warnings = warnings + 1 writer.write(' [%d,%d]:%s\n' % (e.position[0], e.position[1] - 1, e.message)) return warnings, errors
def process_file(filePath): errors = [] warnings = [] try: with open(filePath, "r", encoding="utf-8", errors="ignore") as file: content = file.read() if "#ASC_ignoreFile" in content: return (filePath, errors, warnings) sqfLintParse = parse(content) exceptions = sqf.analyzer.analyze(sqfLintParse).exceptions if (exceptions): for e in exceptions: if ("assigned to an outer scope" in e.message): warnings.append( f"[{e.position[0]},{e.position[1]}] {e.message}") if ("is not from this scope" in e.message): warnings.append( f"[{e.position[0]},{e.position[1]}] {e.message}") if ("not used" in e.message): warnings.append( f"[{e.position[0]},{e.position[1]}] {e.message}") # most of this is just noise about macro parsing: # if (e.message.startswith("error")): # errors.append(f"[{e.position[0]},{e.position[1]}] {e.message}") # else: # warnings.append(f"[{e.position[0]},{e.position[1]}] {e.message}") except Exception as e: # errors.append(f"Exception {e}") pass return (filePath, errors, warnings)
def test_error_message_binary(self): code = '1 + "2"' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 1) self.assertTrue(errors[0].message.startswith( 'error:Binary operator "+" arguments must be ['))
def analyze(filename, startTime, writer=sys.stdout): warnings = 0 errors = 0 with open(filename, 'r') as file: code = file.read() try: result = parse(code) except SQFParserError as e: now = time.time() currentTime = now - startTime print("{0}: {1}".format(filename, currentTime)) writer.write(' [%d,%d]:%s\n' % (e.position[0], e.position[1] - 1, e.message)) return 0, 1 exceptions = sqf.analyzer.analyze(result).exceptions if (exceptions): now = time.time() currentTime = now - startTime print("{0}: {1}".format(filename, currentTime)) for e in exceptions: if (e.message.startswith("error")): errors += 1 writer.write(' [%d,%d]:%s\n' % (e.position[0], e.position[1] - 1, e.message)) else: warnings += 1 return warnings, errors
def test_double_ifdef(self): code = '#ifdef A\n#include "A"\n#endif\n' \ '#ifdef B\n#include "B"\n#endif\n' \ 'a = "";' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(type(analyzer['a']), String)
def test_basic(self): code = 'a=[_x,\n_y]' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 2) self.assertEqual((1, 4), errors[0].position) self.assertEqual((2, 1), errors[1].position)
def test_strange(self): code = '{\n\tformat ["",\n\t\t\t_z, _y];\n} forEach a;\n' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 2) self.assertEqual((3, 8), errors[1].position)
def test_define_replace_in_statement(self): code = '#define A 2\n' code += 'z=((2)min A)max 1' analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 0) self.assertEqual(Number, type(analyzer['z']))
def test_with_namespace_simple(self): code = 'with uinamespace do {_x; x = 2}' analyzer = analyze(parse(code)) self.assertEqual(len(analyzer.exceptions), 1) self.assertEqual(Anything, type(analyzer['x'])) # missionnamespace is empty self.assertEqual(Number, type(analyzer.namespace('uinamespace')['x']))
def test_select_count_apply(self): code = '{_x == 2} count x' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'x select {_x == 2}' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'x apply {_x == 2}' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) code = 'x select {_x == _y}' # _y is undefined analyzer = analyze(parse(code)) errors = analyzer.exceptions self.assertEqual(len(errors), 1)
def test_if_with_private_with_scoping(self): """ Changing on a scope does not alter the type of the other scope """ code = 'private _x = 1; if (y) then {private _x = ""; _x}; _x' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(Number, type(analyzer['_x']))
def test_undef_else_2(self): code = '#ifndef A\n' \ 'x=\n' \ '#else\n' \ 'y=\n' \ '#endif\n' \ '2' analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(type(analyzer['x']), Number) self.assertEqual(type(analyzer['y']), Anything) code = '#define A\n' + code analyzer = analyze(parse(code)) self.assertEqual(analyzer.exceptions, []) self.assertEqual(type(analyzer['x']), Anything) self.assertEqual(type(analyzer['y']), Number)