[javascriptlint-commit] SF.net SVN: javascriptlint:[325] trunk
Status: Beta
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2013-10-01 17:12:24
|
Revision: 325 http://sourceforge.net/p/javascriptlint/code/325 Author: matthiasmiller Date: 2013-10-01 17:12:20 +0000 (Tue, 01 Oct 2013) Log Message: ----------- First cut at warnings to validate function expression names (disabled by default) Modified Paths: -------------- trunk/javascriptlint/conf.py trunk/javascriptlint/warnings.py trunk/tests/control_comments/option_explicit.js trunk/tests/warnings/want_assign_or_call.js Added Paths: ----------- trunk/tests/warnings/function_name_mismatch.js trunk/tests/warnings/function_name_missing.js trunk/tests/warnings/misplaced_function.js Modified: trunk/javascriptlint/conf.py =================================================================== --- trunk/javascriptlint/conf.py 2013-10-01 17:07:11 UTC (rev 324) +++ trunk/javascriptlint/conf.py 2013-10-01 17:12:20 UTC (rev 325) @@ -6,12 +6,18 @@ import util import warnings +_DISABLED_WARNINGS = ( + 'block_without_braces', + 'function_name_missing', + 'function_name_mismatch', +) + def _getwarningsconf(): lines = [] for name in sorted(warnings.warnings.keys()): message = warnings.warnings[name] sign = '+' - if name == 'block_without_braces': + if name in _DISABLED_WARNINGS: sign = '-' assert len(name) < 29 lines.append(sign + name.ljust(29) + '# ' + message) @@ -183,7 +189,8 @@ } for name in warnings.warnings: self._settings[name] = BooleanSetting(True) - self.loadline('-block_without_braces') + for warning in _DISABLED_WARNINGS: + self.loadline('-%s' % warning) def loadfile(self, path): path = os.path.abspath(path) Modified: trunk/javascriptlint/warnings.py =================================================================== --- trunk/javascriptlint/warnings.py 2013-10-01 17:07:11 UTC (rev 324) +++ trunk/javascriptlint/warnings.py 2013-10-01 17:12:20 UTC (rev 325) @@ -102,6 +102,9 @@ 'unsupported_version': 'JavaScript {version} is not supported', 'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.', 'for_in_missing_identifier': 'for..in should have identifier on left side', + 'misplaced_function': 'unconventional use of function expression', + 'function_name_missing': 'anonymous function should be named to match property name {name}', + 'function_name_mismatch': 'function name {fn_name} does not match property name {prop_name}', } errors = { @@ -604,6 +607,87 @@ if not left.kind in (tok.VAR, tok.NAME): raise LintWarning, left +@lookfor(tok.FUNCTION) +def misplaced_function(node): + # Ignore function statements. + if node.opcode in (None, op.CLOSURE): + return + + # Ignore parens. + parent = node.parent + while parent.kind == tok.RP: + parent = parent.parent + + # Allow x = x || ... + if parent.kind == tok.OR and len(parent.kids) == 2 and \ + node is parent.kids[-1]: + parent = parent.parent + + if parent.kind == tok.NAME and parent.opcode == op.SETNAME: + return # Allow in var statements + if parent.kind == tok.ASSIGN and parent.opcode == op.NOP: + return # Allow in assigns + if parent.kind == tok.COLON and parent.parent.kind == tok.RC: + return # Allow in object literals + if parent.kind == tok.LP and parent.opcode in (op.CALL, op.SETCALL): + return # Allow in parameters + if parent.kind == tok.RETURN: + return # Allow for return values + if parent.kind == tok.NEW: + return # Allow as constructors + raise LintWarning, node + +def _get_expected_function_name(node): + # Ignore function statements. + if node.opcode in (None, op.CLOSURE): + return + + # Ignore parens. + parent = node.parent + while parent.kind == tok.RP: + parent = parent.parent + + # Allow x = x || ... + if parent.kind == tok.OR and len(parent.kids) == 2 and \ + node is parent.kids[-1]: + parent = parent.parent + + # Var assignment. + if parent.kind == tok.NAME and parent.opcode == op.SETNAME: + return parent.atom + + # Assignment. + if parent.kind == tok.ASSIGN and parent.opcode == op.NOP: + if parent.kids[0].kind == tok.NAME and \ + parent.kids[0].opcode == op.SETNAME: + return parent.kids[0].atom + return '<error>' + + # Object literal. + if parent.kind == tok.COLON and parent.parent.kind == tok.RC: + return parent.kids[0].atom + +@lookfor(tok.FUNCTION) +def function_name_missing(node): + if node.fn_name: + return + + expected_name = _get_expected_function_name(node) + if not expected_name is None: + raise LintWarning(node, name=expected_name) + +@lookfor(tok.FUNCTION) +def function_name_mismatch(node): + if not node.fn_name: + return + + expected_name = _get_expected_function_name(node) + if expected_name is None: + return + + if expected_name != node.fn_name: + raise LintWarning(node, fn_name=node.fn_name, prop_name=expected_name) + @lookfor() def mismatch_ctrl_comments(node): pass Modified: trunk/tests/control_comments/option_explicit.js =================================================================== --- trunk/tests/control_comments/option_explicit.js 2013-10-01 17:07:11 UTC (rev 324) +++ trunk/tests/control_comments/option_explicit.js 2013-10-01 17:12:20 UTC (rev 325) @@ -62,7 +62,7 @@ // This should be undeclared because this is an expression, // not a declaration. - (function func_expr() { /*warning:want_assign_or_call*/ + (function func_expr() { /*warning:misplaced_function*/ /*warning:want_assign_or_call*/ return 10; }); j = func_expr(); /*warning:undeclared_identifier*/ Added: trunk/tests/warnings/function_name_mismatch.js =================================================================== --- trunk/tests/warnings/function_name_mismatch.js (rev 0) +++ trunk/tests/warnings/function_name_mismatch.js 2013-10-01 17:12:20 UTC (rev 325) @@ -0,0 +1,36 @@ +/*conf:+function_name_mismatch*/ +function function_name_mismatch() { + var f = function bogus() { /*warning:function_name_mismatch*/ + }; + var g = function g() { + }; + + f = new function bogus() { + }; + f = new function() { + }; + + f = (function() { + return 10; + })(); + + var o = { + f: function bogus() { /*warning:function_name_mismatch*/ + return null; + } + }; + o.a.b = { + f: function bogus() { /*warning:function_name_mismatch*/ + return null; + } + }; + o.a.b = o.a.b || function bogus() { return 10; }; /*warning:function_name_mismatch*/ + + function closure(a) { + return function() { return a; }; + } + + function x() { + } +} + Added: trunk/tests/warnings/function_name_missing.js =================================================================== --- trunk/tests/warnings/function_name_missing.js (rev 0) +++ trunk/tests/warnings/function_name_missing.js 2013-10-01 17:12:20 UTC (rev 325) @@ -0,0 +1,30 @@ +/*conf:+function_name_missing*/ +function function_name_missing() { + var f = function() { /*warning:function_name_missing*/ + }; + f = new function() { + }; + f = (function() { + return 10; + })(); + + var o = { + f: function() { /*warning:function_name_missing*/ + return null; + } + }; + o.a.b = { + f: function() { /*warning:function_name_missing*/ + return null; + } + }; + o.a.b = o.a.b || function() { return 10; }; /*warning:function_name_missing*/ + + function closure(a) { + return function() { return a; }; + } + + function x() { + } +} + Added: trunk/tests/warnings/misplaced_function.js =================================================================== --- trunk/tests/warnings/misplaced_function.js (rev 0) +++ trunk/tests/warnings/misplaced_function.js 2013-10-01 17:12:20 UTC (rev 325) @@ -0,0 +1,33 @@ +/*conf:-want_assign_or_call*/ +function misplaced_functions() { + var f = function() { + }; + f = new function() { + }; + f = (function() { + return 10; + })(); + + var o = { + f: function() { + return null; + } + }; + o.a.b = { + f: function() { + return null; + } + }; + o.a.b = o.a.b || function() { return 10; }; + o.a.b = o.a.c || function() { return 10; }; /*TODO*/ + + function closure(a) { + return function() { return a; }; + } + + function x() { + } + + function() {}; /*warning:misplaced_function*/ +} + Modified: trunk/tests/warnings/want_assign_or_call.js =================================================================== --- trunk/tests/warnings/want_assign_or_call.js 2013-10-01 17:07:11 UTC (rev 324) +++ trunk/tests/warnings/want_assign_or_call.js 2013-10-01 17:12:20 UTC (rev 325) @@ -14,7 +14,7 @@ function test() { } - function() { /*warning:want_assign_or_call*/ + function() { /*warning:want_assign_or_call*/ /*warning:misplaced_function*/ return 42; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |