Index: .coafile =================================================================== --- .coafile +++ .coafile @@ -4,7 +4,7 @@ ignore = source/third_party/** [JS] -bears = ESLintBear, JSHintBear +bears = ESLintBear, JSHintBear, MirageBear eslint_config = build/jenkins/lint-config/eslintrc.json jshint_config = build/jenkins/lint-config/jshintrc.json files = binaries/data/**.js Index: build/coala/MirageBear.py =================================================================== --- /dev/null +++ build/coala/MirageBear.py @@ -0,0 +1,49 @@ +from coalib.bears.LocalBear import LocalBear +from coalib.results.Result import Result + +import os +import re + +class MirageBear(LocalBear): + + """ + Tries to detect unimplemented function calls on mirages. + """ + + LANGUAGES = {'Javascript'} + AUTHORS = {'Lancelot de Ferrière'} + LICENSE = 'GPL-2.0' + CAN_DETECT = {'Documentation', 'Formatting'} + + def run(self, filename, file): + + funcNames = set() + with open('binaries/data/mods/public/simulation/components/Mirage.js', 'r') as mirageFile: + line = mirageFile.readline() + while line: + match = re.match("Mirage\\.prototype\\.([aA-zZ_]+)", line) + if match != None: + funcNames.add(match.group(1)) + + line = mirageFile.readline() + + varNames = [] + for line_number, line in enumerate(file): + match = re.match("(\\t*)(let|var) (.+?) = QueryMiragedInterface", line) + if match != None: + # Count the number of tabs as primitive scoping detection + tabs = len(match.group(1)) + varNames.append((match.group(3), tabs)) + else: + currTabs = len(re.match("(\\t*)", line).group(1)) + delete = [] + for varName, tabs in varNames: + # if we are presumably out of scope, don't look for this variable name anymore. + if currTabs < tabs: + delete.append((varName, tabs)) + continue + funcCalls = re.findall(f"{varName}\\.([aA-zZ_]+)\\(", line) + for funcCall in funcCalls: + if funcCall not in funcNames: + yield Result.from_values('MirageBear', f"Possibly miraged function call {varName}.{funcCall}() appears to be unimplemented in Mirage.js.", file = filename, line = line_number + 1, severity = 2) + [varNames.remove(x) for x in delete]