UNPKG

@coffeelint/cli

Version:
152 lines (136 loc) 4.91 kB
(function() { var SpaceOperators, indexOf = [].indexOf; module.exports = SpaceOperators = (function() { class SpaceOperators { constructor() { this.callTokens = []; // A stack tracking the call token pairs. this.parenTokens = []; // A stack tracking the parens token pairs. this.interpolationLevel = 0; this.isParam = 0; } lintToken(token, tokenApi) { var rest, type; [type, ...rest] = token; // These just keep track of state if (type === 'CALL_START' || type === 'CALL_END') { this.trackCall(token, tokenApi); return; } if (type === 'PARAM_START' || type === 'PARAM_END') { this.trackParams(token, tokenApi); return; } if (type === 'STRING_START' || type === 'STRING_END') { this.trackParens(token, tokenApi); return; } // These may return errors if (type === '+' || type === '-') { return this.lintPlus(token, tokenApi); } else { return this.lintMath(token, tokenApi); } } lintPlus(token, tokenApi) { var isUnary, notFirstToken, p, ref, unaries; // We can't check this inside of interpolations right now, because the // plusses used for the string type co-ercion are marked not spaced. if (this.isInInterpolation() || this.isInExtendedRegex()) { return null; } p = tokenApi.peek(-1); unaries = ['TERMINATOR', '(', '=', '-', '+', ',', 'CALL_START', 'INDEX_START', '..', '...', 'COMPARE', 'IF', 'THROW', '&', '^', '|', '&&', '||', 'POST_IF', ':', '[', 'INDENT', 'COMPOUND_ASSIGN', 'RETURN', 'MATH', 'BY', 'LEADING_WHEN']; isUnary = !p ? false : (ref = p[0], indexOf.call(unaries, ref) >= 0); notFirstToken = p || (token.spaced != null) || token.newLine; if (notFirstToken && ((isUnary && (token.spaced != null)) || (!isUnary && !token.newLine && (!token.spaced || (p && !p.spaced))))) { return { token, context: token[1] }; } else { return null; } } lintMath(token, tokenApi) { var default_parameters, p; default_parameters = tokenApi.config[this.rule.name].default_parameters; p = tokenApi.peek(-1); if (!default_parameters && this.isParam > 0 && token[0] === '=') { if (token.spaced || (p && p.spaced)) { return { token, context: token[1] }; } else { return null; } } else if (!token.newLine && (!token.spaced || (p && !p.spaced))) { return { token, context: token[1] }; } else { return null; } } isInExtendedRegex() { var i, len, ref, t; ref = this.callTokens; for (i = 0, len = ref.length; i < len; i++) { t = ref[i]; if (t.isRegex) { return true; } } return false; } isInInterpolation() { return this.interpolationLevel > 0; } trackCall(token, tokenApi) { var p; if (token[0] === 'CALL_START') { p = tokenApi.peek(-1); // Track regex calls, to know (approximately) if we're in an // extended regex. token.isRegex = p && p[0] === 'IDENTIFIER' && p[1] === 'RegExp'; this.callTokens.push(token); } else { this.callTokens.pop(); } return null; } trackParens(token, tokenApi) { if (token[0] === 'STRING_START') { this.interpolationLevel += 1; } else if (token[0] === 'STRING_END') { this.interpolationLevel -= 1; } // We're not linting, just tracking interpolations. return null; } trackParams(token, tokenApi) { if (token[0] === 'PARAM_START') { this.isParam++; } else if (token[0] === 'PARAM_END') { this.isParam--; } // We're not linting, just tracking function params. return null; } }; SpaceOperators.prototype.rule = { type: 'style', name: 'space_operators', level: 'ignore', message: 'Operators must be spaced properly', description: `This rule enforces that operators have space around them. Optionally, you can set \`default_parameters\` to \`false\` to require no space around \`=\` when used to define default paramaters.`, default_parameters: true }; SpaceOperators.prototype.tokens = ['+', '-', '=', '**', 'MATH', 'COMPARE', '&', '^', '|', '&&', '||', 'COMPOUND_ASSIGN', 'STRING_START', 'STRING_END', 'CALL_START', 'CALL_END', 'PARAM_START', 'PARAM_END']; return SpaceOperators; }).call(this); }).call(this);