Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

"Suppress messages" feature for JSLint #131

Closed
wants to merge 10 commits into from

2 participants

penartur Douglas Crockford
penartur

In the current JSLint version, not everything is configurable; some checks are impossible to disable. This patch provides user with workaround for this limitation, allowing to disable specific warning messages (as opposed to checks that triggered the warning).

Allows to write code like this:

options: {
    suppress: { unnecessary_use: true }
}

or

"use strict";

var itWillBeStringifiedAndSentToBrowser = function () {
    /*suppress unnecessary_use: true */
    "use strict"; //so that the function will be executed in strict environment in browser
}
  • Implemented suppress setting in options, in the fashion similar to predef setting (e.g. suppress: ['some_message', 'some_other_message'] or suppress: { some_message: true, some_other_message: true }). true means that the message should be suppressed, false is the default.
  • Implemented setting suppress setting inline, in the fashion similar to /*jslint ... */ and /*global ... */ (e.g. /*suppress some_message, some_other_message */ or /*suppress some_message: true, other_message_suppressed_in_an_external_scope: false */).
  • Changed JSLint processing source code files to respect suppress setting; if the error JSLint is about to report is suppressed, it won't report about the error nor include it in its report.
  • In order to make this with as less pain as possible, some additional modifications were performed. Namely,
    • Previously warn always returned some return value. warn is used everywhere, but we only cared about the return value in stop. Now, only do_warn returns a return value, and do_warn is only called from warn and stop. In case error passed to do_warn should be suppressed, do_warn returns false instead of the detailed error info object.
    • In order for do_warn to check whether the message should be suppressed, suppressed_messages property added to JSLint object.
Douglas Crockford

That is going to further encourage bad practices. That is not my intent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 86 additions and 21 deletions.
  1. +86 −21 jslint.js
107 jslint.js
View
@@ -289,20 +289,20 @@
scanned_a_b, screen, script, search, second, section, select, shift,
slash_equal, slice, sloppy, small, sort, source, span, speech, split, src,
statement_block, stopping, strange_loop, strict, string, strong, stupid,
- style, styleproperty, sub, subscript, substr, sup, supplant, sync_a, t,
- table, 'table-layout', tag_a_in_b, tbody, td, test, 'text-align',
- 'text-decoration', 'text-indent', 'text-shadow', 'text-transform', textarea,
- tfoot, th, thead, third, thru, time, title, toLowerCase, toString,
- toUpperCase, token, too_long, too_many, top, tr, trailing_decimal_a, tree,
- tt, tty, tv, type, u, ul, unclosed, unclosed_comment, unclosed_regexp, undef,
- undefined, unescaped_a, unexpected_a, unexpected_char_a_b,
- unexpected_comment, unexpected_else, unexpected_label_a,
- unexpected_property_a, unexpected_space_a_b, 'unicode-bidi',
- unnecessary_initialize, unnecessary_use, unparam, unreachable_a_b,
- unrecognized_style_attribute_a, unrecognized_tag_a, unsafe, unused, url,
- urls, use_array, use_braces, use_charAt, use_object, use_or, use_param,
- used_before_a, var, var_a_not, vars, 'vertical-align', video, visibility,
- was, weird_assignment, weird_condition, weird_new, weird_program,
+ style, styleproperty, sub, subscript, substr, sup, supplant, suppress,
+ suppressed_messages, sync_a, t, table, 'table-layout', tag_a_in_b, tbody, td,
+ test, 'text-align', 'text-decoration', 'text-indent', 'text-shadow',
+ 'text-transform', textarea, tfoot, th, thead, third, thru, time, title,
+ toLowerCase, toString, toUpperCase, token, too_long, too_many, top, tr,
+ trailing_decimal_a, tree, tt, tty, tv, type, u, ul, unclosed,
+ unclosed_comment, unclosed_regexp, undef, undefined, unescaped_a,
+ unexpected_a, unexpected_char_a_b, unexpected_comment, unexpected_else,
+ unexpected_label_a, unexpected_property_a, unexpected_space_a_b,
+ 'unicode-bidi', unnecessary_initialize, unnecessary_use, unparam,
+ unreachable_a_b, unrecognized_style_attribute_a, unrecognized_tag_a, unsafe,
+ unused, url, urls, use_array, use_braces, use_charAt, use_object, use_or,
+ use_param, used_before_a, var, var_a_not, vars, 'vertical-align', video,
+ visibility, was, weird_assignment, weird_condition, weird_new, weird_program,
weird_relation, weird_ternary, white, 'white-space', width, windows,
'word-spacing', 'word-wrap', wrap, wrap_immediate, wrap_regexp,
write_is_wrong, writeable, 'z-index'
@@ -887,6 +887,7 @@ var JSLINT = (function () {
], false),
strict_mode,
+ suppressed_messages = {},
syntax = {},
tab,
token,
@@ -940,7 +941,7 @@ var JSLINT = (function () {
sx = /^\s*([{}:#%.=,>+\[\]@()"';]|[*$\^~]=|[a-zA-Z_][a-zA-Z0-9_\-]*|[0-9]+|<\/|\/\*)/,
ssx = /^\s*([@#!"'};:\-%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\/\*?|\d+(?:\.\d+)?|<\/)/,
// token
- tx = /^\s*([(){}\[\]\?.,:;'"~#@`]|={1,3}|\/(\*(jslint|properties|property|members?|globals?)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|[\^%]=?|&[&=]?|\|[|=]?|>{1,3}=?|<(?:[\/=!]|\!(\[|--)?|<=?)?|\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\.[0-9]*)?(?:[eE][+\-]?[0-9]+)?)/,
+ tx = /^\s*([(){}\[\]\?.,:;'"~#@`]|={1,3}|\/(\*(jslint|properties|property|members?|globals?|suppress)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|[\^%]=?|&[&=]?|\|[|=]?|>{1,3}=?|<(?:[\/=!]|\!(\[|--)?|<=?)?|\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\.[0-9]*)?(?:[eE][+\-]?[0-9]+)?)/,
// url badness
ux = /&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto|script/i,
@@ -1058,6 +1059,13 @@ var JSLINT = (function () {
}
+ function add_to_suppressed_messages(group) {
+ Object.keys(group).forEach(function (name) {
+ suppressed_messages[name] = group[name];
+ });
+ }
+
+
function assume() {
if (!option.safe) {
if (option.rhino) {
@@ -1106,8 +1114,11 @@ var JSLINT = (function () {
};
}
- function warn(message, offender, a, b, c, d) {
+ function do_warn(message, offender, a, b, c, d) {
var character, line, warning;
+ if (JSLINT.suppressed_messages[message] === true) {
+ return false;
+ }
offender = offender || next_token; // ~~
line = offender.line || 0;
character = offender.from || 0;
@@ -1136,20 +1147,26 @@ var JSLINT = (function () {
return warning;
}
+ function warn(message, offender, a, b, c, d) {
+ do_warn(message, offender, a, b, c, d);
+ }
+
function warn_at(message, line, character, a, b, c, d) {
- return warn(message, {
+ warn(message, {
line: line,
from: character
}, a, b, c, d);
}
function stop(message, offender, a, b, c, d) {
- var warning = warn(message, offender, a, b, c, d);
- quit(bundle.stopping, warning.line, warning.character);
+ var warning = do_warn(message, offender, a, b, c, d);
+ if (warning !== false) {
+ quit(bundle.stopping, warning.line, warning.character);
+ }
}
function stop_at(message, line, character, a, b, c, d) {
- return stop(message, {
+ stop(message, {
line: line,
from: character
}, a, b, c, d);
@@ -2144,6 +2161,38 @@ klass: do {
}
+ function do_suppresses() {
+ var name, is_suppress;
+ for (;;) {
+ if (next_token.id !== '(string)' && !next_token.identifier) {
+ return;
+ }
+ name = next_token.string;
+ advance();
+ is_suppress = true;
+ if (next_token.id === ':') {
+ advance(':');
+ switch (next_token.id) {
+ case 'true':
+ advance('true');
+ break;
+ case 'false':
+ is_suppress = false;
+ advance('false');
+ break;
+ default:
+ stop('unexpected_a');
+ }
+ }
+ suppressed_messages[name] = is_suppress;
+ if (next_token.id !== ',') {
+ return;
+ }
+ advance(',');
+ }
+ }
+
+
function do_jslint() {
var name, value;
while (next_token.id === '(string)' || next_token.identifier) {
@@ -2239,6 +2288,9 @@ klass: do {
}
do_globals();
break;
+ case '/*suppress':
+ do_suppresses();
+ break;
default:
stop('unexpected_a', this);
}
@@ -3960,6 +4012,7 @@ klass: do {
stmt('/*members', directive);
stmt('/*property', directive);
stmt('/*properties', directive);
+ stmt('/*suppress', directive);
stmt('var', function () {
@@ -5998,7 +6051,7 @@ klass: do {
itself = function JSLint(the_source, the_option) {
- var i, predef, tree;
+ var i, predef, suppress, tree;
JSLINT.errors = [];
JSLINT.tree = '';
JSLINT.properties = '';
@@ -6019,6 +6072,16 @@ klass: do {
add_to_predefined(predef);
}
}
+ suppress = option.suppress;
+ if (suppress) {
+ if (Array.isArray(suppress)) {
+ for (i = 0; i < suppress.length; i += 1) {
+ suppressed_messages[suppress[i]] = true;
+ }
+ } else if (typeof suppress === 'object') {
+ add_to_suppressed_messages(suppress);
+ }
+ }
do_safe();
} else {
option = {};
@@ -6392,6 +6455,8 @@ klass: do {
return output.join('\n');
};
+ itself.suppressed_messages = suppressed_messages;
+
itself.jslint = itself;
itself.edition = '2012-05-09';
Something went wrong with that request. Please try again.