From 1055f16fc6f78cc553f0b1462e8af44244c1f84b Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Thu, 11 Nov 2021 02:48:33 +0100 Subject: [PATCH] docs: no-unused-expressions - class static blocks don't have directives (#15283) Refs #15016 --- docs/rules/no-unused-expressions.md | 54 +++++++++++++++++++----- lib/rules/no-unused-expressions.js | 6 +++ tests/lib/rules/no-unused-expressions.js | 23 ++++++++++ 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/docs/rules/no-unused-expressions.md b/docs/rules/no-unused-expressions.md index 1557725a193..89cfb334e80 100644 --- a/docs/rules/no-unused-expressions.md +++ b/docs/rules/no-unused-expressions.md @@ -62,16 +62,6 @@ injectGlobal`body{ color: red; }` ``` -Note that one or more string expression statements (with or without semi-colons) will only be considered as unused if they are not in the beginning of a script, module, or function (alone and uninterrupted by other statements). Otherwise, they will be treated as part of a "directive prologue", a section potentially usable by JavaScript engines. This includes "strict mode" directives. - -```js -"use strict"; -"use asm" -"use stricter"; -"use babel" -"any other strings like this in the prologue"; -``` - Examples of **correct** code for the default `{ "allowShortCircuit": false, "allowTernary": false }` options: ```js @@ -96,6 +86,50 @@ delete a.b void a ``` +Note that one or more string expression statements (with or without semi-colons) will only be considered as unused if they are not in the beginning of a script, module, or function (alone and uninterrupted by other statements). Otherwise, they will be treated as part of a "directive prologue", a section potentially usable by JavaScript engines. This includes "strict mode" directives. + +Examples of **correct** code for this rule in regard to directives: + +```js +/*eslint no-unused-expressions: "error"*/ + +"use strict"; +"use asm" +"use stricter"; +"use babel" +"any other strings like this in the directive prologue"; +"this is still the directive prologue"; + +function foo() { + "bar"; +} + +class Foo { + someMethod() { + "use strict"; + } +} +``` + +Examples of **incorrect** code for this rule in regard to directives: + +```js +/*eslint no-unused-expressions: "error"*/ + +doSomething(); +"use strict"; // this isn't in a directive prologue, because there is a non-directive statement before it + +function foo() { + "bar" + 1; +} + +class Foo { + static { + "use strict"; // class static blocks do not have directive prologues + } +} +``` + ### allowShortCircuit Examples of **incorrect** code for the `{ "allowShortCircuit": true }` option: diff --git a/lib/rules/no-unused-expressions.js b/lib/rules/no-unused-expressions.js index 3bb816df778..2081a518b30 100644 --- a/lib/rules/no-unused-expressions.js +++ b/lib/rules/no-unused-expressions.js @@ -115,6 +115,12 @@ module.exports = { const parent = ancestors[ancestors.length - 1], grandparent = ancestors[ancestors.length - 2]; + /** + * https://tc39.es/ecma262/#directive-prologue + * + * Only `FunctionBody`, `ScriptBody` and `ModuleBody` can have directive prologue. + * Class static blocks do not have directive prologue. + */ return (parent.type === "Program" || parent.type === "BlockStatement" && (/Function/u.test(grandparent.type))) && directives(parent).indexOf(node) >= 0; diff --git a/tests/lib/rules/no-unused-expressions.js b/tests/lib/rules/no-unused-expressions.js index 6f49a0a24fb..7cf11a9a3ea 100644 --- a/tests/lib/rules/no-unused-expressions.js +++ b/tests/lib/rules/no-unused-expressions.js @@ -190,6 +190,29 @@ ruleTester.run("no-unused-expressions", rule, { options: [{ enforceForJSX: true }], parserOptions: { ecmaFeatures: { jsx: true } }, errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }] + }, + + // class static blocks do not have directive prologues + { + code: "class C { static { 'use strict'; } }", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }] + }, + { + code: "class C { static { \n'foo'\n'bar'\n } }", + parserOptions: { ecmaVersion: 2022 }, + errors: [ + { + messageId: "unusedExpression", + type: "ExpressionStatement", + line: 2 + }, + { + messageId: "unusedExpression", + type: "ExpressionStatement", + line: 3 + } + ] } ] });