Skip to content

Commit

Permalink
fix(eslint-plugin): add isTypeAssertion utility function (#1369)
Browse files Browse the repository at this point in the history
While working on a new rule, I noticed that there were a few places that we didn't check for both angle bracket and as assertions.
This introduces a utility function which does that, and uses it everywhere.
  • Loading branch information
bradzacher committed Dec 21, 2019
1 parent bac780c commit bb1671e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 39 deletions.
18 changes: 3 additions & 15 deletions packages/eslint-plugin/src/rules/explicit-function-return-type.ts
Expand Up @@ -161,18 +161,6 @@ export default util.createRule<Options, MessageIds>({
return parent.type === AST_NODE_TYPES.NewExpression;
}

/**
* Checks if a node is a type cast
* `(() => {}) as Foo`
* `<Foo>(() => {})`
*/
function isTypeCast(node: TSESTree.Node): boolean {
return (
node.type === AST_NODE_TYPES.TSAsExpression ||
node.type === AST_NODE_TYPES.TSTypeAssertion
);
}

/**
* Checks if a node belongs to:
* `const x: Foo = { prop: () => {} }`
Expand All @@ -199,7 +187,7 @@ export default util.createRule<Options, MessageIds>({
}

return (
isTypeCast(parent) ||
util.isTypeAssertion(parent) ||
isClassPropertyWithTypeAnnotation(parent) ||
isVariableDeclaratorWithTypeAnnotation(parent) ||
isFunctionArgument(parent)
Expand Down Expand Up @@ -274,7 +262,7 @@ export default util.createRule<Options, MessageIds>({
node: TSESTree.ArrowFunctionExpression,
): boolean {
const { body } = node;
if (body.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(body)) {
const { typeAnnotation } = body;
if (typeAnnotation.type === AST_NODE_TYPES.TSTypeReference) {
const { typeName } = typeAnnotation;
Expand Down Expand Up @@ -331,7 +319,7 @@ export default util.createRule<Options, MessageIds>({
/* istanbul ignore else */ if (node.parent) {
if (options.allowTypedFunctionExpressions) {
if (
isTypeCast(node.parent) ||
util.isTypeAssertion(node.parent) ||
isVariableDeclaratorWithTypeAnnotation(node.parent) ||
isClassPropertyWithTypeAnnotation(node.parent) ||
isPropertyOfObjectWithType(node.parent) ||
Expand Down
42 changes: 18 additions & 24 deletions packages/eslint-plugin/src/rules/no-extra-parens.ts
Expand Up @@ -35,7 +35,7 @@ export default util.createRule<Options, MessageIds>({
const rule = rules.BinaryExpression as (n: typeof node) => void;

// makes the rule think it should skip the left or right
if (node.left.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.left)) {
return rule({
...node,
left: {
Expand All @@ -44,7 +44,7 @@ export default util.createRule<Options, MessageIds>({
},
});
}
if (node.right.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.right)) {
return rule({
...node,
right: {
Expand All @@ -61,7 +61,7 @@ export default util.createRule<Options, MessageIds>({
): void {
const rule = rules.CallExpression as (n: typeof node) => void;

if (node.callee.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.callee)) {
// reduces the precedence of the node so the rule thinks it needs to be wrapped
return rule({
...node,
Expand All @@ -79,7 +79,7 @@ export default util.createRule<Options, MessageIds>({
): void {
const rule = rules.UnaryExpression as (n: typeof node) => void;

if (node.argument.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.argument)) {
// reduces the precedence of the node so the rule thinks it needs to be wrapped
return rule({
...node,
Expand All @@ -96,7 +96,7 @@ export default util.createRule<Options, MessageIds>({
const overrides: TSESLint.RuleListener = {
// ArrayExpression
ArrowFunctionExpression(node) {
if (node.body.type !== AST_NODE_TYPES.TSAsExpression) {
if (!util.isTypeAssertion(node.body)) {
return rules.ArrowFunctionExpression(node);
}
},
Expand All @@ -108,7 +108,7 @@ export default util.createRule<Options, MessageIds>({
// ClassExpression
ConditionalExpression(node) {
// reduces the precedence of the node so the rule thinks it needs to be wrapped
if (node.test.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.test)) {
return rules.ConditionalExpression({
...node,
test: {
Expand All @@ -117,7 +117,7 @@ export default util.createRule<Options, MessageIds>({
},
});
}
if (node.consequent.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.consequent)) {
return rules.ConditionalExpression({
...node,
consequent: {
Expand All @@ -126,7 +126,7 @@ export default util.createRule<Options, MessageIds>({
},
});
}
if (node.alternate.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.alternate)) {
// reduces the precedence of the node so the rule thinks it needs to be rapped
return rules.ConditionalExpression({
...node,
Expand All @@ -142,7 +142,7 @@ export default util.createRule<Options, MessageIds>({
'ForInStatement, ForOfStatement'(
node: TSESTree.ForInStatement | TSESTree.ForOfStatement,
) {
if (node.right.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.right)) {
// makes the rule skip checking of the right
return rules['ForInStatement, ForOfStatement']({
...node,
Expand All @@ -158,19 +158,19 @@ export default util.createRule<Options, MessageIds>({
},
ForStatement(node) {
// make the rule skip the piece by removing it entirely
if (node.init && node.init.type === AST_NODE_TYPES.TSAsExpression) {
if (node.init && util.isTypeAssertion(node.init)) {
return rules.ForStatement({
...node,
init: null,
});
}
if (node.test && node.test.type === AST_NODE_TYPES.TSAsExpression) {
if (node.test && util.isTypeAssertion(node.test)) {
return rules.ForStatement({
...node,
test: null,
});
}
if (node.update && node.update.type === AST_NODE_TYPES.TSAsExpression) {
if (node.update && util.isTypeAssertion(node.update)) {
return rules.ForStatement({
...node,
update: null,
Expand All @@ -180,14 +180,14 @@ export default util.createRule<Options, MessageIds>({
return rules.ForStatement(node);
},
'ForStatement > *.init:exit'(node: TSESTree.Node) {
if (node.type !== AST_NODE_TYPES.TSAsExpression) {
if (!util.isTypeAssertion(node)) {
return rules['ForStatement > *.init:exit'](node);
}
},
// IfStatement
LogicalExpression: binaryExp,
MemberExpression(node) {
if (node.object.type === AST_NODE_TYPES.TSAsExpression) {
if (util.isTypeAssertion(node.object)) {
// reduces the precedence of the node so the rule thinks it needs to be wrapped
return rules.MemberExpression({
...node,
Expand All @@ -205,21 +205,18 @@ export default util.createRule<Options, MessageIds>({
// ReturnStatement
// SequenceExpression
SpreadElement(node) {
if (node.argument.type !== AST_NODE_TYPES.TSAsExpression) {
if (!util.isTypeAssertion(node.argument)) {
return rules.SpreadElement(node);
}
},
SwitchCase(node) {
if (node.test && node.test.type !== AST_NODE_TYPES.TSAsExpression) {
if (node.test && !util.isTypeAssertion(node.test)) {
return rules.SwitchCase(node);
}
},
// SwitchStatement
ThrowStatement(node) {
if (
node.argument &&
node.argument.type !== AST_NODE_TYPES.TSAsExpression
) {
if (node.argument && !util.isTypeAssertion(node.argument)) {
return rules.ThrowStatement(node);
}
},
Expand All @@ -229,10 +226,7 @@ export default util.createRule<Options, MessageIds>({
// WhileStatement
// WithStatement - i'm not going to even bother implementing this terrible and never used feature
YieldExpression(node) {
if (
node.argument &&
node.argument.type !== AST_NODE_TYPES.TSAsExpression
) {
if (node.argument && !util.isTypeAssertion(node.argument)) {
return rules.YieldExpression(node);
}
},
Expand Down
18 changes: 18 additions & 0 deletions packages/eslint-plugin/src/util/astUtils.ts
Expand Up @@ -61,7 +61,25 @@ function isTokenOnSameLine(
return left.loc.end.line === right.loc.start.line;
}

/**
* Checks if a node is a type assertion:
* - x as foo
* - <foo>x
*/
function isTypeAssertion(
node: TSESTree.Node | undefined | null,
): node is TSESTree.TSAsExpression | TSESTree.TSTypeAssertion {
if (!node) {
return false;
}
return (
node.type === AST_NODE_TYPES.TSAsExpression ||
node.type === AST_NODE_TYPES.TSTypeAssertion
);
}

export {
isTypeAssertion,
isNonNullAssertionPunctuator,
isNotNonNullAssertionPunctuator,
isNotOptionalChainPunctuator,
Expand Down

0 comments on commit bb1671e

Please sign in to comment.