From 2766e18b21bae59747d1ed585c2d4abbf71991be Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sun, 29 Dec 2013 12:40:26 -0500 Subject: [PATCH] Add validateQuoteMarks rule, closes #106 --- README.md | 19 ++++++++ lib/rules/validate-quote-marks.js | 42 +++++++++++++++++ lib/string-checker.js | 1 + test/test.validate-quote-marks.js | 77 +++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 lib/rules/validate-quote-marks.js create mode 100644 test/test.validate-quote-marks.js diff --git a/README.md b/README.md index 0c8132c1b..c64b9b590 100644 --- a/README.md +++ b/README.md @@ -524,6 +524,25 @@ Example configuration: */ "validateLineBreaks": "LF", + /* + Option: validateQuoteMarks + Possible values: "\"", "'", true + Requires all quote marks to be either the supplied value, or consistent if "true" + + Valid example for mode "\"" or mode "true": + + var x = "x"; + + Valid example for mode "'" or mode "true": + + var x = 'x'; + + Invalid example for mode "true": + + var x = "x", y = 'y'; + */ + "validateQuoteMarks": "\"", + /* Option: disallowKeywordsOnNewLine Disallows placing keywords on a new line. diff --git a/lib/rules/validate-quote-marks.js b/lib/rules/validate-quote-marks.js new file mode 100644 index 000000000..dc460c20b --- /dev/null +++ b/lib/rules/validate-quote-marks.js @@ -0,0 +1,42 @@ +var assert = require('assert'); + +module.exports = function() {}; + +module.exports.prototype = { + + configure: function(allowedQuoteMark) { + assert( + allowedQuoteMark === '"' || allowedQuoteMark === '\'' || allowedQuoteMark === true, + 'validateQuoteMarks option requires \'"\', "\'", or boolean true' + ); + + this._allowedQuoteMark = allowedQuoteMark; + }, + + getOptionName: function () { + return 'validateQuoteMarks'; + }, + + check: function(file, errors) { + var tokens = file.getTokens(); + var allowedQuoteMark = this._allowedQuoteMark; + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + if (token.type === 'String') { + if (allowedQuoteMark === true) { + allowedQuoteMark = token.value[0]; + } + + if (token.value[0] !== allowedQuoteMark) { + errors.add( + 'Invalid quote mark found', + token.loc.start.line, + token.loc.start.column + ); + } + } + } + } + +}; diff --git a/lib/string-checker.js b/lib/string-checker.js index aae1b5573..1a39c2c2a 100644 --- a/lib/string-checker.js +++ b/lib/string-checker.js @@ -47,6 +47,7 @@ StringChecker.prototype = { this.registerRule(new (require('./rules/disallow-keywords'))()); this.registerRule(new (require('./rules/disallow-multiple-line-breaks'))()); this.registerRule(new (require('./rules/validate-line-breaks'))()); + this.registerRule(new (require('./rules/validate-quote-marks'))()); this.registerRule(new (require('./rules/require-keywords-on-new-line'))()); this.registerRule(new (require('./rules/disallow-keywords-on-new-line'))()); this.registerRule(new (require('./rules/require-line-feed-at-file-end'))()); diff --git a/test/test.validate-quote-marks.js b/test/test.validate-quote-marks.js new file mode 100644 index 000000000..2e3a67a05 --- /dev/null +++ b/test/test.validate-quote-marks.js @@ -0,0 +1,77 @@ +var Checker = require('../lib/checker'); +var assert = require('assert'); + +describe('rules/validate-quote-marks', function() { + var checker; + + beforeEach(function() { + checker = new Checker(); + checker.registerDefaultRules(); + }); + + describe('option value \' ', function() { + beforeEach(function() { + checker.configure({ validateQuoteMarks: '\'' }); + }); + + it('should report double quotes in strings', function() { + assert(checker.checkString('var x = "x";').getErrorCount() === 1); + }); + + it('should not report single quotes in strings', function() { + assert(checker.checkString('var x = \'x\';').isEmpty()); + }); + + it('should not report double quotes values in single quotes strings', function() { + assert(checker.checkString('var x = \'"x"\';').isEmpty()); + }); + + it('should not report double quotes in comments', function() { + assert(checker.checkString('var x = \'x\'; /*"y"*/').isEmpty()); + }); + }); + + describe('option value " ', function() { + beforeEach(function() { + checker.configure({ validateQuoteMarks: '"' }); + }); + + it('should report single quotes in strings', function() { + assert(checker.checkString('var x = \'x\';').getErrorCount() === 1); + }); + + it('should not report double quotes in strings', function() { + assert(checker.checkString('var x = "x";').isEmpty()); + }); + + it('should not report single quotes values in double quotes strings', function() { + assert(checker.checkString('var x = "\'x\'";').isEmpty()); + }); + + it('should not report single quotes in comments', function() { + assert(checker.checkString('var x = "x"; /*\'y\'*/').isEmpty()); + }); + }); + + describe('option value true ', function() { + beforeEach(function() { + checker.configure({ validateQuoteMarks: true }); + }); + + it('should report inconsistent quotes in strings', function() { + assert(checker.checkString('var x = \'x\', y = "y";').getErrorCount() === 1); + }); + + it('should not report consistent single quotes in strings', function() { + assert(checker.checkString('var x = \'x\', y = \'y\';').isEmpty()); + }); + + it('should not report consistent double quotes in strings', function() { + assert(checker.checkString('var x = "x", y = "y";').isEmpty()); + }); + + it('should not report inconsistent quotes in comments', function() { + assert(checker.checkString('var x = "x", y = "y"; /*\'y\'*/').isEmpty()); + }); + }); +});