From e0dc925bbe148022df6b43dd6965ebca661915fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=B8=85=E9=9B=A8?= Date: Tue, 27 Jul 2021 22:02:09 +0800 Subject: [PATCH] feat(traverse): specific return type for virtual types' validators (#13578) * feat(traverse): specific return type for virtual types' validators update generator script to use virtualType.types[0] as it's type fix #13576 * fix: remove unused ts-expect-error so glad that it works * feat: use VirtualTypeAliases to generate validators for virtual types * fix: return boolean when it doesn't have any alias * fix: use type only import and simplify condition --- .../scripts/generators/validators.js | 9 +++++ .../babel-traverse/src/path/evaluation.ts | 4 -- .../src/path/generated/validators.ts | 37 ++++++++++++++----- .../babel-traverse/src/path/introspection.ts | 1 - 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/packages/babel-traverse/scripts/generators/validators.js b/packages/babel-traverse/scripts/generators/validators.js index eae98a33e2..a3ec31a3eb 100644 --- a/packages/babel-traverse/scripts/generators/validators.js +++ b/packages/babel-traverse/scripts/generators/validators.js @@ -9,6 +9,7 @@ export default function generateValidators() { */ import * as t from "@babel/types"; import NodePath from "../index"; +import type { VirtualTypeAliases } from "./virtual-types"; export interface NodePathValidators { `; @@ -18,10 +19,18 @@ export interface NodePathValidators { } for (const type of Object.keys(virtualTypes)) { + const { types } = virtualTypes[type]; if (type[0] === "_") continue; if (definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]) { output += `is${type}(opts?: object): this is NodePath;`; + } else if (types /* in VirtualTypeAliases */) { + output += `is${type}(opts?: object): this is NodePath;`; } else { + // if it don't have types, then VirtualTypeAliases[type] is t.Node + // which TS marked as always true + // eg. if (path.isBlockScope()) return; + // path resolved to `never` here + // so we have to return boolean instead of this is NodePath here output += `is${type}(opts?: object): boolean;`; } } diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 09b509f1b6..de673dd007 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -153,7 +153,6 @@ function _evaluate(path: NodePath, state) { } if (path.isReferencedIdentifier()) { - // @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference const binding = path.scope.getBinding(path.node.name); if (binding && binding.constantViolations.length > 0) { @@ -167,13 +166,10 @@ function _evaluate(path: NodePath, state) { if (binding?.hasValue) { return binding.value; } else { - // @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference if (path.node.name === "undefined") { return binding ? deopt(binding.path, state) : undefined; - // @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference } else if (path.node.name === "Infinity") { return binding ? deopt(binding.path, state) : Infinity; - // @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference } else if (path.node.name === "NaN") { return binding ? deopt(binding.path, state) : NaN; } diff --git a/packages/babel-traverse/src/path/generated/validators.ts b/packages/babel-traverse/src/path/generated/validators.ts index 75c8badee0..7dbf7d828d 100755 --- a/packages/babel-traverse/src/path/generated/validators.ts +++ b/packages/babel-traverse/src/path/generated/validators.ts @@ -4,6 +4,7 @@ */ import * as t from "@babel/types"; import NodePath from "../index"; +import type { VirtualTypeAliases } from "./virtual-types"; export interface NodePathValidators { isAnyTypeAnnotation(opts?: object): this is NodePath; @@ -416,22 +417,38 @@ export interface NodePathValidators { isWhileStatement(opts?: object): this is NodePath; isWithStatement(opts?: object): this is NodePath; isYieldExpression(opts?: object): this is NodePath; - isReferencedIdentifier(opts?: object): boolean; - isReferencedMemberExpression(opts?: object): boolean; - isBindingIdentifier(opts?: object): boolean; + isReferencedIdentifier( + opts?: object, + ): this is NodePath; + isReferencedMemberExpression( + opts?: object, + ): this is NodePath; + isBindingIdentifier( + opts?: object, + ): this is NodePath; isStatement(opts?: object): this is NodePath; isExpression(opts?: object): this is NodePath; - isScope(opts?: object): boolean; + isScope(opts?: object): this is NodePath; isReferenced(opts?: object): boolean; isBlockScoped(opts?: object): boolean; - isVar(opts?: object): boolean; + isVar(opts?: object): this is NodePath; isUser(opts?: object): boolean; isGenerated(opts?: object): boolean; isPure(opts?: object): boolean; isFlow(opts?: object): this is NodePath; - isRestProperty(opts?: object): boolean; - isSpreadProperty(opts?: object): boolean; - isExistentialTypeParam(opts?: object): boolean; - isNumericLiteralTypeAnnotation(opts?: object): boolean; - isForAwaitStatement(opts?: object): boolean; + isRestProperty( + opts?: object, + ): this is NodePath; + isSpreadProperty( + opts?: object, + ): this is NodePath; + isExistentialTypeParam( + opts?: object, + ): this is NodePath; + isNumericLiteralTypeAnnotation( + opts?: object, + ): this is NodePath; + isForAwaitStatement( + opts?: object, + ): this is NodePath; } diff --git a/packages/babel-traverse/src/path/introspection.ts b/packages/babel-traverse/src/path/introspection.ts index bd569e77e3..38d50dbff9 100644 --- a/packages/babel-traverse/src/path/introspection.ts +++ b/packages/babel-traverse/src/path/introspection.ts @@ -480,7 +480,6 @@ export function _resolve( // otherwise it's a request for a pattern and that's a bit more tricky } } else if (this.isReferencedIdentifier()) { - // @ts-expect-error todo(flow->ts): think about options to improve type refinements const binding = this.scope.getBinding(this.node.name); if (!binding) return;