From fb356249331c0c7b598dfb6236db3c91825f993d Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Mon, 26 Nov 2018 09:18:00 +0900 Subject: [PATCH 01/11] add core rule wrapper --- .../consistent-docs-description.js | 14 +++-- eslint-internal-rules/no-invalid-meta.js | 11 ++-- lib/utils/index.js | 62 +++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/eslint-internal-rules/consistent-docs-description.js b/eslint-internal-rules/consistent-docs-description.js index 42e5970a5..f93149e78 100644 --- a/eslint-internal-rules/consistent-docs-description.js +++ b/eslint-internal-rules/consistent-docs-description.js @@ -23,14 +23,15 @@ const ALLOWED_FIRST_WORDS = [ * @returns {ASTNode} The Property node or null if not found. */ function getPropertyFromObject (property, node) { - const properties = node.properties + if (node && node.type === 'ObjectExpression') { + const properties = node.properties - for (let i = 0; i < properties.length; i++) { - if (properties[i].key.name === property) { - return properties[i] + for (let i = 0; i < properties.length; i++) { + if (properties[i].key.name === property) { + return properties[i] + } } } - return null } @@ -128,7 +129,8 @@ module.exports = { node.right && node.left.type === 'MemberExpression' && node.left.object.name === 'module' && - node.left.property.name === 'exports') { + node.left.property.name === 'exports' && + node.right.type === 'ObjectExpression') { checkMetaDocsDescription(context, node.right) } } diff --git a/eslint-internal-rules/no-invalid-meta.js b/eslint-internal-rules/no-invalid-meta.js index af4afd8e3..bd96f4f74 100644 --- a/eslint-internal-rules/no-invalid-meta.js +++ b/eslint-internal-rules/no-invalid-meta.js @@ -17,14 +17,15 @@ * @returns {ASTNode} The Property node or null if not found. */ function getPropertyFromObject (property, node) { - const properties = node.properties + if (node && node.type === 'ObjectExpression') { + const properties = node.properties - for (let i = 0; i < properties.length; i++) { - if (properties[i].key.name === property) { - return properties[i] + for (let i = 0; i < properties.length; i++) { + if (properties[i].key.name === property) { + return properties[i] + } } } - return null } diff --git a/lib/utils/index.js b/lib/utils/index.js index cf58a0fce..8450456bf 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -15,6 +15,26 @@ const VOID_ELEMENT_NAMES = new Set(require('./void-elements.json')) const assert = require('assert') const vueEslintParser = require('vue-eslint-parser') +/** + * Wrap the rule context object to override methods which access to tokens (such as getTokenAfter). + * @param {RuleContext} context The rule context object. + * @param {TokenStore} tokenStore The token store object for template. + */ +function wrapContextToOverrideTokenMethods (context, tokenStore) { + const sourceCode = new Proxy(context.getSourceCode(), { + get (object, key) { + return key in tokenStore ? tokenStore[key] : object[key] + } + }) + + return { + __proto__: context, + getSourceCode () { + return sourceCode + } + } +} + // ------------------------------------------------------------------------------ // Exports // ------------------------------------------------------------------------------ @@ -41,6 +61,48 @@ module.exports = { return context.parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor) }, + /** + * Wrap a given core rule to apply it to Vue.js template. + * @param {Rule} coreRule The core rule implementation to wrap. + * @param {string|undefined} category The category of this rule. + * @returns {Rule} The wrapped rule implementation. + */ + wrapCoreRule (coreRule, category) { + return { + create (context) { + const tokenStore = + context.parserServices.getTemplateBodyTokenStore && + context.parserServices.getTemplateBodyTokenStore() + + // The `context.getSourceCode()` cannot access the tokens of templates. + // So override the methods which access to tokens by the `tokenStore`. + if (tokenStore) { + context = wrapContextToOverrideTokenMethods(context, tokenStore) + } + + // Move `Program` handlers to `VElement[parent.type!='VElement']` + const handlers = coreRule.create(context) + if (handlers.Program) { + handlers["VElement[parent.type!='VElement']"] = handlers.Program + delete handlers.Program + } + if (handlers['Program:exit']) { + handlers["VElement[parent.type!='VElement']:exit"] = handlers['Program:exit'] + delete handlers['Program:exit'] + } + + // Apply the handlers to templates. + return module.exports.defineTemplateBodyVisitor(context, handlers) + }, + + meta: Object.assign( + {}, + coreRule.meta, + { docs: Object.assign({}, coreRule.meta.docs, { category }) } + ) + } + }, + /** * Check whether the given node is the root element or not. * @param {ASTNode} node The element node to check. From 6a1ef078c98c35517175f145f58d5f3bd976ce9f Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Mon, 26 Nov 2018 09:25:56 +0900 Subject: [PATCH 02/11] add array-bracket-spacing --- docs/rules/array-bracket-spacing.md | 11 ++++ lib/rules/array-bracket-spacing.js | 9 +++ tests/lib/rules/array-bracket-spacing.js | 79 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 docs/rules/array-bracket-spacing.md create mode 100644 lib/rules/array-bracket-spacing.js create mode 100644 tests/lib/rules/array-bracket-spacing.js diff --git a/docs/rules/array-bracket-spacing.md b/docs/rules/array-bracket-spacing.md new file mode 100644 index 000000000..0bf144402 --- /dev/null +++ b/docs/rules/array-bracket-spacing.md @@ -0,0 +1,11 @@ +# enforce consistent spacing inside array brackets (vue/array-bracket-spacing) + +- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule. + +This rule is the same rule as core [array-bracket-spacing] rule but it applies to the expressions in `