From a21247bdbc3bb2ab3a33e34191e42a28324b6988 Mon Sep 17 00:00:00 2001 From: Christian Wygoda Date: Thu, 8 Jan 2015 18:48:44 +0100 Subject: [PATCH] Add ignore capability Comments /* csslint ignore:start */ and /* csslint ignore:end */ will exclude the lines in between. Linting is still done, but any errors are not reported. This aims to fix CSSLint/csslint#558. --- src/core/CSSLint.js | 29 +++++++++++++++++++++++++++-- src/core/Reporter.js | 24 +++++++++++++++++++++++- tests/core/CSSLint.js | 29 +++++++++++++++++++++++++++++ tests/core/Reporter.js | 8 ++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/core/CSSLint.js b/src/core/CSSLint.js index 4e459eb1..bb013b77 100644 --- a/src/core/CSSLint.js +++ b/src/core/CSSLint.js @@ -178,6 +178,7 @@ var CSSLint = (function() { reporter, lines, allow = {}, + ignore = [], report, parser = new parserlib.css.Parser({ starHack: true, ieFilters: true, underscoreHack: true, strict: false }); @@ -201,6 +202,29 @@ var CSSLint = (function() { } }); + var ignoreStart = null, + ignoreEnd = null; + CSSLint.Util.forEach(lines, function (line, lineno) { + // Keep oldest, "unclosest" ignore:start + if(null === ignoreStart && line.match(/\/\*[ \t]*csslint[ \t]+ignore:start[ \t]*\*\//i)) { + ignoreStart = lineno; + } + + if(line.match(/\/\*[ \t]*csslint[ \t]+ignore:end[ \t]*\*\//i)) { + ignoreEnd = lineno; + } + + if(null !== ignoreStart && null !== ignoreEnd) { + ignore.push([ignoreStart, ignoreEnd]); + ignoreStart = ignoreEnd = null; + } + }); + + // Close remaining ignore block, if any + if(null !== ignoreStart) { + ignore.push([ignoreStart, lines.length]); + } + if (!ruleset) { ruleset = this.getRuleset(); } @@ -211,7 +235,7 @@ var CSSLint = (function() { ruleset = applyEmbeddedRuleset(text, ruleset); } - reporter = new Reporter(lines, ruleset, allow); + reporter = new Reporter(lines, ruleset, allow, ignore); ruleset.errors = 2; //always report parsing errors as errors for (i in ruleset) { @@ -234,7 +258,8 @@ var CSSLint = (function() { messages : reporter.messages, stats : reporter.stats, ruleset : reporter.ruleset, - allow : reporter.allow + allow : reporter.allow, + ignore : reporter.ignore }; //sort by line numbers, rollups at the bottom diff --git a/src/core/Reporter.js b/src/core/Reporter.js index ff2abeb7..e81dbe59 100644 --- a/src/core/Reporter.js +++ b/src/core/Reporter.js @@ -6,8 +6,10 @@ * @param {String[]} lines The text lines of the source. * @param {Object} ruleset The set of rules to work with, including if * they are errors or warnings. + * @param {Object} explicitly allowed lines + * @param {[][]} ingore list of line ranges to be ignored */ -function Reporter(lines, ruleset, allow) { +function Reporter(lines, ruleset, allow, ignore) { "use strict"; /** @@ -49,6 +51,16 @@ function Reporter(lines, ruleset, allow) { if(!this.allow) { this.allow = {}; } + + /** + * Linesets not to include in the report. + * @property ignore + * @type [][] + */ + this.ignore = ignore; + if(!this.ignore) { + this.ignore = []; + } } Reporter.prototype = { @@ -106,6 +118,16 @@ Reporter.prototype = { return; } + var ignore = false; + CSSLint.Util.forEach(this.ignore, function (range) { + if(range[0] <= line && line <= range[1]) { + ignore = true; + } + }); + if(ignore) { + return; + } + this.messages.push({ type : this.ruleset[rule.id] === 2 ? "error" : "warning", line : line, diff --git a/tests/core/CSSLint.js b/tests/core/CSSLint.js index 2642a28b..a3a4673a 100644 --- a/tests/core/CSSLint.js +++ b/tests/core/CSSLint.js @@ -69,6 +69,35 @@ Assert.isTrue(report.allow["2"].hasOwnProperty("box-sizing")); Assert.isTrue(report.allow.hasOwnProperty("4")); Assert.isTrue(report.allow["4"].hasOwnProperty("box-model")); + }, + + "Full ignore blocks should be captured": function(){ + var report = CSSLint.verify("/* csslint ignore:start */\n\n/* csslint ignore:end */"); + Assert.areEqual(1, report.ignore.length); + Assert.areEqual(0, report.ignore[0][0]); + Assert.areEqual(2, report.ignore[0][1]); + }, + + "Whitespace should be no problem inside ignore comments": function(){ + var report = CSSLint.verify("/* csslint ignore:start */\n\n/* csslint ignore:end */,\n/*csslint ignore:start*/\n/*csslint ignore:end*/"); + Assert.areEqual(2, report.ignore.length); + Assert.areEqual(0, report.ignore[0][0]); + Assert.areEqual(2, report.ignore[0][1]); + Assert.areEqual(3, report.ignore[1][0]); + Assert.areEqual(4, report.ignore[1][1]); + }, + + "Ignore blocks should be autoclosed": function(){ + var report = CSSLint.verify("/* csslint ignore:start */\n\n"); + Assert.areEqual(1, report.ignore.length); + Assert.areEqual(0, report.ignore[0][0]); + Assert.areEqual(3, report.ignore[0][1]); + }, + + "Restarting ignore should be harmless": function(){ + var report = CSSLint.verify("/* csslint ignore:start */\n/* csslint ignore:start */\n"); + Assert.areEqual(1, report.ignore.length); + Assert.areEqual(0, report.ignore[0][0]); } })); diff --git a/tests/core/Reporter.js b/tests/core/Reporter.js index 9fc83a0c..042c8197 100644 --- a/tests/core/Reporter.js +++ b/tests/core/Reporter.js @@ -52,6 +52,14 @@ reporter.report("Bar", 3, 1, { id: "fake-rule2" }); Assert.areEqual(0, reporter.messages.length); + }, + + "Ignores should step over a report in their range": function(){ + var reporter = new CSSLint._Reporter([], { "fake-rule": 1}, {}, [[1,3]]); + reporter.report("Foo", 2, 1, { id: "fake-rule" }); + reporter.report("Bar", 5, 1, { id: "fake-rule" }); + + Assert.areEqual(1, reporter.messages.length); } }));