From c442efa7c5a44f19f321a3d6aa839118081ef75b Mon Sep 17 00:00:00 2001 From: jquense Date: Fri, 19 Jun 2015 00:01:10 -0400 Subject: [PATCH] Initial --- eslint/babel-eslint-plugin/.gitignore | 1 + eslint/babel-eslint-plugin/.travis.yml | 7 + eslint/babel-eslint-plugin/LICENSE | 23 + eslint/babel-eslint-plugin/README.md | 38 + eslint/babel-eslint-plugin/helpers.js | 15 + eslint/babel-eslint-plugin/index.js | 8 + eslint/babel-eslint-plugin/package.json | 37 + .../rules/generator-star-spacing.js | 92 +++ .../rules/generator-star.js | 84 +++ .../rules/object-shorthand.js | 73 ++ .../tests/generator-star-spacing.js | 680 ++++++++++++++++++ .../tests/generator-star.js | 32 + .../tests/object-shorthand.js | 100 +++ 13 files changed, 1190 insertions(+) create mode 100644 eslint/babel-eslint-plugin/.gitignore create mode 100644 eslint/babel-eslint-plugin/.travis.yml create mode 100644 eslint/babel-eslint-plugin/LICENSE create mode 100644 eslint/babel-eslint-plugin/README.md create mode 100644 eslint/babel-eslint-plugin/helpers.js create mode 100644 eslint/babel-eslint-plugin/index.js create mode 100644 eslint/babel-eslint-plugin/package.json create mode 100644 eslint/babel-eslint-plugin/rules/generator-star-spacing.js create mode 100644 eslint/babel-eslint-plugin/rules/generator-star.js create mode 100644 eslint/babel-eslint-plugin/rules/object-shorthand.js create mode 100644 eslint/babel-eslint-plugin/tests/generator-star-spacing.js create mode 100644 eslint/babel-eslint-plugin/tests/generator-star.js create mode 100644 eslint/babel-eslint-plugin/tests/object-shorthand.js diff --git a/eslint/babel-eslint-plugin/.gitignore b/eslint/babel-eslint-plugin/.gitignore new file mode 100644 index 0000000000..3c3629e647 --- /dev/null +++ b/eslint/babel-eslint-plugin/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/eslint/babel-eslint-plugin/.travis.yml b/eslint/babel-eslint-plugin/.travis.yml new file mode 100644 index 0000000000..5a7ce2a7f9 --- /dev/null +++ b/eslint/babel-eslint-plugin/.travis.yml @@ -0,0 +1,7 @@ +--- +git: + depth: 1 +language: node_js +node_js: + - '0.12' + - 'io.js' \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/LICENSE b/eslint/babel-eslint-plugin/LICENSE new file mode 100644 index 0000000000..3d0e2f3067 --- /dev/null +++ b/eslint/babel-eslint-plugin/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2014-2015 Jason Quense +Original work by respective rule authors; copywrites noted in files. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/README.md b/eslint/babel-eslint-plugin/README.md new file mode 100644 index 0000000000..5de7ba997e --- /dev/null +++ b/eslint/babel-eslint-plugin/README.md @@ -0,0 +1,38 @@ +# eslint-plugin-babel + +An eslint plugin companion to babel-eslint. babel-eslint does a great job of adapting the eslint parser to valid babel code, it can't change built in rules to deal with the syntactic differences. eslint-plugin-babel reimplements problematic rules to not give false positives or negatives. + +### Install + +```sh +npm install eslint-plugin-babel -S +``` + +enable the plugin by adjusting your `.eslintrc` file to include the plugin: + +```json +{ + "plugins": [ + "babel" + ] +} +``` + +Finally enable all the rules you like to use (remember to disable the originals as well!). + +```json +{ + "rules": { + "babel/object-shorthand": 1, + "babel/generator-star": 1, + "babel/generator-star-spacing": 1, + } +} +``` +### Rules + +Each rule cooresponds to a core eslint rule, and has the same options. + +- `babel/object-shorthand`: doesn't fail when using object spread (`...obj`) +- `babel/generator-star`: Handles async/await functions correctly +- `babel/generator-star-spacing`: Handles async/await functions correctly diff --git a/eslint/babel-eslint-plugin/helpers.js b/eslint/babel-eslint-plugin/helpers.js new file mode 100644 index 0000000000..77f42a3bf4 --- /dev/null +++ b/eslint/babel-eslint-plugin/helpers.js @@ -0,0 +1,15 @@ +var _parse = require('babel-core').parse; + +module.exports = { + parse: function(code){ + var ast = null + try { + ast = _parse(code, { locations: true, ranges: true }).body[0] //unwrap body + } + catch (err){ + console.warn(err) + } + + return ast + } +} \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/index.js b/eslint/babel-eslint-plugin/index.js new file mode 100644 index 0000000000..86fbe85988 --- /dev/null +++ b/eslint/babel-eslint-plugin/index.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + rules: { + 'object-shorthand': require('./rules/object-shorthand'), + 'generator-star': require('./rules/object-shorthand') + } +}; diff --git a/eslint/babel-eslint-plugin/package.json b/eslint/babel-eslint-plugin/package.json new file mode 100644 index 0000000000..39201ad510 --- /dev/null +++ b/eslint/babel-eslint-plugin/package.json @@ -0,0 +1,37 @@ +{ + "name": "eslint-plugin-babel", + "version": "1.0.0", + "description": "eslint rule plugin companion to babel-eslint", + "main": "index.js", + "scripts": { + "test": "mocha -R spec ./tests/*.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/babel/eslint-plugin-babel.git" + }, + "keywords": [ + "babel", + "eslint", + "eslintplugin", + "babel-eslint" + ], + "author": "jquense @monasticpanic", + "license": "MIT", + "bugs": { + "url": "https://github.com/babel/eslint-plugin-babel/issues" + }, + "homepage": "https://github.com/babel/eslint-plugin-babel#readme", + "devDependencies": { + "babel-eslint": "^3.1.17", + "eslint": "^0.23.0", + "eslint-tester": "^0.8.0", + "is-my-json-valid": "^2.12.0", + "mocha": "^2.2.5", + "mocha-phantomjs": "^3.5.3", + "phantomjs": "^1.9.17" + }, + "dependencies": { + "babel-core": "^5.5.8" + } +} diff --git a/eslint/babel-eslint-plugin/rules/generator-star-spacing.js b/eslint/babel-eslint-plugin/rules/generator-star-spacing.js new file mode 100644 index 0000000000..b122ed19c8 --- /dev/null +++ b/eslint/babel-eslint-plugin/rules/generator-star-spacing.js @@ -0,0 +1,92 @@ +/** + * @fileoverview Rule to check the spacing around the * in generator functions. + * @author Jamund Ferguson + * @copyright 2015 Brandon Mills. All rights reserved. + * @copyright 2014 Jamund Ferguson. All rights reserved. + */ + +"use strict"; + +module.exports = function(context) { + + var mode = { + before: { before: true, after: false }, + after: { before: false, after: true }, + both: { before: true, after: true }, + neither: { before: false, after: false } + }[context.options[0] || "before"]; + + function isAsyncGenerator(node){ + return context.getFirstToken(node, 2).value === '*' + } + + /** + * Checks the spacing between two tokens before or after the star token. + * @param {string} side Either "before" or "after". + * @param {Token} leftToken `function` keyword token if side is "before", or + * star token if side is "after". + * @param {Token} rightToken Star token if side is "before", or identifier + * token if side is "after". + * @returns {void} + */ + function checkSpacing(side, leftToken, rightToken) { + if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) { + context.report( + leftToken.value === "*" ? leftToken : rightToken, + "{{type}} space {{side}} *.", + { + type: mode[side] ? "Missing" : "Unexpected", + side: side + } + ); + } + } + + /** + * Enforces the spacing around the star if node is a generator function. + * @param {ASTNode} node A function expression or declaration node. + * @returns {void} + */ + function checkFunction(node) { + var first = context.getFirstToken(node) + , isMethod = node.parent.method || node.parent.type === "MethodDefinition" + , isAsync = first.value === 'async'; + + var prevToken, starToken, nextToken; + + + if ( !node.generator || (isAsync && !isAsyncGenerator(node))) { + return; + } + + if (isMethod) { + starToken = context.getTokenBefore(node, 1); + } else { + starToken = context.getFirstToken(node, isAsync ? 2 : 1); + } + + // Only check before when preceded by `function` keyword + prevToken = context.getTokenBefore(starToken); + if (prevToken.value === "function" || prevToken.value === "static") { + checkSpacing("before", prevToken, starToken); + } + + // Only check after when followed by an identifier + nextToken = context.getTokenAfter(starToken); + if (nextToken.type === "Identifier") { + checkSpacing("after", starToken, nextToken); + } + } + + return { + "FunctionDeclaration": checkFunction, + "FunctionExpression": checkFunction + }; + +}; + +module.exports.schema = [ + { + "enum": ["before", "after", "both", "neither"] + } +]; \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/rules/generator-star.js b/eslint/babel-eslint-plugin/rules/generator-star.js new file mode 100644 index 0000000000..b5247f4f68 --- /dev/null +++ b/eslint/babel-eslint-plugin/rules/generator-star.js @@ -0,0 +1,84 @@ +/** + * @fileoverview Rule to check for the position of the * in your generator functions + * @author Jamund Ferguson + * @copyright 2014 Jamund Ferguson. All rights reserved. + */ + +"use strict"; + +var parse = require('../helpers').parse + +module.exports = function(context) { + + var position = context.options[0] || "end"; + + function isAsyncGenerator(node){ + return context.getFirstToken(node, 2).value === '*' + } + + /** + * Check the position of the star compared to the expected position. + * @param {ASTNode} node - the entire function node + * @returns {void} + */ + function checkStarPosition(node) { + + var first = context.getFirstToken(node) + , isAsync = first.value === 'async' + , starToken; + + + if (!node.generator || (isAsync && !isAsyncGenerator(node))) { + return; + } + + // Blocked, pending decision to fix or work around in eslint/espree#36 + if (context.getAncestors().pop().method) { + return; + } + + starToken = context.getFirstToken(node, isAsync ? 2 : 1); + + //console.log(declaration, starToken) + + // check for function *name() {} + if (position === "end") { + if (starToken.range[1] !== context.getTokenAfter(starToken).range[0]) { + // * starts where the next identifier begins + context.report(node, "Expected a space before *."); + } + } + + // check for function* name() {} + if (position === "start") { + + // * begins where the previous identifier ends + if (starToken.range[0] !== context.getTokenBefore(starToken).range[1]) { + context.report(node, "Expected no space before *."); + } + } + + // check for function * name() {} + if (position === "middle") { + + // must be a space before and afer the * + if (starToken.range[0] <= context.getTokenBefore(starToken).range[1] || + starToken.range[1] >= context.getTokenAfter(starToken).range[0]) { + context.report(node, "Expected spaces around *."); + } + } + + } + + return { + "FunctionDeclaration": checkStarPosition, + "FunctionExpression": checkStarPosition + }; + +}; + +module.exports.schema = [ + { + "enum": ["start", "middle", "end"] + } +]; \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/rules/object-shorthand.js b/eslint/babel-eslint-plugin/rules/object-shorthand.js new file mode 100644 index 0000000000..e584bfb684 --- /dev/null +++ b/eslint/babel-eslint-plugin/rules/object-shorthand.js @@ -0,0 +1,73 @@ + +/** + * @fileoverview Rule to enforce concise object methods and properties. + * @author Jamund Ferguson + * @copyright 2015 Jamund Ferguson. All rights reserved. + */ + +'use strict'; + +var OPTIONS = { + always: 'always', + never: 'never', + methods: 'methods', + properties: 'properties' + }; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + + var APPLY = context.options[0] || OPTIONS.always; + var APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; + var APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; + var APPLY_NEVER = APPLY === OPTIONS.never; + + return { + Property: function(node) { + var isConciseProperty = node.method || node.shorthand + , isSpreadProperty = !!this.getSource(node).match(/^\.\.\./) + , type; + + // if we're 'never' and concise we should warn now + if (APPLY_NEVER && isConciseProperty) { + type = node.method ? 'method' : 'property'; + context.report(node, 'Expected longform ' + type + ' syntax.'); + } + + // at this point if we're concise or if we're 'never' we can leave + if (APPLY_NEVER || isConciseProperty) { + return; + } + + if (node.kind === 'get' || node.kind === 'set') { + return; + } + + if (isSpreadProperty) { + return; + } + + if (node.value.type === 'FunctionExpression' && node.value.id == null && APPLY_TO_METHODS) { + // {x: function(){}} should be written as {x() {}} + context.report(node, 'Expected method shorthand.'); + } + else if (node.value.type === 'Identifier' && node.key.name === node.value.name && APPLY_TO_PROPS) { + // {x: x} should be written as {x} + context.report(node, 'Expected property shorthand.'); + } + else if (node.value.type === 'Identifier' && node.key.type === 'Literal' && node.key.value === node.value.name && APPLY_TO_PROPS) { + // {'x': x} should be written as {x} + context.report(node, 'Expected property shorthand.'); + } + } + }; +}; + +module.exports.schema = [ + { + 'enum': ['always', 'methods', 'properties', 'never'] + } +]; diff --git a/eslint/babel-eslint-plugin/tests/generator-star-spacing.js b/eslint/babel-eslint-plugin/tests/generator-star-spacing.js new file mode 100644 index 0000000000..4de1141b10 --- /dev/null +++ b/eslint/babel-eslint-plugin/tests/generator-star-spacing.js @@ -0,0 +1,680 @@ +/* eslint-disable */ +var linter = require('eslint').linter + , ESLintTester = require('eslint-tester') + , eslintTester = new ESLintTester(linter); + +var features = { + generators: true +}; + +function ok(code, args){ + return { code: code, args: args, parser: 'babel-eslint', ecmaFeatures: features } +} + +function err(code, errors, args){ + var e = ok(code, args) + e.errors = errors + return e +} + +var features = { + generators: true +}; + +function ok(code, args){ + return { code: code, args: args, parser: 'babel-eslint', ecmaFeatures: features } +} + +function err(code, errors, args){ + var e = ok(code, args) + e.errors = errors + return e +} + + +eslintTester.addRuleTest('rules/generator-star-spacing', { + valid: [ + ok('var test = async function(){}'), + ok('async function test(){}'), + ok('var test = async function *(){}'), + ok('async function *test(){}', [1, "before"]) , + ok('async function* test(){}', [1, "after"]), + ok('async function * test(){}', [1, "both"]), + ok('async function*test(){}', [1, "neither"]), + { + code: "function foo(){}" + }, + { + code: "function *foo(){}", + ecmaFeatures: { generators: true } + }, + { + code: "function *foo(arg1, arg2){}", + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function *foo(){};", + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function *(){};", + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function * (){};", + ecmaFeatures: { generators: true } + }, + { + code: "var foo = { *foo(){} };", + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "var foo = {*foo(){} };", + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "class Foo { *foo(){} }", + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo {*foo(){} }", + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { static *foo(){} }", + ecmaFeatures: { classes: true, generators: true } + }, + + // "before" + { + code: "function foo(){}", + args: [2, "before"] + }, + { + code: "function *foo(){}", + args: [2, "before"], + ecmaFeatures: { generators: true } + }, + { + code: "function *foo(arg1, arg2){}", + args: [2, "before"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function *foo(){};", + args: [2, "before"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function *(){};", + args: [2, "before"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function * (){};", + args: [2, "before"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = { *foo(){} };", + args: [2, "before"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "var foo = {*foo(){} };", + args: [2, "before"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "class Foo { *foo(){} }", + args: [2, "before"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo {*foo(){} }", + args: [2, "before"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { static *foo(){} }", + args: [2, "before"], + ecmaFeatures: { classes: true, generators: true } + }, + + // "after" + { + code: "function foo(){}", + args: [2, "after"] + }, + { + code: "function* foo(){}", + args: [2, "after"], + ecmaFeatures: { generators: true } + }, + { + code: "function* foo(arg1, arg2){}", + args: [2, "after"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function* foo(){};", + args: [2, "after"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function* (){};", + args: [2, "after"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function*(){};", + args: [2, "after"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = {* foo(){} };", + args: [2, "after"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "var foo = { * foo(){} };", + args: [2, "after"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "class Foo {* foo(){} }", + args: [2, "after"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { * foo(){} }", + args: [2, "after"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { static* foo(){} }", + args: [2, "after"], + ecmaFeatures: { classes: true, generators: true } + }, + + // "both" + { + code: "function foo(){}", + args: [2, "both"] + }, + { + code: "function * foo(){}", + args: [2, "both"], + ecmaFeatures: { generators: true } + }, + { + code: "function * foo(arg1, arg2){}", + args: [2, "both"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function * foo(){};", + args: [2, "both"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function * (){};", + args: [2, "both"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function *(){};", + args: [2, "both"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = { * foo(){} };", + args: [2, "both"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "var foo = {* foo(){} };", + args: [2, "both"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "class Foo { * foo(){} }", + args: [2, "both"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo {* foo(){} }", + args: [2, "both"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { static * foo(){} }", + args: [2, "both"], + ecmaFeatures: { classes: true, generators: true } + }, + + // "neither" + { + code: "function foo(){}", + args: [2, "neither"] + }, + { + code: "function*foo(){}", + args: [2, "neither"], + ecmaFeatures: { generators: true } + }, + { + code: "function*foo(arg1, arg2){}", + args: [2, "neither"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function*foo(){};", + args: [2, "neither"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function*(){};", + args: [2, "neither"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = function* (){};", + args: [2, "neither"], + ecmaFeatures: { generators: true } + }, + { + code: "var foo = {*foo(){} };", + args: [2, "neither"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "var foo = { *foo(){} };", + args: [2, "neither"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true } + }, + { + code: "class Foo {*foo(){} }", + args: [2, "neither"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { *foo(){} }", + args: [2, "neither"], + ecmaFeatures: { classes: true, generators: true } + }, + { + code: "class Foo { static*foo(){} }", + args: [2, "neither"], + ecmaFeatures: { classes: true, generators: true } + } + + ], + + invalid: [ + // Default ("before") + err('async function*test(){}', [ + { message: 'Missing space before *.' }, + ]), + err('async function* test(){}', [ + { + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + } + ]), + + { + code: "function*foo(){}", + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "function* foo(arg1, arg2){}", + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function*foo(){};", + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function* (){};", + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = {* foo(){} };", + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo {* foo(){} }", + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { static* foo(){} }", + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + + // "before" + { + code: "function*foo(){}", + args: [2, "before"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "function* foo(arg1, arg2){}", + args: [2, "before"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function*foo(){};", + args: [2, "before"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function* (){};", + args: [2, "before"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = {* foo(){} };", + args: [2, "before"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo {* foo(){} }", + args: [2, "before"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + + // "after" + { + code: "function*foo(){}", + args: [2, "after"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "function *foo(arg1, arg2){}", + args: [2, "after"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function *foo(){};", + args: [2, "after"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function *(){};", + args: [2, "after"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = { *foo(){} };", + args: [2, "after"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true }, + errors: [{ + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { *foo(){} }", + args: [2, "after"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { static *foo(){} }", + args: [2, "after"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + + // "both" + { + code: "function*foo(){}", + args: [2, "both"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "function*foo(arg1, arg2){}", + args: [2, "both"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function*foo(){};", + args: [2, "both"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function*(){};", + args: [2, "both"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = {*foo(){} };", + args: [2, "both"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true }, + errors: [{ + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo {*foo(){} }", + args: [2, "both"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Missing space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { static*foo(){} }", + args: [2, "both"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Missing space before *.", + type: "Punctuator" + }, { + message: "Missing space after *.", + type: "Punctuator" + }] + }, + + // "neither" + { + code: "function * foo(){}", + args: [2, "neither"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "function * foo(arg1, arg2){}", + args: [2, "neither"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function * foo(){};", + args: [2, "neither"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "var foo = function * (){};", + args: [2, "neither"], + ecmaFeatures: { generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }] + }, + { + code: "var foo = { * foo(){} };", + args: [2, "neither"], + ecmaFeatures: { generators: true, objectLiteralShorthandMethods: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { * foo(){} }", + args: [2, "neither"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Unexpected space after *.", + type: "Punctuator" + }] + }, + { + code: "class Foo { static * foo(){} }", + args: [2, "neither"], + ecmaFeatures: { classes: true, generators: true }, + errors: [{ + message: "Unexpected space before *.", + type: "Punctuator" + }, { + message: "Unexpected space after *.", + type: "Punctuator" + }] + } + + ] +}); \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/tests/generator-star.js b/eslint/babel-eslint-plugin/tests/generator-star.js new file mode 100644 index 0000000000..131d41f9c6 --- /dev/null +++ b/eslint/babel-eslint-plugin/tests/generator-star.js @@ -0,0 +1,32 @@ +/* eslint-disable */ +var linter = require('eslint').linter + , ESLintTester = require('eslint-tester') + , eslintTester = new ESLintTester(linter); + +var features = { + generators: true +}; + +function ok(code, args){ + return { code: code, args: args, parser: 'babel-eslint', ecmaFeatures: features } +} + +function err(code, errors, args){ + var e = ok(code, args) + e.errors = errors + return e +} + + +eslintTester.addRuleTest('rules/generator-star', { + valid: [ + ok('async function test(){}'), + ok('async function *test(){}', [1, "end"]) , + ok('async function* test(){}', [1, "start"]), + ok('async function * test(){}', [1, "middle"]) + ], + invalid: [ + err('async function* test(){}', [ { message: 'Expected a space before *.' }]), + err('async function *test(){}', [ { message: 'Expected no space before *.' }], [1, 'start']) + ] +}); \ No newline at end of file diff --git a/eslint/babel-eslint-plugin/tests/object-shorthand.js b/eslint/babel-eslint-plugin/tests/object-shorthand.js new file mode 100644 index 0000000000..9a89b10cc6 --- /dev/null +++ b/eslint/babel-eslint-plugin/tests/object-shorthand.js @@ -0,0 +1,100 @@ +/* eslint-disable */ +var linter = require('eslint').linter + , ESLintTester = require('eslint-tester') + , eslintTester = new ESLintTester(linter); + +var features = { + objectLiteralShorthandMethods: true, + objectLiteralShorthandProperties: true, + arrowFunctions: true, + destructuring: true, + generators: true +}; + +function ok(code, args){ + return { code: code, parser: 'babel-eslint', ecmaFeatures: features} +} + + +eslintTester.addRuleTest('rules/object-shorthand', { + valid: [ + ok('let { ...spread } = obj'), + ok('let { ...spread } = obj', [2, 'never']), + + //original test cases + { code: "var x = {y() {}}", ecmaFeatures: features }, + { code: "var x = {y}", ecmaFeatures: features }, + { code: "var x = {a: b}", ecmaFeatures: features }, + { code: "var x = {a: 'a'}", ecmaFeatures: features }, + { code: "var x = {'a': 'a'}", ecmaFeatures: features }, + { code: "var x = {'a': b}", ecmaFeatures: features }, + { code: "var x = {y(x) {}}", ecmaFeatures: features }, + { code: "var {x,y,z} = x", ecmaFeatures: features }, + { code: "var {x: {y}} = z", ecmaFeatures: features }, + { code: "var x = {*x() {}}", ecmaFeatures: features }, + { code: "var x = {x: y}", ecmaFeatures: features }, + { code: "var x = {x: y, y: z}", ecmaFeatures: features}, + { code: "var x = {x: y, y: z, z: 'z'}", ecmaFeatures: features}, + { code: "var x = {x() {}, y: z, l(){}}", ecmaFeatures: features}, + { code: "var x = {x: y, y: z, a: b}", ecmaFeatures: features}, + { code: "var x = {x: y, y: z, 'a': b}", ecmaFeatures: features}, + { code: "var x = {x: y, y() {}, z: a}", ecmaFeatures: features}, + { code: "doSomething({x: y})", ecmaFeatures: features}, + { code: "doSomething({'x': y})", ecmaFeatures: features}, + { code: "doSomething({x: 'x'})", ecmaFeatures: features}, + { code: "doSomething({'x': 'x'})", ecmaFeatures: features}, + { code: "doSomething({y() {}})", ecmaFeatures: features}, + { code: "doSomething({x: y, y() {}})", ecmaFeatures: features}, + { code: "doSomething({y() {}, z: a})", ecmaFeatures: features}, + { code: "!{ a: function a(){} };", ecmaFeatures: features }, + + // arrows functions are still alright + { code: "var x = {y: (x)=>x}", ecmaFeatures: features }, + { code: "doSomething({y: (x)=>x})", ecmaFeatures: features }, + { code: "var x = {y: (x)=>x, y: a}", ecmaFeatures: features }, + { code: "doSomething({x, y: (x)=>x})", ecmaFeatures: features }, + + // getters and setters are ok + { code: "var x = {get y() {}}", ecmaFeatures: features }, + { code: "var x = {set y(z) {}}", ecmaFeatures: features }, + { code: "var x = {get y() {}, set y(z) {}}", ecmaFeatures: features }, + { code: "doSomething({get y() {}})", ecmaFeatures: features }, + { code: "doSomething({set y(z) {}})", ecmaFeatures: features }, + { code: "doSomething({get y() {}, set y(z) {}})", ecmaFeatures: features }, + + // options + { code: "var x = {y() {}}", ecmaFeatures: features, args: [2, "methods"] }, + { code: "var x = {x, y() {}, a:b}", ecmaFeatures: features, args: [2, "methods"] }, + { code: "var x = {y}", ecmaFeatures: features, args: [2, "properties"] }, + { code: "var x = {y: {b}}", ecmaFeatures: features, args: [2, "properties"] }, + { code: "var x = {a: n, c: d, f: g}", ecmaFeatures: features, args: [2, "never"] }, + { code: "var x = {a: function(){}, b: {c: d}}", ecmaFeatures: features, args: [2, "never"] } + ], + + invalid: [ + { code: "var x = {x: x}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "var x = {'x': x}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "var x = {y: y, x: x}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected property shorthand.", type: "Property" }] }, + { code: "var x = {y: z, x: x, a: b}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "var x = {y: function() {}}", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }] }, + { code: "var x = {y: function*() {}}", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }] }, + { code: "var x = {x: y, y: z, a: a}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "var x = {x: y, y: z, a: function(){}, b() {}}", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }] }, + { code: "var x = {x: x, y: function() {}}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected method shorthand.", type: "Property" }]}, + { code: "doSomething({x: x})", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "doSomething({'x': x})", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "doSomething({a: 'a', 'x': x})", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }] }, + { code: "doSomething({y: function() {}})", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }] }, + + // options + { code: "var x = {y: function() {}}", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }], args: [2, "methods"] }, + { code: "var x = {x, y() {}, z: function() {}}", ecmaFeatures: features, errors: [{ message: "Expected method shorthand.", type: "Property" }], args: [2, "methods"] }, + { code: "var x = {x: x}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }], args: [2, "properties"] }, + { code: "var x = {a, b, c(){}, x: x}", ecmaFeatures: features, errors: [{ message: "Expected property shorthand.", type: "Property" }], args: [2, "properties"] }, + { code: "var x = {y() {}}", ecmaFeatures: features, errors: [{ message: "Expected longform method syntax.", type: "Property" }], args: [2, "never"] }, + { code: "var x = {*y() {}}", ecmaFeatures: features, errors: [{ message: "Expected longform method syntax.", type: "Property" }], args: [2, "never"] }, + { code: "var x = {y}", ecmaFeatures: features, errors: [{ message: "Expected longform property syntax.", type: "Property" }], args: [2, "never"]}, + { code: "var x = {y, a: b, *x(){}}", ecmaFeatures: features, errors: [{ message: "Expected longform property syntax.", type: "Property" }, { message: "Expected longform method syntax.", type: "Property" }], args: [2, "never"]}, + { code: "var x = {y: {x}}", ecmaFeatures: features, errors: [{ message: "Expected longform property syntax.", type: "Property" }], args: [2, "never"]} + ] +}); \ No newline at end of file