From 2eed7fbb4f2bcac09160e9d236fd2319b0881b26 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 21 Jan 2017 02:04:02 -0800 Subject: [PATCH] [Breaking] drop node < 4 support. Also, require template literals instead of concatenation, and auto fix. --- .eslintrc | 17 ++++++---- .travis.yml | 4 --- index.js | 2 +- lib/rules/forbid-component-props.js | 2 +- lib/rules/forbid-prop-types.js | 2 +- lib/rules/jsx-closing-bracket-location.js | 5 ++- lib/rules/jsx-curly-spacing.js | 12 +++---- lib/rules/jsx-filename-extension.js | 2 +- lib/rules/jsx-handler-names.js | 9 +++-- lib/rules/jsx-indent-props.js | 4 +-- lib/rules/jsx-indent.js | 4 +-- lib/rules/jsx-max-props-per-line.js | 2 +- lib/rules/jsx-no-undef.js | 2 +- lib/rules/jsx-pascal-case.js | 2 +- lib/rules/jsx-wrap-multilines.js | 2 +- lib/rules/no-children-prop.js | 4 +-- lib/rules/no-danger-with-children.js | 9 +++-- lib/rules/no-deprecated.js | 34 +++++++++---------- lib/rules/no-render-return-value.js | 2 +- lib/rules/no-unused-prop-types.js | 5 ++- lib/rules/prop-types.js | 2 +- lib/rules/require-default-props.js | 5 ++- lib/rules/require-extension.js | 2 +- lib/rules/sort-prop-types.js | 4 +-- lib/rules/style-prop-object.js | 5 ++- lib/util/Components.js | 6 ++-- lib/util/pragma.js | 4 +-- lib/util/variable.js | 4 +-- lib/util/version.js | 2 +- package.json | 12 +++---- tests/eslint-compat.js | 12 ------- tests/index.js | 14 ++++---- .../lib/rules/jsx-closing-bracket-location.js | 3 +- tests/lib/rules/jsx-uses-react.js | 7 ++-- tests/lib/rules/jsx-uses-vars.js | 28 +++++++-------- tests/lib/rules/require-default-props.js | 5 ++- tests/lib/rules/style-prop-object.js | 7 ++-- tests/mocha.opts | 1 - tests/setup.js | 3 -- 39 files changed, 108 insertions(+), 143 deletions(-) delete mode 100644 tests/eslint-compat.js delete mode 100644 tests/mocha.opts delete mode 100644 tests/setup.js diff --git a/.eslintrc b/.eslintrc index 0667d9ddb5..b6f0d450fb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,13 +2,12 @@ "env": { "node": true }, + parserOptions: { + ecmaVersion: 2015 + }, ecmaFeatures: { jsx: true }, - "globals": { - }, - "plugins": [ - ], "rules": { // Possible Errors "comma-dangle": [2, "never"], @@ -149,10 +148,16 @@ "wrap-regex": 0, // Legacy "max-depth": 0, - "max-len": [2, 120], + "max-len": [2, 120, { + "ignoreStrings": true, + "ignoreTemplateLiterals": true, + "ignoreComments": true, + }], "max-params": 0, "max-statements": 0, "no-plusplus": 0, - "no-prototype-builtins": 2 + "no-prototype-builtins": 2, + "prefer-template": 2, + "template-curly-spacing": [2, "never"] } } diff --git a/.travis.yml b/.travis.yml index 1f6e191125..8e11eaa334 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,7 @@ node_js: - '6' - '5' - '4' - - 'iojs' - - '0.12' - - '0.10' before_script: - - 'if [ "${TRAVIS_NODE_VERSION}" = "iojs" ] || [ "${TRAVIS_NODE_VERSION}" = "0.12" ] || [ "${TRAVIS_NODE_VERSION}" = "0.10" ]; then npm install eslint@2 babel-eslint@6; fi' after_success: - npm run coveralls matrix: diff --git a/index.js b/index.js index df651dfbd1..2bdba47d3b 100644 --- a/index.js +++ b/index.js @@ -79,7 +79,7 @@ function configureAsError(rules) { if (!has(rules, key)) { continue; } - result['react/' + key] = 2; + result[`react/${key}`] = 2; } return result; } diff --git a/lib/rules/forbid-component-props.js b/lib/rules/forbid-component-props.js index 8d6ba9f9b3..ef3a70d6db 100644 --- a/lib/rules/forbid-component-props.js +++ b/lib/rules/forbid-component-props.js @@ -61,7 +61,7 @@ module.exports = { context.report({ node: node, - message: 'Prop `' + prop + '` is forbidden on Components' + message: `Prop \`${prop}\` is forbidden on Components` }); } }; diff --git a/lib/rules/forbid-prop-types.js b/lib/rules/forbid-prop-types.js index 0a59b1637c..b9cbda2bfe 100644 --- a/lib/rules/forbid-prop-types.js +++ b/lib/rules/forbid-prop-types.js @@ -102,7 +102,7 @@ module.exports = { if (isForbidden(target)) { context.report({ node: declaration, - message: 'Prop type `' + target + '` is forbidden' + message: `Prop type \`${target}\` is forbidden` }); } }); diff --git a/lib/rules/jsx-closing-bracket-location.js b/lib/rules/jsx-closing-bracket-location.js index 67520506cb..b6a5eb0dc3 100644 --- a/lib/rules/jsx-closing-bracket-location.js +++ b/lib/rules/jsx-closing-bracket-location.js @@ -248,8 +248,7 @@ module.exports = { if (correctColumn !== null) { expectedNextLine = tokens.lastProp && (tokens.lastProp.lastLine === tokens.closing.line); - data.details = ' (expected column ' + (correctColumn + 1) + - (expectedNextLine ? ' on the next line)' : ')'); + data.details = ` (expected column ${correctColumn + 1}${expectedNextLine ? ' on the next line)' : ')'}`; } context.report({ @@ -274,7 +273,7 @@ module.exports = { case 'tag-aligned': case 'line-aligned': return fixer.replaceTextRange([cachedLastAttributeEndPos, node.end], - '\n' + getIndentation(tokens, expectedLocation, correctColumn) + closingTag); + `\n${getIndentation(tokens, expectedLocation, correctColumn)}${closingTag}`); default: return true; } diff --git a/lib/rules/jsx-curly-spacing.js b/lib/rules/jsx-curly-spacing.js index 432809de5c..87772d8028 100644 --- a/lib/rules/jsx-curly-spacing.js +++ b/lib/rules/jsx-curly-spacing.js @@ -83,7 +83,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'There should be no newline after \'' + token.value + '\'', + message: `There should be no newline after '${token.value}'`, fix: function(fixer) { var nextToken = sourceCode.getTokenAfter(token); return fixer.replaceTextRange([token.range[1], nextToken.range[0]], spaced ? ' ' : ''); @@ -101,7 +101,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'There should be no newline before \'' + token.value + '\'', + message: `There should be no newline before '${token.value}'`, fix: function(fixer) { var previousToken = sourceCode.getTokenBefore(token); return fixer.replaceTextRange([previousToken.range[1], token.range[0]], spaced ? ' ' : ''); @@ -119,7 +119,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'There should be no space after \'' + token.value + '\'', + message: `There should be no space after '${token.value}'`, fix: function(fixer) { var nextToken = sourceCode.getTokenAfter(token); var leadingComments = sourceCode.getNodeByRangeIndex(nextToken.range[0]).leadingComments; @@ -139,7 +139,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'There should be no space before \'' + token.value + '\'', + message: `There should be no space before '${token.value}'`, fix: function(fixer) { var previousToken = sourceCode.getTokenBefore(token); var trailingComments = sourceCode.getNodeByRangeIndex(previousToken.range[0]).trailingComments; @@ -159,7 +159,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'A space is required after \'' + token.value + '\'', + message: `A space is required after '${token.value}'`, fix: function(fixer) { return fixer.insertTextAfter(token, ' '); } @@ -176,7 +176,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: 'A space is required before \'' + token.value + '\'', + message: `A space is required before '${token.value}'`, fix: function(fixer) { return fixer.insertTextBefore(token, ' '); } diff --git a/lib/rules/jsx-filename-extension.js b/lib/rules/jsx-filename-extension.js index 04b5c41a56..628850ab04 100644 --- a/lib/rules/jsx-filename-extension.js +++ b/lib/rules/jsx-filename-extension.js @@ -85,7 +85,7 @@ module.exports = { context.report({ node: invalidNode, - message: 'JSX not allowed in files with extension \'' + invalidExtension + '\'' + message: `JSX not allowed in files with extension '${invalidExtension}'` }); } }; diff --git a/lib/rules/jsx-handler-names.js b/lib/rules/jsx-handler-names.js index 4ed731baf9..7e9284e2ff 100644 --- a/lib/rules/jsx-handler-names.js +++ b/lib/rules/jsx-handler-names.js @@ -37,9 +37,8 @@ module.exports = { var eventHandlerPrefix = configuration.eventHandlerPrefix || 'handle'; var eventHandlerPropPrefix = configuration.eventHandlerPropPrefix || 'on'; - var EVENT_HANDLER_REGEX = new RegExp('^((props\\.' + eventHandlerPropPrefix + ')' - + '|((.*\\.)?' + eventHandlerPrefix + '))[A-Z].*$'); - var PROP_EVENT_HANDLER_REGEX = new RegExp('^(' + eventHandlerPropPrefix + '[A-Z].*|ref)$'); + var EVENT_HANDLER_REGEX = new RegExp(`^((props\\.${eventHandlerPropPrefix})|((.*\\.)?${eventHandlerPrefix}))[A-Z].*$`); + var PROP_EVENT_HANDLER_REGEX = new RegExp(`^(${eventHandlerPropPrefix}[A-Z].*|ref)$`); return { JSXAttribute: function(node) { @@ -60,12 +59,12 @@ module.exports = { if (propIsEventHandler && !propFnIsNamedCorrectly) { context.report({ node: node, - message: 'Handler function for ' + propKey + ' prop key must begin with \'' + eventHandlerPrefix + '\'' + message: `Handler function for ${propKey} prop key must begin with '${eventHandlerPrefix}'` }); } else if (propFnIsNamedCorrectly && !propIsEventHandler) { context.report({ node: node, - message: 'Prop key for ' + propValue + ' must begin with \'' + eventHandlerPropPrefix + '\'' + message: `Prop key for ${propValue} must begin with '${eventHandlerPropPrefix}'` }); } } diff --git a/lib/rules/jsx-indent-props.js b/lib/rules/jsx-indent-props.js index d0315f16a6..059b50c7b3 100644 --- a/lib/rules/jsx-indent-props.js +++ b/lib/rules/jsx-indent-props.js @@ -128,9 +128,9 @@ module.exports = { var regExp; if (indentType === 'space') { - regExp = new RegExp('^[ ' + skip + ']+'); + regExp = new RegExp(`^[ ${skip}]+`); } else { - regExp = new RegExp('^[\t' + skip + ']+'); + regExp = new RegExp(`^[\t${skip}]+`); } var indent = regExp.exec(src); diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js index 6a75b6f64f..a07cb8b87b 100644 --- a/lib/rules/jsx-indent.js +++ b/lib/rules/jsx-indent.js @@ -144,9 +144,9 @@ module.exports = { var regExp; if (indentType === 'space') { - regExp = new RegExp('^[ ' + skip + ']+'); + regExp = new RegExp(`^[ ${skip}]+`); } else { - regExp = new RegExp('^[\t' + skip + ']+'); + regExp = new RegExp(`^[\t${skip}]+`); } var indent = regExp.exec(src); diff --git a/lib/rules/jsx-max-props-per-line.js b/lib/rules/jsx-max-props-per-line.js index 0838edc68c..b4582d28b7 100644 --- a/lib/rules/jsx-max-props-per-line.js +++ b/lib/rules/jsx-max-props-per-line.js @@ -64,7 +64,7 @@ module.exports = { var name = getPropName(props[line][maximum]); context.report({ node: props[line][maximum], - message: 'Prop `' + name + '` must be placed on a new line' + message: `Prop \`${name}\` must be placed on a new line` }); break; } diff --git a/lib/rules/jsx-no-undef.js b/lib/rules/jsx-no-undef.js index 7639af1671..d496081432 100644 --- a/lib/rules/jsx-no-undef.js +++ b/lib/rules/jsx-no-undef.js @@ -67,7 +67,7 @@ module.exports = { context.report({ node: node, - message: '\'' + node.name + '\' is not defined.' + message: `'${node.name}' is not defined.` }); } diff --git a/lib/rules/jsx-pascal-case.js b/lib/rules/jsx-pascal-case.js index 07ac40874a..dab4c8fd15 100644 --- a/lib/rules/jsx-pascal-case.js +++ b/lib/rules/jsx-pascal-case.js @@ -66,7 +66,7 @@ module.exports = { if (!isPascalCase && !isCompatTag && !isAllowedAllCaps && !isIgnored) { context.report({ node: node, - message: 'Imported JSX component ' + name + ' must be in PascalCase' + message: `Imported JSX component ${name} must be in PascalCase` }); } } diff --git a/lib/rules/jsx-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js index 7ee23e706c..592bc160b3 100644 --- a/lib/rules/jsx-wrap-multilines.js +++ b/lib/rules/jsx-wrap-multilines.js @@ -73,7 +73,7 @@ module.exports = { node: node, message: 'Missing parentheses around multilines JSX', fix: function(fixer) { - return fixer.replaceText(node, '(' + sourceCode.getText(node) + ')'); + return fixer.replaceText(node, `(${sourceCode.getText(node)})`); } }); } diff --git a/lib/rules/no-children-prop.js b/lib/rules/no-children-prop.js index ebf8304912..54540db784 100644 --- a/lib/rules/no-children-prop.js +++ b/lib/rules/no-children-prop.js @@ -4,8 +4,6 @@ */ 'use strict'; -var find = require('array.prototype.find'); - // ------------------------------------------------------------------------------ // Helpers // ------------------------------------------------------------------------------ @@ -55,7 +53,7 @@ module.exports = { } var props = node.arguments[1].properties; - var childrenProp = find(props, function(prop) { + var childrenProp = props.find(function(prop) { return prop.key && prop.key.name === 'children'; }); diff --git a/lib/rules/no-danger-with-children.js b/lib/rules/no-danger-with-children.js index 671bdf40ea..d0920dd58b 100644 --- a/lib/rules/no-danger-with-children.js +++ b/lib/rules/no-danger-with-children.js @@ -4,7 +4,6 @@ */ 'use strict'; -var find = require('array.prototype.find'); var variableUtil = require('../util/variable'); // ------------------------------------------------------------------------------ @@ -21,7 +20,7 @@ module.exports = { }, create: function(context) { function findSpreadVariable(name) { - return find(variableUtil.variablesInScope(context), function (item) { + return variableUtil.variablesInScope(context).find(function (item) { return item.name === name; }); } @@ -34,7 +33,7 @@ module.exports = { if (!node.properties) { return false; } - return find(node.properties, function(prop) { + return node.properties.find(function(prop) { if (prop.type === 'Property') { return prop.key.name === propName; } else if (prop.type === 'ExperimentalSpreadProperty') { @@ -54,7 +53,7 @@ module.exports = { */ function findJsxProp(node, propName) { var attributes = node.openingElement.attributes; - return find(attributes, function (attribute) { + return attributes.find(function (attribute) { if (attribute.type === 'JSXSpreadAttribute') { var variable = findSpreadVariable(attribute.argument.name); if (variable && variable.defs.length && variable.defs[0].node.init) { @@ -95,7 +94,7 @@ module.exports = { var props = node.arguments[1]; if (props.type === 'Identifier') { - var variable = find(variableUtil.variablesInScope(context), function (item) { + var variable = variableUtil.variablesInScope(context).find(function (item) { return item.name === props.name; }); if (variable && variable.defs[0].node.init) { diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 4552a4f688..d7dcf8a877 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -38,28 +38,28 @@ module.exports = { MemberExpression: {} }; // 0.12.0 - deprecated.MemberExpression[pragma + '.renderComponent'] = ['0.12.0', pragma + '.render']; - deprecated.MemberExpression[pragma + '.renderComponentToString'] = ['0.12.0', pragma + '.renderToString']; - deprecated.MemberExpression[pragma + '.renderComponentToStaticMarkup'] = [ + deprecated.MemberExpression[`${pragma}.renderComponent`] = ['0.12.0', `${pragma}.render`]; + deprecated.MemberExpression[`${pragma}.renderComponentToString`] = ['0.12.0', `${pragma}.renderToString`]; + deprecated.MemberExpression[`${pragma}.renderComponentToStaticMarkup`] = [ '0.12.0', - pragma + '.renderToStaticMarkup' + `${pragma}.renderToStaticMarkup` ]; - deprecated.MemberExpression[pragma + '.isValidComponent'] = ['0.12.0', pragma + '.isValidElement']; - deprecated.MemberExpression[pragma + '.PropTypes.component'] = ['0.12.0', pragma + '.PropTypes.element']; - deprecated.MemberExpression[pragma + '.PropTypes.renderable'] = ['0.12.0', pragma + '.PropTypes.node']; - deprecated.MemberExpression[pragma + '.isValidClass'] = ['0.12.0']; + deprecated.MemberExpression[`${pragma}.isValidComponent`] = ['0.12.0', `${pragma}.isValidElement`]; + deprecated.MemberExpression[`${pragma}.PropTypes.component`] = ['0.12.0', `${pragma}.PropTypes.element`]; + deprecated.MemberExpression[`${pragma}.PropTypes.renderable`] = ['0.12.0', `${pragma}.PropTypes.node`]; + deprecated.MemberExpression[`${pragma}.isValidClass`] = ['0.12.0']; deprecated.MemberExpression['this.transferPropsTo'] = ['0.12.0', 'spread operator ({...})']; // 0.13.0 - deprecated.MemberExpression[pragma + '.addons.classSet'] = ['0.13.0', 'the npm module classnames']; - deprecated.MemberExpression[pragma + '.addons.cloneWithProps'] = ['0.13.0', pragma + '.cloneElement']; + deprecated.MemberExpression[`${pragma}.addons.classSet`] = ['0.13.0', 'the npm module classnames']; + deprecated.MemberExpression[`${pragma}.addons.cloneWithProps`] = ['0.13.0', `${pragma}.cloneElement`]; // 0.14.0 - deprecated.MemberExpression[pragma + '.render'] = ['0.14.0', 'ReactDOM.render']; - deprecated.MemberExpression[pragma + '.unmountComponentAtNode'] = ['0.14.0', 'ReactDOM.unmountComponentAtNode']; - deprecated.MemberExpression[pragma + '.findDOMNode'] = ['0.14.0', 'ReactDOM.findDOMNode']; - deprecated.MemberExpression[pragma + '.renderToString'] = ['0.14.0', 'ReactDOMServer.renderToString']; - deprecated.MemberExpression[pragma + '.renderToStaticMarkup'] = ['0.14.0', 'ReactDOMServer.renderToStaticMarkup']; + deprecated.MemberExpression[`${pragma}.render`] = ['0.14.0', 'ReactDOM.render']; + deprecated.MemberExpression[`${pragma}.unmountComponentAtNode`] = ['0.14.0', 'ReactDOM.unmountComponentAtNode']; + deprecated.MemberExpression[`${pragma}.findDOMNode`] = ['0.14.0', 'ReactDOM.findDOMNode']; + deprecated.MemberExpression[`${pragma}.renderToString`] = ['0.14.0', 'ReactDOMServer.renderToString']; + deprecated.MemberExpression[`${pragma}.renderToStaticMarkup`] = ['0.14.0', 'ReactDOMServer.renderToStaticMarkup']; // 15.0.0 - deprecated.MemberExpression[pragma + '.addons.LinkedStateMixin'] = ['15.0.0']; + deprecated.MemberExpression[`${pragma}.addons.LinkedStateMixin`] = ['15.0.0']; deprecated.MemberExpression['ReactPerf.printDOM'] = ['15.0.0', 'ReactPerf.printOperations']; deprecated.MemberExpression['Perf.printDOM'] = ['15.0.0', 'Perf.printOperations']; deprecated.MemberExpression['ReactPerf.getMeasurementsSummaryMap'] = ['15.0.0', 'ReactPerf.getWasted']; @@ -96,7 +96,7 @@ module.exports = { data: { oldMethod: method, version: deprecated[node.type][method][0], - newMethod: deprecated[node.type][method][1] ? ', use ' + deprecated[node.type][method][1] + ' instead' : '' + newMethod: deprecated[node.type][method][1] ? `, use ${deprecated[node.type][method][1]} instead` : '' } }); }, diff --git a/lib/rules/no-render-return-value.js b/lib/rules/no-render-return-value.js index de684d42cf..2bb69b1042 100644 --- a/lib/rules/no-render-return-value.js +++ b/lib/rules/no-render-return-value.js @@ -60,7 +60,7 @@ module.exports = { ) { context.report({ node: callee, - message: 'Do not depend on the return value from ' + callee.object.name + '.render' + message: `Do not depend on the return value from ${callee.object.name}.render` }); } } diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js index be9054934c..1697a8f63d 100644 --- a/lib/rules/no-unused-prop-types.js +++ b/lib/rules/no-unused-prop-types.js @@ -8,7 +8,6 @@ // https://github.com/yannickcr/eslint-plugin-react/issues/7 var has = require('has'); -var assign = require('object.assign'); var Components = require('../util/Components'); var variable = require('../util/variable'); var annotations = require('../util/annotations'); @@ -52,7 +51,7 @@ module.exports = { var defaults = {skipShapeProps: true}; var sourceCode = context.getSourceCode(); - var configuration = assign({}, defaults, context.options[0] || {}); + var configuration = Object.assign({}, defaults, context.options[0] || {}); var skipShapeProps = configuration.skipShapeProps; var customValidators = configuration.customValidators || []; // Used to track the type annotations in scope. @@ -588,7 +587,7 @@ module.exports = { } break; default: - throw new Error(node.type + ' ASTNodes are not handled by markPropTypesAsUsed'); + throw new Error(`${node.type} ASTNodes are not handled by markPropTypesAsUsed`); } var component = components.get(utils.getParentComponent()); diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js index 80befb599f..6a71187f35 100644 --- a/lib/rules/prop-types.js +++ b/lib/rules/prop-types.js @@ -604,7 +604,7 @@ module.exports = { } break; default: - throw new Error(node.type + ' ASTNodes are not handled by markPropTypesAsUsed'); + throw new Error(`${node.type} ASTNodes are not handled by markPropTypesAsUsed`); } var component = components.get(utils.getParentComponent()); diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js index 86aedc1c29..354351053a 100644 --- a/lib/rules/require-default-props.js +++ b/lib/rules/require-default-props.js @@ -5,7 +5,6 @@ 'use strict'; var has = require('has'); -var find = require('array.prototype.find'); var Components = require('../util/Components'); var variableUtil = require('../util/variable'); var annotations = require('../util/annotations'); @@ -78,7 +77,7 @@ module.exports = { * @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise. */ function findVariableByName(name) { - var variable = find(variableUtil.variablesInScope(context), function(item) { + var variable = variableUtil.variablesInScope(context).find(function(item) { return item.name === name; }); @@ -214,7 +213,7 @@ module.exports = { * from this ObjectExpression can't be resolved. */ function getDefaultPropsFromObjectExpression(objectExpression) { - var hasSpread = find(objectExpression.properties, function(property) { + var hasSpread = objectExpression.properties.find(function(property) { return property.type === 'ExperimentalSpreadProperty'; }); diff --git a/lib/rules/require-extension.js b/lib/rules/require-extension.js index 273d356363..7b1bb23280 100644 --- a/lib/rules/require-extension.js +++ b/lib/rules/require-extension.js @@ -89,7 +89,7 @@ module.exports = { if (!isPackage(id) && isForbiddenExtension(ext)) { context.report({ node: node, - message: 'Unable to require module with extension \'' + ext + '\'' + message: `Unable to require module with extension '${ext}'` }); } } diff --git a/lib/rules/sort-prop-types.js b/lib/rules/sort-prop-types.js index 817e4123d7..791471c83e 100644 --- a/lib/rules/sort-prop-types.js +++ b/lib/rules/sort-prop-types.js @@ -3,8 +3,6 @@ */ 'use strict'; -var find = require('array.prototype.find'); - var variableUtil = require('../util/variable'); // ------------------------------------------------------------------------------ @@ -164,7 +162,7 @@ module.exports = { declarations = right.properties; break; case 'Identifier': - var variable = find(variableUtil.variablesInScope(context), function (item) { + var variable = variableUtil.variablesInScope(context).find(function (item) { return item.name === right.name; }); if ( diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index a3dc6212fb..1dad301562 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -4,7 +4,6 @@ */ 'use strict'; -var find = require('array.prototype.find'); var variableUtil = require('../util/variable'); // ------------------------------------------------------------------------------ @@ -33,7 +32,7 @@ module.exports = { * @param {object} node A Identifier node */ function checkIdentifiers(node) { - var variable = find(variableUtil.variablesInScope(context), function (item) { + var variable = variableUtil.variablesInScope(context).find(function (item) { return item.name === node.name; }); @@ -55,7 +54,7 @@ module.exports = { && node.arguments.length > 1 ) { if (node.arguments[1].type === 'ObjectExpression') { - var style = find(node.arguments[1].properties, function(property) { + var style = node.arguments[1].properties.find(function(property) { return property.key && property.key.name === 'style' && !property.computed; }); if (style) { diff --git a/lib/util/Components.js b/lib/util/Components.js index fec2d2e50e..80afc2a564 100644 --- a/lib/util/Components.js +++ b/lib/util/Components.js @@ -155,7 +155,7 @@ function componentRule(rule, context) { if (!node.parent) { return false; } - return new RegExp('^(' + pragma + '\\.)?' + createClass + '$').test(sourceCode.getText(node.parent.callee)); + return new RegExp(`^(${pragma}\\.)?${createClass}$`).test(sourceCode.getText(node.parent.callee)); }, /** @@ -172,7 +172,7 @@ function componentRule(rule, context) { if (!node.superClass) { return false; } - return new RegExp('^(' + pragma + '\\.)?(Pure)?Component$').test(sourceCode.getText(node.superClass)); + return new RegExp(`^(${pragma}\\.)?(Pure)?Component$`).test(sourceCode.getText(node.superClass)); }, /** @@ -208,7 +208,7 @@ function componentRule(rule, context) { */ isPureComponent: function (node) { if (node.superClass) { - return new RegExp('^(' + pragma + '\\.)?PureComponent$').test(sourceCode.getText(node.superClass)); + return new RegExp(`^(${pragma}\\.)?PureComponent$`).test(sourceCode.getText(node.superClass)); } return false; }, diff --git a/lib/util/pragma.js b/lib/util/pragma.js index 7938ed28f8..c7bec3463e 100644 --- a/lib/util/pragma.js +++ b/lib/util/pragma.js @@ -16,7 +16,7 @@ function getCreateClassFromContext(context) { pragma = context.settings.react.createClass; } if (!JS_IDENTIFIER_REGEX.test(pragma)) { - throw new Error('createClass pragma ' + pragma + 'is not a valid function name'); + throw new Error(`createClass pragma ${pragma} is not a valid function name`); } return pragma; } @@ -28,7 +28,7 @@ function getFromContext(context) { pragma = context.settings.react.pragma; } if (!JS_IDENTIFIER_REGEX.test(pragma)) { - throw new Error('React pragma ' + pragma + 'is not a valid identifier'); + throw new Error(`React pragma ${pragma} is not a valid identifier`); } return pragma; } diff --git a/lib/util/variable.js b/lib/util/variable.js index 26924489c1..6ec67c686e 100644 --- a/lib/util/variable.js +++ b/lib/util/variable.js @@ -4,8 +4,6 @@ */ 'use strict'; -var find = require('array.prototype.find'); - /** * Search a particular variable in a list * @param {Array} variables The variables list. @@ -25,7 +23,7 @@ function findVariable(variables, name) { * @returns {Object} Variable if the variable was found, null if not. */ function getVariable(variables, name) { - return find(variables, function (variable) { + return variables.find(function (variable) { return variable.name === name; }); } diff --git a/lib/util/version.js b/lib/util/version.js index 04737cf3dc..f173ed12e6 100644 --- a/lib/util/version.js +++ b/lib/util/version.js @@ -10,7 +10,7 @@ function getFromContext(context) { if (context.settings.react && context.settings.react.version) { confVer = context.settings.react.version; } - confVer = /^[0-9]+\.[0-9]+$/.test(confVer) ? confVer + '.0' : confVer; + confVer = /^[0-9]+\.[0-9]+$/.test(confVer) ? `${confVer}.0` : confVer; return confVer.split('.').map(function(part) { return Number(part); }); diff --git a/package.json b/package.json index bacb8dd2bf..01a5568648 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "coveralls": "cat ./reports/coverage/lcov.info | coveralls", "lint": "eslint ./", "test": "npm run lint && npm run unit-test", - "unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/**/*.js -- --reporter dot --opts tests/mocha.opts" + "unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/**/*.js -- --reporter dot" }, "files": [ "LICENSE", @@ -25,22 +25,20 @@ "dependencies": { "doctrine": "^1.2.2", "has": "^1.0.1", - "jsx-ast-utils": "^1.3.4", - "array.prototype.find": "^2.0.1", - "object.assign": "^4.0.4" + "jsx-ast-utils": "^1.3.4" }, "devDependencies": { "babel-eslint": "7.1.1", "coveralls": "2.11.15", - "eslint": "^2.0.0 || ^3.0.0", + "eslint": "^3.0.0", "istanbul": "0.4.5", "mocha": "3.2.0" }, "peerDependencies": { - "eslint": "^2.0.0 || ^3.0.0" + "eslint": "^3.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=4" }, "keywords": [ "eslint", diff --git a/tests/eslint-compat.js b/tests/eslint-compat.js deleted file mode 100644 index c488584dd6..0000000000 --- a/tests/eslint-compat.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -var isEslint2 = require('eslint/package.json').version.slice(0, 2) === '2.'; - -module.exports = { - isEslint2: function () { - return isEslint2; - }, - dot: function dot(msg) { - return isEslint2 ? msg : msg + '.'; - } -}; diff --git a/tests/index.js b/tests/index.js index 8e058037d2..12411e6d15 100644 --- a/tests/index.js +++ b/tests/index.js @@ -14,7 +14,7 @@ var ruleFiles = fs.readdirSync(path.resolve(__dirname, '../lib/rules/')) describe('all rule files should be exported by the plugin', function() { ruleFiles.forEach(function(ruleName) { - it('should export ' + ruleName, function() { + it(`should export ${ruleName}`, function() { assert.equal( plugin.rules[ruleName], require(path.join('../lib/rules', ruleName)) @@ -29,9 +29,9 @@ describe('deprecated rules', function() { var inDeprecatedRules = Boolean(plugin.deprecatedRules[ruleName]); var isDeprecated = plugin.rules[ruleName].meta.deprecated; if (inDeprecatedRules) { - assert(isDeprecated, ruleName + ' metadata should mark it as deprecated'); + assert(isDeprecated, `${ruleName} metadata should mark it as deprecated`); } else { - assert(!isDeprecated, ruleName + ' metadata should not mark it as deprecated'); + assert(!isDeprecated, `${ruleName} metadata should not mark it as deprecated`); } }); }); @@ -47,12 +47,12 @@ describe('configurations', function() { }); ruleFiles.forEach(function(ruleName) { - var inRecommendedConfig = Boolean(plugin.configs.recommended.rules['react/' + ruleName]); + var inRecommendedConfig = Boolean(plugin.configs.recommended.rules[`react/${ruleName}`]); var isRecommended = plugin.rules[ruleName].meta.docs.recommended; if (inRecommendedConfig) { - assert(isRecommended, ruleName + ' metadata should mark it as recommended'); + assert(isRecommended, `${ruleName} metadata should mark it as recommended`); } else { - assert(!isRecommended, ruleName + ' metadata should not mark it as recommended'); + assert(!isRecommended, `${ruleName} metadata should not mark it as recommended`); } }); }); @@ -64,7 +64,7 @@ describe('configurations', function() { }); ruleFiles.forEach(function(ruleName) { var inDeprecatedRules = Boolean(plugin.deprecatedRules[ruleName]); - var inAllConfig = Boolean(plugin.configs.all.rules['react/' + ruleName]); + var inAllConfig = Boolean(plugin.configs.all.rules[`react/${ruleName}`]); assert(inDeprecatedRules ^ inAllConfig); }); }); diff --git a/tests/lib/rules/jsx-closing-bracket-location.js b/tests/lib/rules/jsx-closing-bracket-location.js index 7571a1e580..0699da3184 100644 --- a/tests/lib/rules/jsx-closing-bracket-location.js +++ b/tests/lib/rules/jsx-closing-bracket-location.js @@ -26,8 +26,7 @@ var MESSAGE_TAG_ALIGNED = 'The closing bracket must be aligned with the opening var MESSAGE_LINE_ALIGNED = 'The closing bracket must be aligned with the line containing the opening tag'; var messageWithDetails = function(message, expectedColumn, expectedNextLine) { - var details = ' (expected column ' + expectedColumn + - (expectedNextLine ? ' on the next line)' : ')'); + var details = ` (expected column ${expectedColumn}${expectedNextLine ? ' on the next line)' : ')'}`; return message + details; }; diff --git a/tests/lib/rules/jsx-uses-react.js b/tests/lib/rules/jsx-uses-react.js index 773bb870e7..b14058b776 100644 --- a/tests/lib/rules/jsx-uses-react.js +++ b/tests/lib/rules/jsx-uses-react.js @@ -12,7 +12,6 @@ var eslint = require('eslint').linter; var rule = require('eslint/lib/rules/no-unused-vars'); var RuleTester = require('eslint').RuleTester; -var dot = require('../../eslint-compat').dot; var parserOptions = { ecmaVersion: 6, @@ -42,12 +41,12 @@ ruleTester.run('no-unused-vars', rule, { ], invalid: [{ code: '/*eslint jsx-uses-react:1*/ var React;', - errors: [{message: dot('\'React\' is defined but never used')}], parserOptions: parserOptions + errors: [{message: '\'React\' is defined but never used.'}], parserOptions: parserOptions }, { code: '/*eslint jsx-uses-react:1*/ /** @jsx Foo */ var React;
;', - errors: [{message: dot('\'React\' is defined but never used')}], parserOptions: parserOptions + errors: [{message: '\'React\' is defined but never used.'}], parserOptions: parserOptions }, { code: '/*eslint jsx-uses-react:1*/ var React;
;', - errors: [{message: dot('\'React\' is defined but never used')}], settings: settings, parserOptions: parserOptions + errors: [{message: '\'React\' is defined but never used.'}], settings: settings, parserOptions: parserOptions }] }); diff --git a/tests/lib/rules/jsx-uses-vars.js b/tests/lib/rules/jsx-uses-vars.js index ad678d81a9..dd3dd225cc 100644 --- a/tests/lib/rules/jsx-uses-vars.js +++ b/tests/lib/rules/jsx-uses-vars.js @@ -13,8 +13,6 @@ var eslint = require('eslint').linter; var ruleNoUnusedVars = require('eslint/lib/rules/no-unused-vars'); var rulePreferConst = require('eslint/lib/rules/prefer-const'); var RuleTester = require('eslint').RuleTester; -var dot = require('../../eslint-compat').dot; -var isEslint2 = require('../../eslint-compat').isEslint2; var parserOptions = { ecmaVersion: 6, @@ -125,7 +123,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { invalid: [ { code: '/*eslint jsx-uses-vars:1*/ var App;', - errors: [{message: dot('\'App\' is defined but never used')}], + errors: [{message: '\'App\' is defined but never used.'}], parserOptions: parserOptions }, { code: '\ @@ -133,7 +131,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { var App;\ var unused;\ React.render();', - errors: [{message: dot('\'unused\' is defined but never used')}], + errors: [{message: '\'unused\' is defined but never used.'}], parserOptions: parserOptions }, { code: '\ @@ -141,7 +139,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { var App;\ var Hello;\ React.render();', - errors: [{message: dot('\'Hello\' is defined but never used')}], + errors: [{message: '\'Hello\' is defined but never used.'}], parserOptions: parserOptions }, { code: '\ @@ -149,13 +147,13 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { var Button;\ var Input;\ React.render();', - errors: [{message: dot('\'Input\' is defined but never used')}], + errors: [{message: '\'Input\' is defined but never used.'}], parserOptions: parserOptions }, { code: '\ /*eslint jsx-uses-vars:1*/\ class unused {}', - errors: [{message: dot('\'unused\' is defined but never used')}], + errors: [{message: '\'unused\' is defined but never used.'}], parserOptions: parserOptions }, { code: '\ @@ -167,7 +165,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { }\ }', errors: [{ - message: dot('\'HelloMessage\' is defined but never used'), + message: '\'HelloMessage\' is defined but never used.', line: 1 }], parserOptions: parserOptions @@ -181,7 +179,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { }\ }', errors: [{ - message: dot('\'HelloMessage\' is defined but never used'), + message: '\'HelloMessage\' is defined but never used.', line: 1 }], parser: 'babel-eslint', @@ -196,7 +194,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { }\ Greetings();', errors: [{ - message: dot('\'Hello\' is defined but never used'), + message: '\'Hello\' is defined but never used.', line: 1 }], parser: 'babel-eslint', @@ -208,21 +206,21 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { // Check compatibility with eslint prefer-const rule (#716) ruleTester.run('prefer-const', rulePreferConst, { valid: [], - invalid: (isEslint2() ? [] : [{ + invalid: [{ code: [ '/* eslint jsx-uses-vars:1 */', 'let App =
;', ';' ].join('\n'), - errors: [{message: dot('\'App\' is never reassigned. Use \'const\' instead')}], + errors: [{message: '\'App\' is never reassigned. Use \'const\' instead.'}], parserOptions: parserOptions - }]).concat([{ + }, { code: [ '/* eslint jsx-uses-vars:1 */', 'let filters = \'foo\';', '
{filters}
;' ].join('\n'), - errors: [{message: '\'filters\' is never reassigned' + (isEslint2() ? ', use' : '. Use') + ' \'const\' instead.'}], + errors: [{message: '\'filters\' is never reassigned. Use \'const\' instead.'}], parserOptions: parserOptions - }]) + }] }); diff --git a/tests/lib/rules/require-default-props.js b/tests/lib/rules/require-default-props.js index 1ccfe73837..779e2d8b86 100644 --- a/tests/lib/rules/require-default-props.js +++ b/tests/lib/rules/require-default-props.js @@ -10,7 +10,6 @@ var rule = require('../../../lib/rules/require-default-props'); var RuleTester = require('eslint').RuleTester; -var assign = require('object.assign'); require('babel-eslint'); @@ -410,7 +409,7 @@ ruleTester.run('require-default-props', rule, { ' return
{foo}{bar}
;', '}' ].join('\n'), - parserOptions: assign({sourceType: 'module'}, parserOptions) + parserOptions: Object.assign({sourceType: 'module'}, parserOptions) }, { code: [ @@ -425,7 +424,7 @@ ruleTester.run('require-default-props', rule, { ' return
{foo}{bar}
;', '}' ].join('\n'), - parserOptions: assign({sourceType: 'module'}, parserOptions) + parserOptions: Object.assign({sourceType: 'module'}, parserOptions) }, // using spread operator { diff --git a/tests/lib/rules/style-prop-object.js b/tests/lib/rules/style-prop-object.js index 7dafefd1d0..7c7346c76a 100644 --- a/tests/lib/rules/style-prop-object.js +++ b/tests/lib/rules/style-prop-object.js @@ -10,7 +10,6 @@ var rule = require('../../../lib/rules/style-prop-object'); var RuleTester = require('eslint').RuleTester; -var assign = require('object.assign'); var parserOptions = { ecmaVersion: 6, @@ -77,7 +76,7 @@ ruleTester.run('style-prop-object', rule, { ' return
;', '}' ].join('\n'), - parserOptions: assign({sourceType: 'module'}, parserOptions) + parserOptions: Object.assign({sourceType: 'module'}, parserOptions) }, { code: [ @@ -87,7 +86,7 @@ ruleTester.run('style-prop-object', rule, { ' return
;', '}' ].join('\n'), - parserOptions: assign({sourceType: 'module'}, parserOptions) + parserOptions: Object.assign({sourceType: 'module'}, parserOptions) }, { code: [ @@ -102,7 +101,7 @@ ruleTester.run('style-prop-object', rule, { 'const styles = Object.assign({ color: \'red\' }, mystyles);', 'React.createElement("div", { style: styles });' ].join('\n'), - parserOptions: assign({sourceType: 'module'}, parserOptions) + parserOptions: Object.assign({sourceType: 'module'}, parserOptions) }, { code: '
', diff --git a/tests/mocha.opts b/tests/mocha.opts deleted file mode 100644 index 5232e1ad1d..0000000000 --- a/tests/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---require ./tests/setup diff --git a/tests/setup.js b/tests/setup.js deleted file mode 100644 index e0526921a7..0000000000 --- a/tests/setup.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -require('object.assign/shim')();