Merge pull request babel/eslint-plugin-babel#131 from lyleunderwood/do-expressions
add no-unused-expressions with do expressions support
This commit is contained in:
parent
1037e37418
commit
bc15f0627d
@ -32,7 +32,8 @@ original ones as well!).
|
||||
"babel/no-invalid-this": 1,
|
||||
"babel/object-curly-spacing": 1,
|
||||
"babel/quotes": 1,
|
||||
"babel/semi": 1
|
||||
"babel/semi": 1,
|
||||
"babel/no-unused-expressions": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -47,6 +48,7 @@ Each rule corresponds to a core `eslint` rule, and has the same options.
|
||||
- `babel/object-curly-spacing`: doesn't complain about `export x from "mod";` or `export * as x from "mod";` (🛠)
|
||||
- `babel/quotes`: doesn't complain about JSX fragment shorthand syntax (`<>foo</>;`)
|
||||
- `babel/semi`: doesn't fail when using `for await (let something of {})`. Includes class properties (🛠)
|
||||
- `babel/no-unused-expressions`: doesn't fail when using `do` expressions
|
||||
|
||||
#### Deprecated
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ module.exports = {
|
||||
'object-shorthand': require('./rules/object-shorthand'),
|
||||
'quotes': require('./rules/quotes'),
|
||||
'semi': require('./rules/semi'),
|
||||
'no-unused-expressions': require('./rules/no-unused-expressions'),
|
||||
},
|
||||
rulesConfig: {
|
||||
'generator-star-spacing': 0,
|
||||
@ -28,5 +29,6 @@ module.exports = {
|
||||
'no-invalid-this': 0,
|
||||
'quotes': 0,
|
||||
'semi': 0,
|
||||
'no-unused-expressions': 0,
|
||||
}
|
||||
};
|
||||
|
||||
49
eslint/babel-eslint-plugin/rules/no-unused-expressions.js
Normal file
49
eslint/babel-eslint-plugin/rules/no-unused-expressions.js
Normal file
@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
|
||||
const ruleComposer = require('eslint-rule-composer');
|
||||
const eslint = require('eslint');
|
||||
const rule = new eslint.Linter().getRules().get('no-unused-expressions');
|
||||
|
||||
/**
|
||||
* @param {ASTNode} node - any node
|
||||
* @returns {boolean} whether the given node is either an IfStatement or an
|
||||
* ExpressionStatement and is the last node in the body of a BlockStatement
|
||||
*/
|
||||
function isFinalStatementInBlockStatement(node) {
|
||||
const parent = node.parent;
|
||||
return /^(?:If|Expression)Statement$/.test(node.type) &&
|
||||
parent.type === 'BlockStatement' &&
|
||||
parent.body[parent.body.length - 1] === node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ASTNode} node - any node
|
||||
* @returns {boolean} whether the given node represents an unbroken chain of
|
||||
* tail ExpressionStatements and IfStatements within a DoExpression
|
||||
*/
|
||||
function isInDoStatement(node) {
|
||||
if (!node) return false;
|
||||
|
||||
if (node.type === 'DoExpression') return true;
|
||||
|
||||
// this is an `else if`
|
||||
if (
|
||||
node.type === 'IfStatement' &&
|
||||
node.parent &&
|
||||
node.parent.type === 'IfStatement'
|
||||
) {
|
||||
return isInDoStatement(node.parent);
|
||||
}
|
||||
|
||||
if (isFinalStatementInBlockStatement(node)) {
|
||||
return isInDoStatement(node.parent.parent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = ruleComposer.filterReports(
|
||||
rule,
|
||||
(problem, metadata) => !isInDoStatement(problem.node)
|
||||
);
|
||||
|
||||
143
eslint/babel-eslint-plugin/tests/rules/no-unused-expressions.js
Normal file
143
eslint/babel-eslint-plugin/tests/rules/no-unused-expressions.js
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @fileoverview Tests for no-unused-expressions rule.
|
||||
* @author Michael Ficarra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const rule = require("../../rules/no-unused-expressions"),
|
||||
RuleTester = require("../RuleTester");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Tests
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
ruleTester.run("no-unused-expressions", rule, {
|
||||
valid: [
|
||||
// Original test cases.
|
||||
"function f(){}",
|
||||
"a = b",
|
||||
"new a",
|
||||
"{}",
|
||||
"f(); g()",
|
||||
"i++",
|
||||
"a()",
|
||||
{ code: "a && a()", options: [{ allowShortCircuit: true }] },
|
||||
{ code: "a() || (b = c)", options: [{ allowShortCircuit: true }] },
|
||||
{ code: "a ? b() : c()", options: [{ allowTernary: true }] },
|
||||
{ code: "a ? b() || (c = d) : e()", options: [{ allowShortCircuit: true, allowTernary: true }] },
|
||||
"delete foo.bar",
|
||||
"void new C",
|
||||
"\"use strict\";",
|
||||
"\"directive one\"; \"directive two\"; f();",
|
||||
"function foo() {\"use strict\"; return true; }",
|
||||
{ code: "var foo = () => {\"use strict\"; return true; }", parserOptions: { ecmaVersion: 6 } },
|
||||
"function foo() {\"directive one\"; \"directive two\"; f(); }",
|
||||
"function foo() { var foo = \"use strict\"; return true; }",
|
||||
{
|
||||
code: "function* foo(){ yield 0; }",
|
||||
parserOptions: { ecmaVersion: 6 }
|
||||
},
|
||||
{
|
||||
code: "async function foo() { await 5; }",
|
||||
parserOptions: { ecmaVersion: 8 }
|
||||
},
|
||||
{
|
||||
code: "async function foo() { await foo.bar; }",
|
||||
parserOptions: { ecmaVersion: 8 }
|
||||
},
|
||||
{
|
||||
code: "async function foo() { bar && await baz; }",
|
||||
options: [{ allowShortCircuit: true }],
|
||||
parserOptions: { ecmaVersion: 8 }
|
||||
},
|
||||
{
|
||||
code: "async function foo() { foo ? await bar : await baz; }",
|
||||
options: [{ allowTernary: true }],
|
||||
parserOptions: { ecmaVersion: 8 }
|
||||
},
|
||||
{
|
||||
code: "tag`tagged template literal`",
|
||||
options: [{ allowTaggedTemplates: true }],
|
||||
parserOptions: { ecmaVersion: 6 }
|
||||
},
|
||||
{
|
||||
code: "shouldNotBeAffectedByAllowTemplateTagsOption()",
|
||||
options: [{ allowTaggedTemplates: true }],
|
||||
parserOptions: { ecmaVersion: 6 }
|
||||
},
|
||||
|
||||
// Babel-specific test cases.
|
||||
"let a = do { if (foo) { foo.bar } }",
|
||||
"let a = do { foo }",
|
||||
"let a = do { let b = 2; foo; }",
|
||||
"let a = do { (foo + 1) }",
|
||||
"let a = do { if (foo) { if (foo.bar) { foo.bar } } }",
|
||||
"let a = do { if (foo) { if (foo.bar) { foo.bar } else if (foo.baz) { foo.baz } } }",
|
||||
|
||||
],
|
||||
invalid: [
|
||||
{ code: "0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "f(), 0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "{0}", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "[]", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a && b();", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a() || false", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a || (b = c)", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a ? b() || (c = d) : e", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{
|
||||
code: "`untagged template literal`",
|
||||
parserOptions: { ecmaVersion: 6 },
|
||||
errors: ["Expected an assignment or function call and instead saw an expression."]
|
||||
},
|
||||
{
|
||||
code: "tag`tagged template literal`",
|
||||
parserOptions: { ecmaVersion: 6 },
|
||||
errors: ["Expected an assignment or function call and instead saw an expression."]
|
||||
},
|
||||
{ code: "a && b()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a ? b() : c()", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a || b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a() && b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a ? b : 0", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "a ? b : c()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "foo.bar;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "!a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "+a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "\"directive one\"; f(); \"directive two\";", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "function foo() {\"directive one\"; f(); \"directive two\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "if (0) { \"not a directive\"; f(); }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "function foo() { var foo = true; \"use strict\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "var foo = () => { var foo = true; \"use strict\"; }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{
|
||||
code: "`untagged template literal`",
|
||||
options: [{ allowTaggedTemplates: true }],
|
||||
parserOptions: { ecmaVersion: 6 },
|
||||
errors: ["Expected an assignment or function call and instead saw an expression."]
|
||||
},
|
||||
{
|
||||
code: "`untagged template literal`",
|
||||
options: [{ allowTaggedTemplates: false }],
|
||||
parserOptions: { ecmaVersion: 6 },
|
||||
errors: ["Expected an assignment or function call and instead saw an expression."]
|
||||
},
|
||||
{
|
||||
code: "tag`tagged template literal`",
|
||||
options: [{ allowTaggedTemplates: false }],
|
||||
parserOptions: { ecmaVersion: 6 },
|
||||
errors: ["Expected an assignment or function call and instead saw an expression."]
|
||||
},
|
||||
|
||||
// Babel-specific test cases.
|
||||
{ code: "let a = do { foo; let b = 2; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
{ code: "let a = do { if (foo) { foo.bar } else { a; bar.foo } }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
|
||||
|
||||
]
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user