Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(eslint-plugin): add isTypeAssertion utility function #1369

Merged
merged 1 commit into from Dec 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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