UNPKG

@coffeelint/cli

Version:
86 lines (75 loc) 2.54 kB
(function() { var DuplicateKey; module.exports = DuplicateKey = (function() { class DuplicateKey { constructor() { this.braceScopes = []; // A stack tracking keys defined in nexted scopes. } lintToken([type], tokenApi) { if (type === '{' || type === '}') { this.lintBrace(...arguments); return void 0; } if (type === 'PROPERTY' || type === 'STRING') { return this.lintIdentifier(...arguments); } } lintIdentifier(token, tokenApi) { var key, m, nextToken, previousToken; key = token[1]; if (this.currentScope == null) { // Class names might not be in a scope return null; } nextToken = tokenApi.peek(1); if (nextToken[1] !== ':') { // Exit if this identifier isn't being assigned. A and B // are identifiers, but only A should be examined: // A = B return null; } previousToken = tokenApi.peek(-1); if (previousToken[0] === '@') { // Assigning "@something" and "something" are not the same thing key = `@${key}`; } if (m = key.match(/^(["'])(.*)\1$/)) { // Normalize property, "property", and 'property' key = m[2]; } // Added a prefix to not interfere with things like "constructor". key = `identifier-${key}`; if (this.currentScope[key]) { return {token}; } else { this.currentScope[key] = token; return null; } } lintBrace(token) { if (token[0] === '{') { if (this.currentScope != null) { this.braceScopes.push(this.currentScope); } this.currentScope = {}; } else { this.currentScope = this.braceScopes.pop(); } return null; } }; DuplicateKey.prototype.rule = { // I don't know of any legitimate reason to define duplicate keys in an // object. It seems to always be a mistake, it's also a syntax error in // strict mode. // See https://jslinterrors.com/duplicate-key-a/ type: 'problem', name: 'duplicate_key', level: 'error', message: 'Duplicate key defined in object or class', description: `Prevents defining duplicate keys in object literals and classes` }; DuplicateKey.prototype.tokens = ['PROPERTY', 'STRING', '{', '}']; return DuplicateKey; }).call(this); }).call(this);