1 |
|
2 |
|
3 |
|
4 |
|
5 | "use strict";
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | module.exports = function(context) {
|
12 |
|
13 | var OPERATORS = [
|
14 | "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in",
|
15 | "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=",
|
16 | "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=",
|
17 | "?", ":", ","
|
18 | ];
|
19 |
|
20 | function isSpaced(left, right) {
|
21 | var op, tokens = context.getTokens({range: [left.range[1], right.range[0]]}, 1, 1);
|
22 | for(var i = 1, l = tokens.length - 1; i < l; ++i) {
|
23 | op = tokens[i];
|
24 | if(
|
25 | op.type === "Punctuator" &&
|
26 | OPERATORS.indexOf(op.value) >= 0 &&
|
27 | (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
|
28 | ) {
|
29 | return false;
|
30 | }
|
31 | }
|
32 | return true;
|
33 | }
|
34 |
|
35 | function isRightSpaced(left, right) {
|
36 | var op, tokens = context.getTokens({range: [left.range[1], right.range[0]]}, 1, 1);
|
37 | for(var i = 1, l = tokens.length - 1; i < l; ++i) {
|
38 | op = tokens[i];
|
39 | if(
|
40 | op.type === "Punctuator" &&
|
41 | OPERATORS.indexOf(op.value) >= 0 &&
|
42 | op.range[1] >= tokens[i + 1].range[0]
|
43 | ) {
|
44 | return false;
|
45 | }
|
46 | }
|
47 | return true;
|
48 | }
|
49 |
|
50 | function report(node) {
|
51 | context.report(node, "Infix operators must be spaced.");
|
52 | }
|
53 |
|
54 | function checkBinary(node) {
|
55 | if(!isSpaced(node.left, node.right)) { report(node); }
|
56 | }
|
57 |
|
58 | function checkSequence(node) {
|
59 | for(var i = 0, l = node.expressions.length - 1; i < l; ++i) {
|
60 | if(!isRightSpaced(node.expressions[i], node.expressions[i + 1])) {
|
61 | report(node);
|
62 | break;
|
63 | }
|
64 | }
|
65 | }
|
66 |
|
67 | function checkConditional(node) {
|
68 | if(!isSpaced(node.test, node.consequent) || !isSpaced(node.consequent, node.alternate)) {
|
69 | report(node);
|
70 | }
|
71 | }
|
72 |
|
73 | function checkVar(node) {
|
74 | if(node.init && !isSpaced(node.id, node.init)) {
|
75 | report(node);
|
76 | }
|
77 | }
|
78 |
|
79 | return {
|
80 | "AssignmentExpression": checkBinary,
|
81 | "BinaryExpression": checkBinary,
|
82 | "LogicalExpression": checkBinary,
|
83 | "ConditionalExpression": checkConditional,
|
84 | "SequenceExpression": checkSequence,
|
85 | "VariableDeclarator": checkVar
|
86 | };
|
87 |
|
88 | };
|