forked from lightscript/lightscript-eslint
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Patch
no-unused-expressions
rule
- Loading branch information
Showing
7 changed files
with
155 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/** | ||
* @fileoverview Flag expressions in statement position that do not side effect | ||
* @author Michael Ficarra | ||
*/ | ||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: "disallow unused expressions", | ||
category: "Best Practices", | ||
recommended: false, | ||
url: "https://eslint.org/docs/rules/no-unused-expressions" | ||
}, | ||
|
||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowShortCircuit: { | ||
type: "boolean" | ||
}, | ||
allowTernary: { | ||
type: "boolean" | ||
}, | ||
allowTaggedTemplates: { | ||
type: "boolean" | ||
} | ||
}, | ||
additionalProperties: false | ||
} | ||
] | ||
}, | ||
|
||
create(context) { | ||
const config = context.options[0] || {}, | ||
allowShortCircuit = config.allowShortCircuit || false, | ||
allowTernary = config.allowTernary || false, | ||
allowTaggedTemplates = config.allowTaggedTemplates || false; | ||
|
||
/** | ||
* @param {ASTNode} node - any node | ||
* @returns {boolean} whether the given node structurally represents a directive | ||
*/ | ||
function looksLikeDirective(node) { | ||
return node.type === "ExpressionStatement" && | ||
node.expression.type === "Literal" && typeof node.expression.value === "string"; | ||
} | ||
|
||
/** | ||
* @param {Function} predicate - ([a] -> Boolean) the function used to make the determination | ||
* @param {a[]} list - the input list | ||
* @returns {a[]} the leading sequence of members in the given list that pass the given predicate | ||
*/ | ||
function takeWhile(predicate, list) { | ||
for (let i = 0; i < list.length; ++i) { | ||
if (!predicate(list[i])) { | ||
return list.slice(0, i); | ||
} | ||
} | ||
return list.slice(); | ||
} | ||
|
||
/** | ||
* @param {ASTNode} node - a Program or BlockStatement node | ||
* @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body | ||
*/ | ||
function directives(node) { | ||
return takeWhile(looksLikeDirective, node.body); | ||
} | ||
|
||
/** | ||
* @param {ASTNode} node - any node | ||
* @param {ASTNode[]} ancestors - the given node's ancestors | ||
* @returns {boolean} whether the given node is considered a directive in its current position | ||
*/ | ||
function isDirective(node, ancestors) { | ||
const parent = ancestors[ancestors.length - 1], | ||
grandparent = ancestors[ancestors.length - 2]; | ||
|
||
return (parent.type === "Program" || parent.type === "BlockStatement" && | ||
(/Function/.test(grandparent.type))) && | ||
directives(parent).indexOf(node) >= 0; | ||
} | ||
|
||
/** | ||
* Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags. | ||
* @param {ASTNode} node - any node | ||
* @returns {boolean} whether the given node is a valid expression | ||
*/ | ||
function isValidExpression(node) { | ||
if (allowTernary) { | ||
|
||
// Recursive check for ternary and logical expressions | ||
if (node.type === "ConditionalExpression") { | ||
return isValidExpression(node.consequent) && isValidExpression(node.alternate); | ||
} | ||
} | ||
|
||
if (allowShortCircuit) { | ||
if (node.type === "LogicalExpression") { | ||
return isValidExpression(node.right); | ||
} | ||
} | ||
|
||
if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") { | ||
return true; | ||
} | ||
|
||
return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) || | ||
(node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); | ||
} | ||
|
||
return { | ||
ExpressionStatement(node) { | ||
// LSC: if node is implicitly returned, it's fine | ||
if (context.parserServices.isTailNode(node)) return; | ||
|
||
if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) { | ||
context.report({ node, message: "Expected an assignment or function call and instead saw an expression." }); | ||
} | ||
} | ||
}; | ||
|
||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
test/fixtures/lightscript/brokenRules/no-unused-expressions/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
f() -> | ||
1 |
5 changes: 5 additions & 0 deletions
5
test/fixtures/lightscript/brokenRules/no-unused-expressions/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"rules": { | ||
"no-unused-expressions": 1 | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
test/fixtures/lightscript/brokenRules/no-unused-expressions/output.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[] |