coffeelint/lib/coffeelint.js in coffeelint-1.11.0 vs coffeelint/lib/coffeelint.js in coffeelint-1.14.0
- old
+ new
@@ -80,11 +80,11 @@
mergeDefaultConfig = function(userConfig) {
var config, rule, ruleConfig, ruleLoader;
try {
ruleLoader = nodeRequire('./ruleLoader');
ruleLoader.loadFromConfig(coffeelint, userConfig);
- } catch (_error) {}
+ } catch (undefined) {}
config = {};
if (userConfig.coffeelint) {
config.coffeelint = userConfig.coffeelint;
}
for (rule in RULES) {
@@ -139,12 +139,12 @@
};
coffeelint.invertLiterate = function(source) {
var len, line, n, newSource, ref;
source = CoffeeScript.helpers.invertLiterate(source);
- newSource = "";
- ref = source.split("\n");
+ newSource = '';
+ ref = source.split('\n');
for (n = 0, len = ref.length; n < len; n++) {
line = ref[n];
if (line.match(/^#/)) {
line = line.replace(/\s*$/, '');
}
@@ -160,38 +160,38 @@
var e, name, p, ref, ref1;
if (ruleName == null) {
ruleName = void 0;
}
p = new RuleConstructor;
- name = (p != null ? (ref = p.rule) != null ? ref.name : void 0 : void 0) || "(unknown)";
+ name = (p != null ? (ref = p.rule) != null ? ref.name : void 0 : void 0) || '(unknown)';
e = function(msg) {
throw new Error("Invalid rule: " + name + " " + msg);
};
if (p.rule == null) {
- e("Rules must provide rule attribute with a default configuration.");
+ e('Rules must provide rule attribute with a default configuration.');
}
if (p.rule.name == null) {
- e("Rule defaults require a name");
+ e('Rule defaults require a name');
}
if ((ruleName != null) && ruleName !== p.rule.name) {
e("Mismatched rule name: " + ruleName);
}
if (p.rule.message == null) {
- e("Rule defaults require a message");
+ e('Rule defaults require a message');
}
if (p.rule.description == null) {
- e("Rule defaults require a description");
+ e('Rule defaults require a description');
}
if ((ref1 = p.rule.level) !== 'ignore' && ref1 !== 'warn' && ref1 !== 'error') {
e("Default level must be 'ignore', 'warn', or 'error'");
}
if (typeof p.lintToken === 'function') {
if (!p.tokens) {
e("'tokens' is required for 'lintToken'");
}
} else if (typeof p.lintLine !== 'function' && typeof p.lintAST !== 'function') {
- e("Rules must implement lintToken, lintLine, or lintAST");
+ e('Rules must implement lintToken, lintLine, or lintAST');
}
RULES[p.rule.name] = p.rule;
return _rules[p.rule.name] = RuleConstructor;
};
@@ -282,11 +282,11 @@
hasSyntaxError = function(source) {
try {
CoffeeScript.tokens(source);
return false;
- } catch (_error) {}
+ } catch (undefined) {}
return true;
};
ErrorReport = require('./error_report.coffee');
@@ -312,21 +312,21 @@
config = mergeDefaultConfig(userConfig);
if (literate) {
source = this.invertLiterate(source);
}
if ((userConfig != null ? (ref = userConfig.coffeelint) != null ? ref.transforms : void 0 : void 0) != null) {
- sourceLength = source.split("\n").length;
+ sourceLength = source.split('\n').length;
ref2 = userConfig != null ? (ref1 = userConfig.coffeelint) != null ? ref1.transforms : void 0 : void 0;
for (n = 0, len = ref2.length; n < len; n++) {
m = ref2[n];
try {
ruleLoader = nodeRequire('./ruleLoader');
transform = ruleLoader.require(m);
source = transform(source);
- } catch (_error) {}
+ } catch (undefined) {}
}
- if (sourceLength !== source.split("\n").length && config.transform_messes_up_line_numbers.level !== 'ignore') {
+ if (sourceLength !== source.split('\n').length && config.transform_messes_up_line_numbers.level !== 'ignore') {
errors.push(extend({
lineNumber: 1,
context: "File was transformed from " + sourceLength + " lines to " + (source.split("\n").length) + " lines"
}, config.transform_messes_up_line_numbers));
}
@@ -427,11 +427,11 @@
},{"./../package.json":2,"./ast_linter.coffee":3,"./error_report.coffee":5,"./lexical_linter.coffee":6,"./line_linter.coffee":7,"./rules.coffee":8,"./rules/arrow_spacing.coffee":9,"./rules/braces_spacing.coffee":10,"./rules/camel_case_classes.coffee":11,"./rules/colon_assignment_spacing.coffee":12,"./rules/cyclomatic_complexity.coffee":13,"./rules/duplicate_key.coffee":14,"./rules/empty_constructor_needs_parens.coffee":15,"./rules/ensure_comprehensions.coffee":16,"./rules/eol_last.coffee":17,"./rules/indentation.coffee":18,"./rules/line_endings.coffee":19,"./rules/max_line_length.coffee":20,"./rules/missing_fat_arrows.coffee":21,"./rules/newlines_after_classes.coffee":22,"./rules/no_backticks.coffee":23,"./rules/no_debugger.coffee":24,"./rules/no_empty_functions.coffee":25,"./rules/no_empty_param_list.coffee":26,"./rules/no_implicit_braces.coffee":27,"./rules/no_implicit_parens.coffee":28,"./rules/no_interpolation_in_single_quotes.coffee":29,"./rules/no_nested_string_interpolation.coffee":30,"./rules/no_plusplus.coffee":31,"./rules/no_private_function_fat_arrows.coffee":32,"./rules/no_stand_alone_at.coffee":33,"./rules/no_tabs.coffee":34,"./rules/no_this.coffee":35,"./rules/no_throwing_strings.coffee":36,"./rules/no_trailing_semicolons.coffee":37,"./rules/no_trailing_whitespace.coffee":38,"./rules/no_unnecessary_double_quotes.coffee":39,"./rules/no_unnecessary_fat_arrows.coffee":40,"./rules/non_empty_constructor_needs_parens.coffee":41,"./rules/prefer_english_operator.coffee":42,"./rules/space_operators.coffee":43,"./rules/spacing_after_comma.coffee":44,"./rules/transform_messes_up_line_numbers.coffee":45}],2:[function(require,module,exports){
module.exports={
"name": "coffeelint",
"description": "Lint your CoffeeScript",
- "version": "1.11.0",
+ "version": "1.14.0",
"homepage": "http://www.coffeelint.org",
"keywords": [
"lint",
"coffeescript",
"coffee-script"
@@ -468,10 +468,11 @@
"pretest": "cake compile",
"test": "./vowsrunner.js --spec test/*.coffee test/*.litcoffee",
"testrule": "npm run compile && ./vowsrunner.js --spec",
"posttest": "npm run lint",
"prepublish": "cake prepublish",
+ "postpublish": "cake postpublish",
"publish": "cake publish",
"install": "cake install",
"lint": "cake compile && ./bin/coffeelint .",
"lint-csv": "cake compile && ./bin/coffeelint --csv .",
"lint-jslint": "cake compile && ./bin/coffeelint --jslint .",
@@ -543,16 +544,16 @@
ASTLinter.prototype.acceptRule = function(rule) {
return typeof rule.lintAST === 'function';
};
ASTLinter.prototype.lint = function() {
- var coffeeError, err, errors, j, len, ref, rule, v;
+ var coffeeError, err, error, errors, j, len, ref, rule, v;
errors = [];
try {
this.node = this.CoffeeScript.nodes(this.source);
- } catch (_error) {
- coffeeError = _error;
+ } catch (error) {
+ coffeeError = error;
err = this._parseCoffeeScriptError(coffeeError);
if (err != null) {
errors.push(err);
}
return errors;
@@ -644,22 +645,22 @@
if (attrs.level == null) {
attrs.level = this.config[ruleName].level;
}
level = attrs.level;
if (level !== 'ignore' && level !== 'warn' && level !== 'error') {
- throw new Error("unknown level " + level);
+ throw new Error("unknown level " + level + " for rule: " + ruleName);
}
if (level === 'error' || level === 'warn') {
attrs.rule = ruleName;
return defaults(attrs, this.config[ruleName]);
} else {
return null;
}
};
BaseLinter.prototype.acceptRule = function(rule) {
- throw new Error("acceptRule needs to be overridden in the subclass");
+ throw new Error('acceptRule needs to be overridden in the subclass');
};
BaseLinter.prototype.setupRules = function(rules) {
var RuleConstructor, level, name, results, rule;
this.rules = [];
@@ -673,11 +674,11 @@
results.push(this.rules.push(rule));
} else {
results.push(void 0);
}
} else if (level !== 'ignore') {
- throw new Error("unknown level " + level);
+ throw new Error("unknown level " + level + " for rule: " + rule);
} else {
results.push(void 0);
}
}
return results;
@@ -849,30 +850,23 @@
}
return errors;
};
LexicalLinter.prototype.lintToken = function(token) {
- var base, errors, j, len, lineNumber, ref, ref1, rule, type, v, value;
- type = token[0], value = token[1], lineNumber = token[2];
- if (typeof lineNumber === "object") {
- if (type === 'OUTDENT' || type === 'INDENT') {
- lineNumber = lineNumber.last_line;
- } else {
- lineNumber = lineNumber.first_line;
- }
- }
+ var base, errors, j, len, lineNumber, ref, ref1, ref2, rule, type, v, value;
+ type = token[0], value = token[1], (ref = token[2], lineNumber = ref.first_line);
if ((base = this.tokensByLine)[lineNumber] == null) {
base[lineNumber] = [];
}
this.tokensByLine[lineNumber].push(token);
this.lineNumber = lineNumber || this.lineNumber || 0;
this.tokenApi.lineNumber = this.lineNumber;
errors = [];
- ref = this.rules;
- for (j = 0, len = ref.length; j < len; j++) {
- rule = ref[j];
- if (!(ref1 = token[0], indexOf.call(rule.tokens, ref1) >= 0)) {
+ ref1 = this.rules;
+ for (j = 0, len = ref1.length; j < len; j++) {
+ rule = ref1[j];
+ if (!(ref2 = token[0], indexOf.call(rule.tokens, ref2) >= 0)) {
continue;
}
v = this.normalizeResult(rule, rule.lintToken(token, this.tokenApi));
if (v != null) {
errors.push(v);
@@ -883,12 +877,15 @@
LexicalLinter.prototype.createError = function(ruleName, attrs) {
if (attrs == null) {
attrs = {};
}
- attrs.lineNumber = this.lineNumber + 1;
- attrs.line = this.tokenApi.lines[this.lineNumber];
+ if (attrs.lineNumber == null) {
+ attrs.lineNumber = this.lineNumber;
+ }
+ attrs.lineNumber += 1;
+ attrs.line = this.tokenApi.lines[attrs.lineNumber - 1];
return LexicalLinter.__super__.createError.call(this, ruleName, attrs);
};
return LexicalLinter;
@@ -933,11 +930,11 @@
if (this.context["class"].classIndents === 0) {
this.context["class"].inClass = false;
this.context["class"].classIndents = null;
}
}
- if (this.context["class"].inClass && !line.match(/^\s*$/)) {
+ if (!line.match(/^\s*$/)) {
this.context["class"].lastUnemptyLineInClass = this.lineNumber;
}
} else {
if (!line.match(/\\s*/)) {
this.context["class"].lastUnemptyLineInClass = null;
@@ -1019,10 +1016,11 @@
errors = [];
ref = this.lineApi.lines;
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
line = ref[lineNumber];
this.lineApi.lineNumber = this.lineNumber = lineNumber;
+ this.lineApi.line = this.lineApi.lines[lineNumber];
this.lineApi.maintainClassContext(line);
this.collectInlineConfig(line);
ref1 = this.lintLine(line);
for (j = 0, len1 = ref1.length; j < len1; j++) {
error = ref1[j];
@@ -1054,11 +1052,11 @@
rules = [];
if (result[2] != null) {
ref = result[2].split(',');
for (i = 0, len = ref.length; i < len; i++) {
r = ref[i];
- rules.push(r.replace(/^\s+|\s+$/g, ""));
+ rules.push(r.replace(/^\s+|\s+$/g, ''));
}
}
this.block_config[cmd][this.lineNumber] = rules;
}
return null;
@@ -1106,43 +1104,30 @@
ArrowSpacing.prototype.rule = {
name: 'arrow_spacing',
level: 'ignore',
message: 'Function arrows (-> and =>) must be spaced properly',
- description: "<p>This rule checks to see that there is spacing before and after\nthe arrow operator that declares a function. This rule is disabled\nby default.</p> <p>Note that if arrow_spacing is enabled, and you\npass an empty function as a parameter, arrow_spacing will accept\neither a space or no space in-between the arrow operator and the\nparenthesis</p>\n<pre><code># Both of this will not trigger an error,\n# even with arrow_spacing enabled.\nx(-> 3)\nx( -> 3)\n\n# However, this will trigger an error\nx((a,b)-> 3)\n</code>\n</pre>"
+ description: '<p>This rule checks to see that there is spacing before and after\nthe arrow operator that declares a function. This rule is disabled\nby default.</p> <p>Note that if arrow_spacing is enabled, and you\npass an empty function as a parameter, arrow_spacing will accept\neither a space or no space in-between the arrow operator and the\nparenthesis</p>\n<pre><code># Both of this will not trigger an error,\n# even with arrow_spacing enabled.\nx(-> 3)\nx( -> 3)\n\n# However, this will trigger an error\nx((a,b)-> 3)\n</code>\n</pre>'
};
ArrowSpacing.prototype.tokens = ['->', '=>'];
ArrowSpacing.prototype.lintToken = function(token, tokenApi) {
var pp;
pp = tokenApi.peek(-1);
if (!pp) {
return;
}
- if (!token.spaced && (pp[1] === "(" && (pp.generated == null)) && tokenApi.peek(1)[0] === 'INDENT' && tokenApi.peek(2)[0] === 'OUTDENT') {
+ if (!token.spaced && tokenApi.peek(1)[0] === 'INDENT' && tokenApi.peek(2)[0] === 'OUTDENT') {
return null;
- } else if (!(((token.spaced != null) || (token.newLine != null) || this.atEof(tokenApi)) && (((pp.spaced != null) || pp[0] === 'TERMINATOR') || (pp.generated != null) || pp[0] === "INDENT" || (pp[1] === "(" && (pp.generated == null))))) {
+ } else if (!(((token.spaced != null) || (token.newLine != null)) && (((pp.spaced != null) || pp[0] === 'TERMINATOR') || (pp.generated != null) || pp[0] === 'INDENT' || (pp[1] === '(' && (pp.generated == null))))) {
return true;
} else {
return null;
}
};
- ArrowSpacing.prototype.atEof = function(tokenApi) {
- var i, j, len, ref, ref1, token, tokens;
- tokens = tokenApi.tokens, i = tokenApi.i;
- ref = tokens.slice(i + 1);
- for (j = 0, len = ref.length; j < len; j++) {
- token = ref[j];
- if (!(token.generated || ((ref1 = token[0]) === 'OUTDENT' || ref1 === 'TERMINATOR'))) {
- return false;
- }
- }
- return true;
- };
-
return ArrowSpacing;
})();
@@ -1172,11 +1157,11 @@
var nearestToken, totalDifference;
totalDifference = 0;
while (true) {
totalDifference += difference;
nearestToken = tokenApi.peek(totalDifference);
- if (nearestToken[0] === 'OUTDENT') {
+ if (nearestToken[0] === 'OUTDENT' || (nearestToken.generated != null)) {
continue;
}
return nearestToken;
}
};
@@ -1238,11 +1223,11 @@
CamelCaseClasses.prototype.rule = {
name: 'camel_case_classes',
level: 'error',
message: 'Class name should be UpperCamelCased',
- description: "This rule mandates that all class names are UpperCamelCased.\nCamel casing class names is a generally accepted way of\ndistinguishing constructor functions - which require the 'new'\nprefix to behave properly - from plain old functions.\n<pre>\n<code># Good!\nclass BoaConstrictor\n\n# Bad!\nclass boaConstrictor\n</code>\n</pre>\nThis rule is enabled by default."
+ description: 'This rule mandates that all class names are UpperCamelCased.\nCamel casing class names is a generally accepted way of\ndistinguishing constructor functions - which require the \'new\'\nprefix to behave properly - from plain old functions.\n<pre>\n<code># Good!\nclass BoaConstrictor\n\n# Bad!\nclass boaConstrictor\n</code>\n</pre>\nThis rule is enabled by default.'
};
CamelCaseClasses.prototype.tokens = ['CLASS'];
CamelCaseClasses.prototype.lintToken = function(token, tokenApi) {
@@ -1286,11 +1271,11 @@
message: 'Colon assignment without proper spacing',
spacing: {
left: 0,
right: 0
},
- description: "<p>This rule checks to see that there is spacing before and\nafter the colon in a colon assignment (i.e., classes, objects).\nThe spacing amount is specified by\nspacing.left and spacing.right, respectively.\nA zero value means no spacing required.\n</p>\n<pre><code>\n#\n# If spacing.left and spacing.right is 1\n#\n\n# Good\nobject = {spacing : true}\nclass Dog\n canBark : true\n\n# Bad\nobject = {spacing: true}\nclass Cat\n canBark: false\n</code></pre>"
+ description: '<p>This rule checks to see that there is spacing before and\nafter the colon in a colon assignment (i.e., classes, objects).\nThe spacing amount is specified by\nspacing.left and spacing.right, respectively.\nA zero value means no spacing required.\n</p>\n<pre><code>\n#\n# If spacing.left and spacing.right is 1\n#\n\n# Doesn\'t throw an error\nobject = {spacing : true}\nclass Dog\n canBark : true\n\n# Throws an error\nobject = {spacing: true}\nclass Cat\n canBark: false\n</code></pre>'
};
ColonAssignmentSpacing.prototype.tokens = [':'];
ColonAssignmentSpacing.prototype.lintToken = function(token, tokenApi) {
@@ -1316,11 +1301,11 @@
ref1 = checkSpacing('right'), isRightSpaced = ref1[0], rightSpacing = ref1[1];
if (isLeftSpaced && isRightSpaced) {
return null;
} else {
return {
- context: "Incorrect spacing around column " + token[2].first_column + ".\nExpected left: " + spaceRules.left + ", right: " + spaceRules.right + ".\nGot left: " + leftSpacing + ", right: " + rightSpacing + "."
+ context: "Incorrect spacing around column " + token[2].first_column
};
}
};
return ColonAssignmentSpacing;
@@ -1335,14 +1320,14 @@
module.exports = CyclomaticComplexity = (function() {
function CyclomaticComplexity() {}
CyclomaticComplexity.prototype.rule = {
name: 'cyclomatic_complexity',
- value: 10,
level: 'ignore',
message: 'The cyclomatic complexity is too damn high',
- description: 'Examine the complexity of your application.'
+ value: 10,
+ description: 'Examine the complexity of your function.'
};
CyclomaticComplexity.prototype.getComplexity = function(node) {
var complexity, name, ref;
name = this.astApi.getNodeName(node);
@@ -1354,28 +1339,28 @@
this.astApi = astApi;
this.lintNode(node);
return void 0;
};
- CyclomaticComplexity.prototype.lintNode = function(node, line) {
+ CyclomaticComplexity.prototype.lintNode = function(node) {
var complexity, error, name, ref, rule;
name = (ref = this.astApi) != null ? ref.getNodeName(node) : void 0;
complexity = this.getComplexity(node);
node.eachChild((function(_this) {
return function(childNode) {
- var nodeLine;
- nodeLine = childNode.locationData.first_line;
- if (childNode) {
- return complexity += _this.lintNode(childNode, nodeLine);
+ var childComplexity, ref1;
+ childComplexity = _this.lintNode(childNode);
+ if (((ref1 = _this.astApi) != null ? ref1.getNodeName(childNode) : void 0) !== 'Code') {
+ return complexity += childComplexity;
}
};
})(this));
rule = this.astApi.config[this.rule.name];
if (name === 'Code' && complexity >= rule.value) {
error = this.astApi.createError({
context: complexity + 1,
- lineNumber: line + 1,
+ lineNumber: node.locationData.first_line + 1,
lineNumberEnd: node.locationData.last_line + 1
});
if (error) {
this.errors.push(error);
}
@@ -1395,11 +1380,11 @@
module.exports = DuplicateKey = (function() {
DuplicateKey.prototype.rule = {
name: 'duplicate_key',
level: 'error',
message: 'Duplicate key defined in object or class',
- description: "Prevents defining duplicate keys in object literals and classes"
+ description: 'Prevents defining duplicate keys in object literals and classes'
};
DuplicateKey.prototype.tokens = ['IDENTIFIER', '{', '}'];
function DuplicateKey() {
@@ -1467,11 +1452,11 @@
EmptyConstructorNeedsParens.prototype.rule = {
name: 'empty_constructor_needs_parens',
level: 'ignore',
message: 'Invoking a constructor without parens and without arguments',
- description: "Requires constructors with no parameters to include the parens"
+ description: 'Requires constructors with no parameters to include the parens'
};
EmptyConstructorNeedsParens.prototype.tokens = ['UNARY'];
EmptyConstructorNeedsParens.prototype.lintToken = function(token, tokenApi) {
@@ -1531,44 +1516,52 @@
EnsureComprehensions.prototype.tokens = ['FOR'];
EnsureComprehensions.prototype.forBlock = false;
EnsureComprehensions.prototype.lintToken = function(token, tokenApi) {
- var atEqual, idents, numCallEnds, numCallStarts, peeker, prevIdents, prevToken, ref, ref1;
+ var atEqual, idents, numCallEnds, numCallStarts, numParenEnds, numParenStarts, peeker, prevIdents, prevToken, ref, ref1;
idents = this.findIdents(tokenApi);
if (this.forBlock) {
this.forBlock = false;
return;
}
peeker = -1;
atEqual = false;
numCallEnds = 0;
numCallStarts = 0;
+ numParenStarts = 0;
+ numParenEnds = 0;
prevIdents = [];
while ((prevToken = tokenApi.peek(peeker))) {
if (prevToken[0] === 'CALL_END') {
numCallEnds++;
}
if (prevToken[0] === 'CALL_START') {
numCallStarts++;
}
+ if (prevToken[0] === '(') {
+ numParenStarts++;
+ }
+ if (prevToken[0] === ')') {
+ numParenEnds++;
+ }
if (prevToken[0] === 'IDENTIFIER') {
if (!atEqual) {
prevIdents.push(prevToken[1]);
} else if (ref = prevToken[1], indexOf.call(idents, ref) >= 0) {
return;
}
}
if (((ref1 = prevToken[0]) === '(' || ref1 === '->' || ref1 === 'TERMINATOR') || (prevToken.newLine != null)) {
break;
}
- if (prevToken[0] === '=') {
+ if (prevToken[0] === '=' && numParenEnds === numParenStarts) {
atEqual = true;
}
peeker--;
}
- if (atEqual && prevIdents.length > 0 && numCallStarts === numCallEnds) {
+ if (atEqual && numCallStarts === numCallEnds) {
return {
context: ''
};
}
};
@@ -1613,18 +1606,21 @@
EOLLast.prototype.rule = {
name: 'eol_last',
level: 'ignore',
message: 'File does not end with a single newline',
- description: "Checks that the file ends with a single newline"
+ description: 'Checks that the file ends with a single newline'
};
EOLLast.prototype.lintLine = function(line, lineApi) {
+ var isNewline, previousIsNewline;
if (!lineApi.isLastLine()) {
return null;
}
- if (line.length) {
+ isNewline = line.length === 0;
+ previousIsNewline = lineApi.lineCount > 1 ? lineApi.lines[lineApi.lineNumber - 1].length === 0 : false;
+ if (!(isNewline && !previousIsNewline)) {
return true;
}
};
return EOLLast;
@@ -1632,57 +1628,58 @@
})();
},{}],18:[function(require,module,exports){
-var Indentation;
+var Indentation,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
module.exports = Indentation = (function() {
Indentation.prototype.rule = {
name: 'indentation',
value: 2,
level: 'error',
message: 'Line contains inconsistent indentation',
- description: "This rule imposes a standard number of spaces to be used for\nindentation. Since whitespace is significant in CoffeeScript, it's\ncritical that a project chooses a standard indentation format and\nstays consistent. Other roads lead to darkness. <pre> <code>#\nEnabling this option will prevent this ugly\n# but otherwise valid CoffeeScript.\ntwoSpaces = () ->\n fourSpaces = () ->\n eightSpaces = () ->\n 'this is valid CoffeeScript'\n\n</code>\n</pre>\nTwo space indentation is enabled by default."
+ description: 'This rule imposes a standard number of spaces to be used for\nindentation. Since whitespace is significant in CoffeeScript, it\'s\ncritical that a project chooses a standard indentation format and\nstays consistent. Other roads lead to darkness. <pre> <code>#\nEnabling this option will prevent this ugly\n# but otherwise valid CoffeeScript.\ntwoSpaces = () ->\n fourSpaces = () ->\n eightSpaces = () ->\n \'this is valid CoffeeScript\'\n\n</code>\n</pre>\nTwo space indentation is enabled by default.'
};
Indentation.prototype.tokens = ['INDENT', '[', ']', '.'];
+ Indentation.prototype.keywords = ['->', '=>', '@', 'CATCH', 'CLASS', 'ELSE', 'FINALLY', 'FOR', 'FORIN', 'FOROF', 'IDENTIFIER', 'IF', 'LEADING_WHEN', 'LOOP', 'RETURN', 'SWITCH', 'THROW', 'TRY', 'UNTIL', 'WHEN', 'WHILE', 'YIELD'];
+
function Indentation() {
this.arrayTokens = [];
}
Indentation.prototype.lintToken = function(token, tokenApi) {
- var currentLine, expected, ignoreIndent, isArrayIndent, isInterpIndent, isMultiline, lineNumber, lines, numIndents, previous, previousSymbol, ref, ref1, ref2, type;
+ var currentLine, expected, ignoreIndent, isArrayIndent, isMultiline, lineNumber, lines, numIndents, previous, previousSymbol, ref, ref1, ref2, type;
type = token[0], numIndents = token[1], (ref = token[2], lineNumber = ref.first_line);
lines = tokenApi.lines, lineNumber = tokenApi.lineNumber;
expected = tokenApi.config[this.rule.name].value;
if (type === '.') {
currentLine = lines[lineNumber];
- if (((ref1 = currentLine.match(/\S/i)) != null ? ref1[0] : void 0) === '.') {
+ if (((ref1 = currentLine.match(/\S/)) != null ? ref1[0] : void 0) === '.') {
return this.handleChain(tokenApi, expected);
}
return void 0;
}
if (type === '[' || type === ']') {
this.lintArray(token);
return void 0;
}
- if (token.generated != null) {
+ if ((token.generated != null) || (token.explicit != null)) {
return null;
}
- previous = tokenApi.peek(-2);
- isInterpIndent = previous && previous[0] === '+';
previous = tokenApi.peek(-1);
isArrayIndent = this.inArray() && (previous != null ? previous.newLine : void 0);
previousSymbol = (ref2 = tokenApi.peek(-1)) != null ? ref2[0] : void 0;
isMultiline = previousSymbol === '=' || previousSymbol === ',';
- ignoreIndent = isInterpIndent || isArrayIndent || isMultiline;
+ ignoreIndent = isArrayIndent || isMultiline;
numIndents = this.getCorrectIndent(tokenApi);
- if (!ignoreIndent && numIndents !== expected) {
+ if (!ignoreIndent && !(indexOf.call(numIndents, expected) >= 0)) {
return {
- context: "Expected " + expected + " got " + numIndents
+ context: "Expected " + expected + " got " + numIndents[0]
};
}
};
Indentation.prototype.inArray = function() {
@@ -1715,13 +1712,13 @@
prevNum += 1;
}
checkNum = lineNumber - prevNum;
if (checkNum >= 0) {
prevLine = lines[checkNum];
- if (prevLine.match(/\S/i)[0] === '.' || checkNum === lastCheck) {
- currentSpaces = (ref = currentLine.match(/\S/i)) != null ? ref.index : void 0;
- prevSpaces = (ref1 = prevLine.match(/\S/i)) != null ? ref1.index : void 0;
+ if (prevLine.match(/\S/)[0] === '.' || checkNum === lastCheck) {
+ currentSpaces = (ref = currentLine.match(/\S/)) != null ? ref.index : void 0;
+ prevSpaces = (ref1 = prevLine.match(/\S/)) != null ? ref1.index : void 0;
numIndents = currentSpaces - prevSpaces;
prevIsIndent = prevSpaces % expected !== 0;
currIsIndent = currentSpaces % expected !== 0;
if (prevIsIndent && currIsIndent) {
numIndents = currentSpaces;
@@ -1733,25 +1730,85 @@
}
}
}
};
+ Indentation.prototype.grabLineTokens = function(tokenApi, lineNumber, all) {
+ var i, k, len, len1, ref, ref1, results, results1, tok, tokensByLine;
+ if (all == null) {
+ all = false;
+ }
+ tokensByLine = tokenApi.tokensByLine;
+ while (!((tokensByLine[lineNumber] != null) || lineNumber === 0)) {
+ lineNumber--;
+ }
+ if (all) {
+ ref = tokensByLine[lineNumber];
+ results = [];
+ for (i = 0, len = ref.length; i < len; i++) {
+ tok = ref[i];
+ results.push(tok);
+ }
+ return results;
+ } else {
+ ref1 = tokensByLine[lineNumber];
+ results1 = [];
+ for (k = 0, len1 = ref1.length; k < len1; k++) {
+ tok = ref1[k];
+ if ((tok.generated == null) && tok[0] !== 'OUTDENT') {
+ results1.push(tok);
+ }
+ }
+ return results1;
+ }
+ };
+
Indentation.prototype.getCorrectIndent = function(tokenApi) {
- var curIndent, i, lineNumber, lines, prevIndent, prevLine, prevNum, ref, ref1, ref2, tokens;
- lineNumber = tokenApi.lineNumber, lines = tokenApi.lines, tokens = tokenApi.tokens, i = tokenApi.i;
+ var _, curIndent, i, j, len, lineNumber, lines, prevIndent, prevNum, prevTokens, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ret, skipAssign, t, tokens, tryLine;
+ lineNumber = tokenApi.lineNumber, lines = tokenApi.lines, tokens = tokenApi.tokens;
curIndent = (ref = lines[lineNumber].match(/\S/)) != null ? ref.index : void 0;
prevNum = 1;
while (/^\s*(#|$)/.test(lines[lineNumber - prevNum])) {
prevNum += 1;
}
- prevLine = lines[lineNumber - prevNum];
- prevIndent = (ref1 = prevLine.match(/^(\s*)\./)) != null ? ref1[1].length : void 0;
- if (prevIndent > 0) {
- return curIndent - ((ref2 = prevLine.match(/\S/)) != null ? ref2.index : void 0);
+ prevTokens = this.grabLineTokens(tokenApi, lineNumber - prevNum);
+ if (((ref1 = prevTokens[0]) != null ? ref1[0] : void 0) === 'INDENT') {
+ return [curIndent - ((ref2 = prevTokens[1]) != null ? ref2[2].first_column : void 0), curIndent - prevTokens[0][1]];
} else {
- return tokens[i][1];
+ prevIndent = (ref3 = prevTokens[0]) != null ? ref3[2].first_column : void 0;
+ for (j = i = 0, len = prevTokens.length; i < len; j = ++i) {
+ _ = prevTokens[j];
+ if (!(prevTokens[j][0] === '=' && ((ref4 = prevTokens[j + 1]) != null ? ref4[0] : void 0) === 'IF')) {
+ continue;
+ }
+ skipAssign = curIndent - prevTokens[j + 1][2].first_column;
+ ret = curIndent - prevIndent;
+ if (skipAssign < 0) {
+ return [ret];
+ }
+ return [skipAssign, ret];
+ }
+ while (prevIndent > curIndent) {
+ tryLine = lineNumber - prevNum;
+ prevTokens = this.grabLineTokens(tokenApi, tryLine, true);
+ if (((ref5 = prevTokens[0]) != null ? ref5[0] : void 0) === 'INDENT') {
+ prevIndent = prevTokens[0][1];
+ prevTokens = prevTokens.slice(1);
+ }
+ t = 0;
+ while (!((prevTokens[t] == null) || (ref6 = prevTokens[t][0], indexOf.call(this.keywords, ref6) >= 0))) {
+ t++;
+ }
+ prevTokens = prevTokens.slice(t);
+ prevNum++;
+ if (prevTokens[0] == null) {
+ continue;
+ }
+ prevIndent = (ref7 = prevTokens[0]) != null ? ref7[2].first_column : void 0;
+ }
}
+ return [curIndent - prevIndent];
};
return Indentation;
})();
@@ -1767,11 +1824,11 @@
LineEndings.prototype.rule = {
name: 'line_endings',
level: 'ignore',
value: 'unix',
message: 'Line contains incorrect line endings',
- description: "This rule ensures your project uses only <tt>windows</tt> or\n<tt>unix</tt> line endings. This rule is disabled by default."
+ description: 'This rule ensures your project uses only <tt>windows</tt> or\n<tt>unix</tt> line endings. This rule is disabled by default.'
};
LineEndings.prototype.lintLine = function(line, lineApi) {
var ending, lastChar, ref, valid;
ending = (ref = lineApi.config[this.rule.name]) != null ? ref.value : void 0;
@@ -1818,11 +1875,11 @@
name: 'max_line_length',
value: 80,
level: 'error',
limitComments: true,
message: 'Line exceeds maximum allowed length',
- description: "This rule imposes a maximum line length on your code. <a\nhref=\"http://www.python.org/dev/peps/pep-0008/\">Python's style\nguide</a> does a good job explaining why you might want to limit the\nlength of your lines, though this is a matter of taste.\n\nLines can be no longer than eighty characters by default."
+ description: 'This rule imposes a maximum line length on your code. <a\nhref="http://www.python.org/dev/peps/pep-0008/">Python\'s style\nguide</a> does a good job explaining why you might want to limit the\nlength of your lines, though this is a matter of taste.\n\nLines can be no longer than eighty characters by default.'
};
MaxLineLength.prototype.lintLine = function(line, lineApi) {
var limitComments, lineLength, max, ref, ref1;
max = (ref = lineApi.config[this.rule.name]) != null ? ref.value : void 0;
@@ -1888,29 +1945,32 @@
MissingFatArrows.prototype.rule = {
name: 'missing_fat_arrows',
level: 'ignore',
is_strict: false,
message: 'Used `this` in a function without a fat arrow',
- description: "Warns when you use `this` inside a function that wasn't defined\nwith a fat arrow. This rule does not apply to methods defined in a\nclass, since they have `this` bound to the class instance (or the\nclass itself, for class methods). The option `is_strict` is\navailable for checking bindings of class methods.\n\nIt is impossible to statically determine whether a function using\n`this` will be bound with the correct `this` value due to language\nfeatures like `Function.prototype.call` and\n`Function.prototype.bind`, so this rule may produce false positives."
+ description: 'Warns when you use `this` inside a function that wasn\'t defined\nwith a fat arrow. This rule does not apply to methods defined in a\nclass, since they have `this` bound to the class instance (or the\nclass itself, for class methods). The option `is_strict` is\navailable for checking bindings of class methods.\n\nIt is impossible to statically determine whether a function using\n`this` will be bound with the correct `this` value due to language\nfeatures like `Function.prototype.call` and\n`Function.prototype.bind`, so this rule may produce false positives.'
};
MissingFatArrows.prototype.lintAST = function(node, astApi) {
this.astApi = astApi;
this.lintNode(node);
return void 0;
};
MissingFatArrows.prototype.lintNode = function(node, methods) {
- var error, is_strict, ref;
+ var error, isStrict, ref;
if (methods == null) {
methods = [];
}
- is_strict = (ref = this.astApi.config[this.rule.name]) != null ? ref.is_strict : void 0;
+ isStrict = (ref = this.astApi.config[this.rule.name]) != null ? ref.is_strict : void 0;
+ if (this.isPrototype(node)) {
+ return;
+ }
if (this.isConstructor(node)) {
return;
}
- if ((!this.isFatArrowCode(node)) && (is_strict ? true : indexOf.call(methods, node) < 0) && (this.needsFatArrow(node))) {
+ if ((!this.isFatArrowCode(node)) && (isStrict ? true : indexOf.call(methods, node) < 0) && (this.needsFatArrow(node))) {
error = this.astApi.createError({
lineNumber: node.locationData.first_line + 1
});
this.errors.push(error);
}
@@ -1944,10 +2004,22 @@
MissingFatArrows.prototype.isObject = function(node) {
return this.astApi.getNodeName(node) === 'Obj';
};
+ MissingFatArrows.prototype.isPrototype = function(node) {
+ var i, ident, len, props, ref, ref1;
+ props = (node != null ? (ref = node.variable) != null ? ref.properties : void 0 : void 0) || [];
+ for (i = 0, len = props.length; i < len; i++) {
+ ident = props[i];
+ if (((ref1 = ident.name) != null ? ref1.value : void 0) === 'prototype') {
+ return true;
+ }
+ }
+ return false;
+ };
+
MissingFatArrows.prototype.isThis = function(node) {
return this.isValue(node) && node.base.value === 'this';
};
MissingFatArrows.prototype.isFatArrowCode = function(node) {
@@ -1995,27 +2067,67 @@
NewlinesAfterClasses.prototype.rule = {
name: 'newlines_after_classes',
value: 3,
level: 'ignore',
message: 'Wrong count of newlines between a class and other code',
- description: "<p>Checks the number of newlines between classes and other code.</p>\n\nOptions:\n- <pre><code>value</code></pre> - The number of required newlines\nafter class definitions. Defaults to 3."
+ description: '<p>Checks the number of newlines between classes and other code.</p>\n\nOptions:\n- <pre><code>value</code></pre> - The number of required newlines\nafter class definitions. Defaults to 3.'
};
- NewlinesAfterClasses.prototype.lintLine = function(line, lineApi) {
- var context, ending, got, lineNumber;
- ending = lineApi.config[this.rule.name].value;
- if (!ending || lineApi.isLastLine()) {
- return null;
+ NewlinesAfterClasses.prototype.tokens = ['CLASS', '}', '{'];
+
+ NewlinesAfterClasses.prototype.classBracesCount = 0;
+
+ NewlinesAfterClasses.prototype.classCount = 0;
+
+ NewlinesAfterClasses.prototype.lintToken = function(token, tokenApi) {
+ var afters, befores, comment, ending, got, lineNumber, lines, numIndents, outdent, ref, ref1, ref2, start, trueLine, type;
+ type = token[0], numIndents = token[1], (ref = token[2], lineNumber = ref.first_line);
+ lines = tokenApi.lines;
+ ending = tokenApi.config[this.rule.name].value;
+ if (type === 'CLASS') {
+ this.classCount++;
}
- lineNumber = lineApi.lineNumber, context = lineApi.context;
- if (!context["class"].inClass && (context["class"].lastUnemptyLineInClass != null) && (lineNumber - context["class"].lastUnemptyLineInClass) !== ending) {
- got = lineNumber - context["class"].lastUnemptyLineInClass;
- return {
- context: "Expected " + ending + " got " + got
- };
+ if (this.classCount > 0 && (token.generated != null)) {
+ if (type === '{' && ((ref1 = token.origin) != null ? ref1[0] : void 0) === ':') {
+ this.classBracesCount++;
+ }
+ if (type === '}' && ((ref2 = token.origin) != null ? ref2[0] : void 0) === 'OUTDENT') {
+ this.classBracesCount--;
+ this.classCount--;
+ if (this.classCount === 0 && this.classBracesCount === 0) {
+ befores = 1;
+ afters = 1;
+ comment = 0;
+ outdent = token.origin[2].first_line;
+ start = Math.min(lineNumber, outdent);
+ trueLine = Infinity;
+ while (/^\s*(#|$)/.test(lines[start + afters])) {
+ if (/^\s*#/.test(lines[start + afters])) {
+ comment += 1;
+ } else {
+ trueLine = Math.min(trueLine, start + afters);
+ }
+ afters += 1;
+ }
+ while (/^\s*(#|$)/.test(lines[start - befores])) {
+ if (/^\s*#/.test(lines[start - befores])) {
+ comment += 1;
+ } else {
+ trueLine = Math.min(trueLine, start - befores);
+ }
+ befores += 1;
+ }
+ got = afters + befores - comment - 2;
+ if (got !== ending && trueLine + ending <= lines.length) {
+ return {
+ context: "Expected " + ending + " got " + got,
+ lineNumber: trueLine
+ };
+ }
+ }
+ }
}
- return null;
};
return NewlinesAfterClasses;
})();
@@ -2030,14 +2142,14 @@
NoBackticks.prototype.rule = {
name: 'no_backticks',
level: 'error',
message: 'Backticks are forbidden',
- description: "Backticks allow snippets of JavaScript to be embedded in\nCoffeeScript. While some folks consider backticks useful in a few\nniche circumstances, they should be avoided because so none of\nJavaScript's \"bad parts\", like <tt>with</tt> and <tt>eval</tt>,\nsneak into CoffeeScript.\nThis rule is enabled by default."
+ description: 'Backticks allow snippets of JavaScript to be embedded in\nCoffeeScript. While some folks consider backticks useful in a few\nniche circumstances, they should be avoided because so none of\nJavaScript\'s "bad parts", like <tt>with</tt> and <tt>eval</tt>,\nsneak into CoffeeScript.\nThis rule is enabled by default.'
};
- NoBackticks.prototype.tokens = ["JS"];
+ NoBackticks.prototype.tokens = ['JS'];
NoBackticks.prototype.lintToken = function(token, tokenApi) {
return true;
};
@@ -2056,14 +2168,14 @@
NoDebugger.prototype.rule = {
name: 'no_debugger',
level: 'warn',
message: 'Found debugging code',
console: false,
- description: "This rule detects `debugger` and optionally `console` calls\nThis rule is `warn` by default."
+ description: 'This rule detects `debugger` and optionally `console` calls\nThis rule is `warn` by default.'
};
- NoDebugger.prototype.tokens = ["DEBUGGER", "IDENTIFIER"];
+ NoDebugger.prototype.tokens = ['DEBUGGER', 'IDENTIFIER'];
NoDebugger.prototype.lintToken = function(token, tokenApi) {
var method, ref, ref1;
if (token[0] === 'DEBUGGER') {
return {
@@ -2100,11 +2212,11 @@
NoEmptyFunctions.prototype.rule = {
name: 'no_empty_functions',
level: 'ignore',
message: 'Empty function',
- description: "Disallows declaring empty functions. The goal of this rule is that\nunintentional empty callbacks can be detected:\n<pre>\n<code>someFunctionWithCallback ->\ndoSomethingSignificant()\n</code>\n</pre>\nThe problem is that the call to\n<tt>doSomethingSignificant</tt> will be made regardless\nof <tt>someFunctionWithCallback</tt>'s execution. It can\nbe because you did not indent the call to\n<tt>doSomethingSignificant</tt> properly.\n\nIf you really meant that <tt>someFunctionWithCallback</tt>\nshould call a callback that does nothing, you can write your code\nthis way:\n<pre>\n<code>someFunctionWithCallback ->\n undefined\ndoSomethingSignificant()\n</code>\n</pre>"
+ description: 'Disallows declaring empty functions. The goal of this rule is that\nunintentional empty callbacks can be detected:\n<pre>\n<code>someFunctionWithCallback ->\ndoSomethingSignificant()\n</code>\n</pre>\nThe problem is that the call to\n<tt>doSomethingSignificant</tt> will be made regardless\nof <tt>someFunctionWithCallback</tt>\'s execution. It can\nbe because you did not indent the call to\n<tt>doSomethingSignificant</tt> properly.\n\nIf you really meant that <tt>someFunctionWithCallback</tt>\nshould call a callback that does nothing, you can write your code\nthis way:\n<pre>\n<code>someFunctionWithCallback ->\n undefined\ndoSomethingSignificant()\n</code>\n</pre>'
};
NoEmptyFunctions.prototype.lintAST = function(node, astApi) {
this.lintNode(node, astApi);
return void 0;
@@ -2139,14 +2251,14 @@
NoEmptyParamList.prototype.rule = {
name: 'no_empty_param_list',
level: 'ignore',
message: 'Empty parameter list is forbidden',
- description: "This rule prohibits empty parameter lists in function definitions.\n<pre>\n<code># The empty parameter list in here is unnecessary:\nmyFunction = () ->\n\n# We might favor this instead:\nmyFunction = ->\n</code>\n</pre>\nEmpty parameter lists are permitted by default."
+ description: 'This rule prohibits empty parameter lists in function definitions.\n<pre>\n<code># The empty parameter list in here is unnecessary:\nmyFunction = () ->\n\n# We might favor this instead:\nmyFunction = ->\n</code>\n</pre>\nEmpty parameter lists are permitted by default.'
};
- NoEmptyParamList.prototype.tokens = ["PARAM_START"];
+ NoEmptyParamList.prototype.tokens = ['PARAM_START'];
NoEmptyParamList.prototype.lintToken = function(token, tokenApi) {
var nextType;
nextType = tokenApi.peek()[0];
return nextType === 'PARAM_END';
@@ -2168,48 +2280,56 @@
message: 'Implicit braces are forbidden',
strict: true,
description: 'This rule prohibits implicit braces when declaring object literals.\nImplicit braces can make code more difficult to understand,\nespecially when used in combination with optional parenthesis.\n<pre>\n<code># Do you find this code ambiguous? Is it a\n# function call with three arguments or four?\nmyFunction a, b, 1:2, 3:4\n\n# While the same code written in a more\n# explicit manner has no ambiguity.\nmyFunction(a, b, {1:2, 3:4})\n</code>\n</pre>\nImplicit braces are permitted by default, since their use is\nidiomatic CoffeeScript.'
};
- NoImplicitBraces.prototype.tokens = ['{', 'OUTDENT', 'CLASS'];
+ NoImplicitBraces.prototype.tokens = ['{', 'OUTDENT', 'CLASS', 'IDENTIFIER'];
function NoImplicitBraces() {
this.isClass = false;
- this.classBrace = false;
+ this.className = void 0;
}
NoImplicitBraces.prototype.lintToken = function(token, tokenApi) {
- var lineNum, previousToken, type, val;
+ var lineNum, peekTwo, prevToken, type, val;
type = token[0], val = token[1], lineNum = token[2];
if (type === 'OUTDENT' || type === 'CLASS') {
return this.trackClass.apply(this, arguments);
}
- if (token.generated) {
- if (this.classBrace) {
- this.classBrace = false;
- return;
- }
+ if (type === 'IDENTIFIER' && this.isClass && ((this.className == null) || tokenApi.peek(-1)[0] === 'EXTENDS')) {
+ this.className = val;
+ }
+ if (token.generated && type === '{') {
if (!tokenApi.config[this.rule.name].strict) {
- previousToken = tokenApi.peek(-1)[0];
- if (previousToken === 'INDENT') {
+ prevToken = tokenApi.peek(-1)[0];
+ if (prevToken === 'INDENT' || prevToken === 'TERMINATOR') {
return;
}
}
+ if (this.isClass) {
+ prevToken = tokenApi.peek(-1)[0];
+ if (prevToken === 'TERMINATOR') {
+ return;
+ }
+ peekTwo = tokenApi.peek(-2);
+ if (peekTwo[0] === 'IDENTIFIER' && peekTwo[1] === this.className) {
+ return;
+ }
+ }
return true;
}
};
NoImplicitBraces.prototype.trackClass = function(token, tokenApi) {
var ln, n0, n1, ref, ref1, ref2;
ref = [token, tokenApi.peek()], (ref1 = ref[0], n0 = ref1[0], ln = ref1[ref1.length - 1]), (ref2 = ref[1], n1 = ref2[0]);
if (n0 === 'OUTDENT' && n1 === 'TERMINATOR') {
this.isClass = false;
- this.classBrace = false;
}
if (n0 === 'CLASS') {
this.isClass = true;
- this.classBrace = true;
+ this.className = void 0;
}
return null;
};
return NoImplicitBraces;
@@ -2224,14 +2344,14 @@
module.exports = NoImplicitParens = (function() {
function NoImplicitParens() {}
NoImplicitParens.prototype.rule = {
name: 'no_implicit_parens',
- strict: true,
level: 'ignore',
message: 'Implicit parens are forbidden',
- description: "This rule prohibits implicit parens on function calls.\n<pre>\n<code># Some folks don't like this style of coding.\nmyFunction a, b, c\n\n# And would rather it always be written like this:\nmyFunction(a, b, c)\n</code>\n</pre>\nImplicit parens are permitted by default, since their use is\nidiomatic CoffeeScript."
+ strict: true,
+ description: 'This rule prohibits implicit parens on function calls.\n<pre>\n<code># Some folks don\'t like this style of coding.\nmyFunction a, b, c\n\n# And would rather it always be written like this:\nmyFunction(a, b, c)\n</code>\n</pre>\nImplicit parens are permitted by default, since their use is\nidiomatic CoffeeScript.'
};
NoImplicitParens.prototype.tokens = ['CALL_END'];
NoImplicitParens.prototype.lintToken = function(token, tokenApi) {
@@ -2347,14 +2467,14 @@
NoPlusPlus.prototype.rule = {
name: 'no_plusplus',
level: 'ignore',
message: 'The increment and decrement operators are forbidden',
- description: "This rule forbids the increment and decrement arithmetic operators.\nSome people believe the <tt>++</tt> and <tt>--</tt> to be cryptic\nand the cause of bugs due to misunderstandings of their precedence\nrules.\nThis rule is disabled by default."
+ description: 'This rule forbids the increment and decrement arithmetic operators.\nSome people believe the <tt>++</tt> and <tt>--</tt> to be cryptic\nand the cause of bugs due to misunderstandings of their precedence\nrules.\nThis rule is disabled by default.'
};
- NoPlusPlus.prototype.tokens = ["++", "--"];
+ NoPlusPlus.prototype.tokens = ['++', '--'];
NoPlusPlus.prototype.lintToken = function(token, tokenApi) {
return {
context: "found '" + token[0] + "'"
};
@@ -2382,11 +2502,11 @@
NoPrivateFunctionFatArrows.prototype.rule = {
name: 'no_private_function_fat_arrows',
level: 'warn',
message: 'Used the fat arrow for a private function',
- description: "Warns when you use the fat arrow for a private function\ninside a class defintion scope. It is not necessary and\nit does not do anything."
+ description: 'Warns when you use the fat arrow for a private function\ninside a class definition scope. It is not necessary and\nit does not do anything.'
};
NoPrivateFunctionFatArrows.prototype.lintAST = function(node, astApi) {
this.astApi = astApi;
this.lintNode(node);
@@ -2472,11 +2592,11 @@
NoStandAloneAt.prototype.rule = {
name: 'no_stand_alone_at',
level: 'ignore',
message: '@ must not be used stand alone',
- description: "This rule checks that no stand alone @ are in use, they are\ndiscouraged. Further information in CoffeScript issue <a\nhref=\"https://github.com/jashkenas/coffee-script/issues/1601\">\n#1601</a>"
+ description: 'This rule checks that no stand alone @ are in use, they are\ndiscouraged. Further information in CoffeeScript issue <a\nhref="https://github.com/jashkenas/coffee-script/issues/1601">\n#1601</a>'
};
NoStandAloneAt.prototype.tokens = ['@'];
NoStandAloneAt.prototype.lintToken = function(token, tokenApi) {
@@ -2512,11 +2632,11 @@
NoTabs.prototype.rule = {
name: 'no_tabs',
level: 'error',
message: 'Line contains tab indentation',
- description: "This rule forbids tabs in indentation. Enough said. It is enabled by\ndefault."
+ description: 'This rule forbids tabs in indentation. Enough said. It is enabled by\ndefault.'
};
NoTabs.prototype.lintLine = function(line, lineApi) {
var indentation;
indentation = line.split(indentationRegex)[0];
@@ -2539,19 +2659,24 @@
module.exports = NoThis = (function() {
function NoThis() {}
NoThis.prototype.rule = {
name: 'no_this',
- description: 'This rule prohibits \'this\'.\nUse \'@\' instead.',
level: 'ignore',
- message: "Don't use 'this', use '@' instead"
+ message: "Don't use 'this', use '@' instead",
+ description: 'This rule prohibits \'this\'.\nUse \'@\' instead.'
};
NoThis.prototype.tokens = ['THIS'];
NoThis.prototype.lintToken = function(token, tokenApi) {
- return true;
+ var level, nextToken, ref;
+ level = tokenApi.config.no_stand_alone_at.level;
+ nextToken = (ref = tokenApi.peek(1)) != null ? ref[0] : void 0;
+ if (!(level !== 'ignore' && nextToken !== '.')) {
+ return true;
+ }
};
return NoThis;
})();
@@ -2566,11 +2691,11 @@
NoThrowingStrings.prototype.rule = {
name: 'no_throwing_strings',
level: 'error',
message: 'Throwing strings is forbidden',
- description: "This rule forbids throwing string literals or interpolations. While\nJavaScript (and CoffeeScript by extension) allow any expression to\nbe thrown, it is best to only throw <a\nhref=\"https://developer.mozilla.org\n/en/JavaScript/Reference/Global_Objects/Error\"> Error</a> objects,\nbecause they contain valuable debugging information like the stack\ntrace. Because of JavaScript's dynamic nature, CoffeeLint cannot\nensure you are always throwing instances of <tt>Error</tt>. It will\nonly catch the simple but real case of throwing literal strings.\n<pre>\n<code># CoffeeLint will catch this:\nthrow \"i made a boo boo\"\n\n# ... but not this:\nthrow getSomeString()\n</code>\n</pre>\nThis rule is enabled by default."
+ description: 'This rule forbids throwing string literals or interpolations. While\nJavaScript (and CoffeeScript by extension) allow any expression to\nbe thrown, it is best to only throw <a\nhref="https://developer.mozilla.org\n/en/JavaScript/Reference/Global_Objects/Error"> Error</a> objects,\nbecause they contain valuable debugging information like the stack\ntrace. Because of JavaScript\'s dynamic nature, CoffeeLint cannot\nensure you are always throwing instances of <tt>Error</tt>. It will\nonly catch the simple but real case of throwing literal strings.\n<pre>\n<code># CoffeeLint will catch this:\nthrow "i made a boo boo"\n\n# ... but not this:\nthrow getSomeString()\n</code>\n</pre>\nThis rule is enabled by default.'
};
NoThrowingStrings.prototype.tokens = ['THROW'];
NoThrowingStrings.prototype.lintToken = function(token, tokenApi) {
@@ -2600,11 +2725,11 @@
NoTrailingSemicolons.prototype.rule = {
name: 'no_trailing_semicolons',
level: 'error',
message: 'Line contains a trailing semicolon',
- description: "This rule prohibits trailing semicolons, since they are needless\ncruft in CoffeeScript.\n<pre>\n<code># This semicolon is meaningful.\nx = '1234'; console.log(x)\n\n# This semicolon is redundant.\nalert('end of line');\n</code>\n</pre>\nTrailing semicolons are forbidden by default."
+ description: 'This rule prohibits trailing semicolons, since they are needless\ncruft in CoffeeScript.\n<pre>\n<code># This semicolon is meaningful.\nx = \'1234\'; console.log(x)\n\n# This semicolon is redundant.\nalert(\'end of line\');\n</code>\n</pre>\nTrailing semicolons are forbidden by default.'
};
NoTrailingSemicolons.prototype.lintLine = function(line, lineApi) {
var endPos, first, hasNewLine, hasSemicolon, i, last, lineTokens, newLine, ref, ref1, startCounter, startPos, stopTokens, tokenLen;
lineTokens = lineApi.getLineTokens();
@@ -2655,11 +2780,11 @@
name: 'no_trailing_whitespace',
level: 'error',
message: 'Line ends with trailing whitespace',
allowed_in_comments: false,
allowed_in_empty_lines: true,
- description: "This rule forbids trailing whitespace in your code, since it is\nneedless cruft. It is enabled by default."
+ description: 'This rule forbids trailing whitespace in your code, since it is\nneedless cruft. It is enabled by default.'
};
NoTrailingWhitespace.prototype.lintLine = function(line, lineApi) {
var i, len, ref, ref1, ref2, str, token, tokens;
if (!((ref = lineApi.config['no_trailing_whitespace']) != null ? ref.allowed_in_empty_lines : void 0)) {
@@ -2779,11 +2904,11 @@
NoUnnecessaryFatArrows.prototype.rule = {
name: 'no_unnecessary_fat_arrows',
level: 'warn',
message: 'Unnecessary fat arrow',
- description: "Disallows defining functions with fat arrows when `this`\nis not used within the function."
+ description: 'Disallows defining functions with fat arrows when `this`\nis not used within the function.'
};
NoUnnecessaryFatArrows.prototype.lintAST = function(node, astApi) {
this.astApi = astApi;
this.lintNode(node);
@@ -2859,11 +2984,11 @@
NonEmptyConstructorNeedsParens.prototype.rule = {
name: 'non_empty_constructor_needs_parens',
level: 'ignore',
message: 'Invoking a constructor without parens and with arguments',
- description: "Requires constructors with parameters to include the parens"
+ description: 'Requires constructors with parameters to include the parens'
};
NonEmptyConstructorNeedsParens.prototype.handleExpectedCallStart = function(expectedCallStart) {
if (expectedCallStart[0] === 'CALL_START' && expectedCallStart.generated) {
return true;
@@ -2882,14 +3007,14 @@
module.exports = PreferEnglishOperator = (function() {
function PreferEnglishOperator() {}
PreferEnglishOperator.prototype.rule = {
name: 'prefer_english_operator',
- description: 'This rule prohibits &&, ||, ==, != and !.\nUse and, or, is, isnt, and not instead.\n!! for converting to a boolean is ignored.',
level: 'ignore',
+ message: 'Don\'t use &&, ||, ==, !=, or !',
doubleNotLevel: 'ignore',
- message: 'Don\'t use &&, ||, ==, !=, or !'
+ description: 'This rule prohibits &&, ||, ==, != and !.\nUse and, or, is, isnt, and not instead.\n!! for converting to a boolean is ignored.'
};
PreferEnglishOperator.prototype.tokens = ['COMPARE', 'UNARY_MATH', 'LOGIC'];
PreferEnglishOperator.prototype.lintToken = function(token, tokenApi) {
@@ -2945,11 +3070,11 @@
module.exports = SpaceOperators = (function() {
SpaceOperators.prototype.rule = {
name: 'space_operators',
level: 'ignore',
message: 'Operators must be spaced properly',
- description: "This rule enforces that operators have space around them."
+ description: 'This rule enforces that operators have spaces around them.'
};
SpaceOperators.prototype.tokens = ['+', '-', '=', '**', 'MATH', 'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'STRING_START', 'STRING_END', 'CALL_START', 'CALL_END'];
function SpaceOperators() {
@@ -3051,13 +3176,13 @@
var SpacingAfterComma;
module.exports = SpacingAfterComma = (function() {
SpacingAfterComma.prototype.rule = {
name: 'spacing_after_comma',
- description: 'This rule requires a space after commas.',
level: 'ignore',
- message: 'Spaces are required after commas'
+ message: 'a space is required after commas',
+ description: 'This rule checks to make sure you have a space after commas.'
};
SpacingAfterComma.prototype.tokens = [',', 'REGEX_START', 'REGEX_END'];
function SpacingAfterComma() {
@@ -3074,13 +3199,11 @@
if (type === 'REGEX_END') {
this.inRegex = false;
return;
}
if (!(token.spaced || token.newLine || token.generated || this.isRegexFlag(token, tokenApi))) {
- return {
- context: token[1]
- };
+ return true;
}
};
SpacingAfterComma.prototype.isRegexFlag = function(token, tokenApi) {
var maybeEnd;
@@ -3105,10 +3228,10 @@
TransformMessesUpLineNumbers.prototype.rule = {
name: 'transform_messes_up_line_numbers',
level: 'warn',
message: 'Transforming source messes up line numbers',
- description: "This rule detects when changes are made by transform function,\nand warns that line numbers are probably incorrect."
+ description: 'This rule detects when changes are made by transform function,\nand warns that line numbers are probably incorrect.'
};
TransformMessesUpLineNumbers.prototype.tokens = [];
TransformMessesUpLineNumbers.prototype.lintToken = function(token, tokenApi) {};
\ No newline at end of file