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
This commit is contained in:
parent
790c5180d4
commit
e0dc925bbe
@ -9,6 +9,7 @@ export default function generateValidators() {
|
|||||||
*/
|
*/
|
||||||
import * as t from "@babel/types";
|
import * as t from "@babel/types";
|
||||||
import NodePath from "../index";
|
import NodePath from "../index";
|
||||||
|
import type { VirtualTypeAliases } from "./virtual-types";
|
||||||
|
|
||||||
export interface NodePathValidators {
|
export interface NodePathValidators {
|
||||||
`;
|
`;
|
||||||
@ -18,10 +19,18 @@ export interface NodePathValidators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const type of Object.keys(virtualTypes)) {
|
for (const type of Object.keys(virtualTypes)) {
|
||||||
|
const { types } = virtualTypes[type];
|
||||||
if (type[0] === "_") continue;
|
if (type[0] === "_") continue;
|
||||||
if (definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]) {
|
if (definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]) {
|
||||||
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
|
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
|
||||||
|
} else if (types /* in VirtualTypeAliases */) {
|
||||||
|
output += `is${type}(opts?: object): this is NodePath<VirtualTypeAliases["${type}"]>;`;
|
||||||
} else {
|
} 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<t.Node> here
|
||||||
output += `is${type}(opts?: object): boolean;`;
|
output += `is${type}(opts?: object): boolean;`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -153,7 +153,6 @@ function _evaluate(path: NodePath, state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path.isReferencedIdentifier()) {
|
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);
|
const binding = path.scope.getBinding(path.node.name);
|
||||||
|
|
||||||
if (binding && binding.constantViolations.length > 0) {
|
if (binding && binding.constantViolations.length > 0) {
|
||||||
@ -167,13 +166,10 @@ function _evaluate(path: NodePath, state) {
|
|||||||
if (binding?.hasValue) {
|
if (binding?.hasValue) {
|
||||||
return binding.value;
|
return binding.value;
|
||||||
} else {
|
} else {
|
||||||
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
|
|
||||||
if (path.node.name === "undefined") {
|
if (path.node.name === "undefined") {
|
||||||
return binding ? deopt(binding.path, state) : 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") {
|
} else if (path.node.name === "Infinity") {
|
||||||
return binding ? deopt(binding.path, state) : 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") {
|
} else if (path.node.name === "NaN") {
|
||||||
return binding ? deopt(binding.path, state) : NaN;
|
return binding ? deopt(binding.path, state) : NaN;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import * as t from "@babel/types";
|
import * as t from "@babel/types";
|
||||||
import NodePath from "../index";
|
import NodePath from "../index";
|
||||||
|
import type { VirtualTypeAliases } from "./virtual-types";
|
||||||
|
|
||||||
export interface NodePathValidators {
|
export interface NodePathValidators {
|
||||||
isAnyTypeAnnotation(opts?: object): this is NodePath<t.AnyTypeAnnotation>;
|
isAnyTypeAnnotation(opts?: object): this is NodePath<t.AnyTypeAnnotation>;
|
||||||
@ -416,22 +417,38 @@ export interface NodePathValidators {
|
|||||||
isWhileStatement(opts?: object): this is NodePath<t.WhileStatement>;
|
isWhileStatement(opts?: object): this is NodePath<t.WhileStatement>;
|
||||||
isWithStatement(opts?: object): this is NodePath<t.WithStatement>;
|
isWithStatement(opts?: object): this is NodePath<t.WithStatement>;
|
||||||
isYieldExpression(opts?: object): this is NodePath<t.YieldExpression>;
|
isYieldExpression(opts?: object): this is NodePath<t.YieldExpression>;
|
||||||
isReferencedIdentifier(opts?: object): boolean;
|
isReferencedIdentifier(
|
||||||
isReferencedMemberExpression(opts?: object): boolean;
|
opts?: object,
|
||||||
isBindingIdentifier(opts?: object): boolean;
|
): this is NodePath<VirtualTypeAliases["ReferencedIdentifier"]>;
|
||||||
|
isReferencedMemberExpression(
|
||||||
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["ReferencedMemberExpression"]>;
|
||||||
|
isBindingIdentifier(
|
||||||
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["BindingIdentifier"]>;
|
||||||
isStatement(opts?: object): this is NodePath<t.Statement>;
|
isStatement(opts?: object): this is NodePath<t.Statement>;
|
||||||
isExpression(opts?: object): this is NodePath<t.Expression>;
|
isExpression(opts?: object): this is NodePath<t.Expression>;
|
||||||
isScope(opts?: object): boolean;
|
isScope(opts?: object): this is NodePath<VirtualTypeAliases["Scope"]>;
|
||||||
isReferenced(opts?: object): boolean;
|
isReferenced(opts?: object): boolean;
|
||||||
isBlockScoped(opts?: object): boolean;
|
isBlockScoped(opts?: object): boolean;
|
||||||
isVar(opts?: object): boolean;
|
isVar(opts?: object): this is NodePath<VirtualTypeAliases["Var"]>;
|
||||||
isUser(opts?: object): boolean;
|
isUser(opts?: object): boolean;
|
||||||
isGenerated(opts?: object): boolean;
|
isGenerated(opts?: object): boolean;
|
||||||
isPure(opts?: object): boolean;
|
isPure(opts?: object): boolean;
|
||||||
isFlow(opts?: object): this is NodePath<t.Flow>;
|
isFlow(opts?: object): this is NodePath<t.Flow>;
|
||||||
isRestProperty(opts?: object): boolean;
|
isRestProperty(
|
||||||
isSpreadProperty(opts?: object): boolean;
|
opts?: object,
|
||||||
isExistentialTypeParam(opts?: object): boolean;
|
): this is NodePath<VirtualTypeAliases["RestProperty"]>;
|
||||||
isNumericLiteralTypeAnnotation(opts?: object): boolean;
|
isSpreadProperty(
|
||||||
isForAwaitStatement(opts?: object): boolean;
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["SpreadProperty"]>;
|
||||||
|
isExistentialTypeParam(
|
||||||
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["ExistentialTypeParam"]>;
|
||||||
|
isNumericLiteralTypeAnnotation(
|
||||||
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["NumericLiteralTypeAnnotation"]>;
|
||||||
|
isForAwaitStatement(
|
||||||
|
opts?: object,
|
||||||
|
): this is NodePath<VirtualTypeAliases["ForAwaitStatement"]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -480,7 +480,6 @@ export function _resolve(
|
|||||||
// otherwise it's a request for a pattern and that's a bit more tricky
|
// otherwise it's a request for a pattern and that's a bit more tricky
|
||||||
}
|
}
|
||||||
} else if (this.isReferencedIdentifier()) {
|
} 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);
|
const binding = this.scope.getBinding(this.node.name);
|
||||||
if (!binding) return;
|
if (!binding) return;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user