summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/no-multi-spaces.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/lib/rules/no-multi-spaces.js')
-rw-r--r--tools/eslint/lib/rules/no-multi-spaces.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js
new file mode 100644
index 0000000000..9e247c1533
--- /dev/null
+++ b/tools/eslint/lib/rules/no-multi-spaces.js
@@ -0,0 +1,101 @@
+/**
+ * @fileoverview Disallow use of multiple spaces.
+ * @author Nicholas C. Zakas
+ * @copyright 2015 Brandon Mills. All rights reserved.
+ * @copyright 2015 Nicholas C. Zakas. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ // the index of the last comment that was checked
+ var exceptions = { "Property": true },
+ hasExceptions = true,
+ options = context.options[0],
+ lastCommentIndex = 0;
+
+ if (options && options.exceptions) {
+ Object.keys(options.exceptions).forEach(function (key) {
+ if (options.exceptions[key]) {
+ exceptions[key] = true;
+ } else {
+ delete exceptions[key];
+ }
+ });
+ hasExceptions = Object.keys(exceptions).length > 0;
+ }
+
+ /**
+ * Determines if a given source index is in a comment or not by checking
+ * the index against the comment range. Since the check goes straight
+ * through the file, once an index is passed a certain comment, we can
+ * go to the next comment to check that.
+ * @param {int} index The source index to check.
+ * @param {ASTNode[]} comments An array of comment nodes.
+ * @returns {boolean} True if the index is within a comment, false if not.
+ * @private
+ */
+ function isIndexInComment(index, comments) {
+
+ var comment;
+
+ while (lastCommentIndex < comments.length) {
+
+ comment = comments[lastCommentIndex];
+
+ if (comment.range[0] <= index && index < comment.range[1]) {
+ return true;
+ } else if (index > comment.range[1]) {
+ lastCommentIndex++;
+ } else {
+ break;
+ }
+
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "Program": function() {
+
+ var source = context.getSource(),
+ allComments = context.getAllComments(),
+ pattern = /[^\n\r\u2028\u2029 ] {2,}/g, // note: repeating space
+ token,
+ parent;
+
+ while (pattern.test(source)) {
+
+ // do not flag anything inside of comments
+ if (!isIndexInComment(pattern.lastIndex, allComments)) {
+
+ token = context.getTokenByRangeStart(pattern.lastIndex);
+
+ if (token) {
+ if (hasExceptions) {
+ parent = context.getNodeByRangeIndex(pattern.lastIndex - 1);
+ }
+
+ if (!parent || !exceptions[parent.type]) {
+ context.report(token, token.loc.start,
+ "Multiple spaces found before '{{value}}'.",
+ { value: token.value });
+ }
+ }
+
+ }
+ }
+ }
+ };
+
+};