Add placeholders support to @babel/types and @babel/generator (#9542)
This commit is contained in:
parent
095e5c0e09
commit
15dfce33df
@ -82,3 +82,13 @@ export function DirectiveLiteral(node: Object) {
|
||||
export function InterpreterDirective(node: Object) {
|
||||
this.token(`#!${node.value}\n`);
|
||||
}
|
||||
|
||||
export function Placeholder(node: Object) {
|
||||
this.token("%%");
|
||||
this.print(node.name);
|
||||
this.token("%%");
|
||||
|
||||
if (node.expectedNode === "Statement") {
|
||||
this.semicolon();
|
||||
}
|
||||
}
|
||||
|
||||
8
packages/babel-generator/test/fixtures/misc/placeholders/input.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/misc/placeholders/input.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
var %%a%% = %%b%%
|
||||
|
||||
%%c%%
|
||||
|
||||
class %%d%% {}
|
||||
class A %%e%%
|
||||
|
||||
function %%f%%(...%%g%%) %%h%%
|
||||
3
packages/babel-generator/test/fixtures/misc/placeholders/options.json
vendored
Normal file
3
packages/babel-generator/test/fixtures/misc/placeholders/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": ["placeholders"]
|
||||
}
|
||||
8
packages/babel-generator/test/fixtures/misc/placeholders/output.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/misc/placeholders/output.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
var %%a%% = %%b%%;
|
||||
%%c%%;
|
||||
|
||||
class %%d%% {}
|
||||
|
||||
class A %%e%%
|
||||
|
||||
function %%f%%(...%%g%%) %%h%%
|
||||
@ -1,14 +1,37 @@
|
||||
"use strict";
|
||||
const definitions = require("../../lib/definitions");
|
||||
|
||||
const has = Function.call.bind(Object.prototype.hasOwnProperty);
|
||||
|
||||
function joinComparisons(leftArr, right) {
|
||||
return (
|
||||
leftArr.map(JSON.stringify).join(` === ${right} || `) + ` === ${right}`
|
||||
);
|
||||
}
|
||||
|
||||
function addIsHelper(type, aliasKeys, deprecated) {
|
||||
const targetType = JSON.stringify(type);
|
||||
let aliasSource = "";
|
||||
if (aliasKeys) {
|
||||
aliasSource =
|
||||
" || " +
|
||||
aliasKeys.map(JSON.stringify).join(" === nodeType || ") +
|
||||
" === nodeType";
|
||||
aliasSource = " || " + joinComparisons(aliasKeys, "nodeType");
|
||||
}
|
||||
|
||||
let placeholderSource = "";
|
||||
const placeholderTypes = [];
|
||||
if (
|
||||
definitions.PLACEHOLDERS.includes(type) &&
|
||||
has(definitions.FLIPPED_ALIAS_KEYS, type)
|
||||
) {
|
||||
placeholderTypes.push(type);
|
||||
}
|
||||
if (has(definitions.PLACEHOLDERS_FLIPPED_ALIAS, type)) {
|
||||
placeholderTypes.push(...definitions.PLACEHOLDERS_FLIPPED_ALIAS[type]);
|
||||
}
|
||||
if (placeholderTypes.length > 0) {
|
||||
placeholderSource =
|
||||
' || nodeType === "Placeholder" && (' +
|
||||
joinComparisons(placeholderTypes, "node.expectedNode") +
|
||||
")";
|
||||
}
|
||||
|
||||
return `export function is${type}(node: ?Object, opts?: Object): boolean {
|
||||
@ -16,7 +39,7 @@ function addIsHelper(type, aliasKeys, deprecated) {
|
||||
if (!node) return false;
|
||||
|
||||
const nodeType = node.type;
|
||||
if (nodeType === ${targetType}${aliasSource}) {
|
||||
if (nodeType === ${targetType}${aliasSource}${placeholderSource}) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -660,6 +660,9 @@ export function assertJSXClosingFragment(
|
||||
export function assertNoop(node: Object, opts?: Object = {}): void {
|
||||
assert("Noop", node, opts);
|
||||
}
|
||||
export function assertPlaceholder(node: Object, opts?: Object = {}): void {
|
||||
assert("Placeholder", node, opts);
|
||||
}
|
||||
export function assertArgumentPlaceholder(
|
||||
node: Object,
|
||||
opts?: Object = {},
|
||||
|
||||
@ -596,6 +596,10 @@ export function Noop(...args: Array<any>): Object {
|
||||
return builder("Noop", ...args);
|
||||
}
|
||||
export { Noop as noop };
|
||||
export function Placeholder(...args: Array<any>): Object {
|
||||
return builder("Placeholder", ...args);
|
||||
}
|
||||
export { Placeholder as placeholder };
|
||||
export function ArgumentPlaceholder(...args: Array<any>): Object {
|
||||
return builder("ArgumentPlaceholder", ...args);
|
||||
}
|
||||
|
||||
@ -15,6 +15,11 @@ import {
|
||||
BUILDER_KEYS,
|
||||
DEPRECATED_KEYS,
|
||||
} from "./utils";
|
||||
import {
|
||||
PLACEHOLDERS,
|
||||
PLACEHOLDERS_ALIAS,
|
||||
PLACEHOLDERS_FLIPPED_ALIAS,
|
||||
} from "./placeholders";
|
||||
|
||||
// We do this here, because at this point the visitor keys should be ready and setup
|
||||
toFastProperties(VISITOR_KEYS);
|
||||
@ -24,6 +29,9 @@ toFastProperties(NODE_FIELDS);
|
||||
toFastProperties(BUILDER_KEYS);
|
||||
toFastProperties(DEPRECATED_KEYS);
|
||||
|
||||
toFastProperties(PLACEHOLDERS_ALIAS);
|
||||
toFastProperties(PLACEHOLDERS_FLIPPED_ALIAS);
|
||||
|
||||
const TYPES: Array<string> = Object.keys(VISITOR_KEYS)
|
||||
.concat(Object.keys(FLIPPED_ALIAS_KEYS))
|
||||
.concat(Object.keys(DEPRECATED_KEYS));
|
||||
@ -35,5 +43,8 @@ export {
|
||||
NODE_FIELDS,
|
||||
BUILDER_KEYS,
|
||||
DEPRECATED_KEYS,
|
||||
PLACEHOLDERS,
|
||||
PLACEHOLDERS_ALIAS,
|
||||
PLACEHOLDERS_FLIPPED_ALIAS,
|
||||
TYPES,
|
||||
};
|
||||
|
||||
@ -1,6 +1,21 @@
|
||||
// @flow
|
||||
import defineType from "./utils";
|
||||
import defineType, { assertNodeType, assertOneOf } from "./utils";
|
||||
import { PLACEHOLDERS } from "./placeholders";
|
||||
|
||||
defineType("Noop", {
|
||||
visitor: [],
|
||||
});
|
||||
|
||||
defineType("Placeholder", {
|
||||
visitor: [],
|
||||
builder: ["expectedNode", "name"],
|
||||
// aliases: [], defined in placeholders.js
|
||||
fields: {
|
||||
name: {
|
||||
validate: assertNodeType("Identifier"),
|
||||
},
|
||||
expectedNode: {
|
||||
validate: assertOneOf(...PLACEHOLDERS),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
33
packages/babel-types/src/definitions/placeholders.js
Normal file
33
packages/babel-types/src/definitions/placeholders.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { ALIAS_KEYS } from "./utils";
|
||||
|
||||
export const PLACEHOLDERS = [
|
||||
"Identifier",
|
||||
"StringLiteral",
|
||||
"Expression",
|
||||
"Statement",
|
||||
"Declaration",
|
||||
"BlockStatement",
|
||||
"ClassBody",
|
||||
"Pattern",
|
||||
];
|
||||
|
||||
export const PLACEHOLDERS_ALIAS: { [string]: Array<string> } = {
|
||||
Declaration: ["Statement"],
|
||||
Pattern: ["PatternLike", "LVal"],
|
||||
};
|
||||
|
||||
for (const type of PLACEHOLDERS) {
|
||||
const alias = ALIAS_KEYS[type];
|
||||
if (alias && alias.length) PLACEHOLDERS_ALIAS[type] = alias;
|
||||
}
|
||||
|
||||
export const PLACEHOLDERS_FLIPPED_ALIAS: { [string]: Array<string> } = {};
|
||||
|
||||
Object.keys(PLACEHOLDERS_ALIAS).forEach(type => {
|
||||
PLACEHOLDERS_ALIAS[type].forEach(alias => {
|
||||
if (!Object.hasOwnProperty.call(PLACEHOLDERS_FLIPPED_ALIAS, alias)) {
|
||||
PLACEHOLDERS_FLIPPED_ALIAS[alias] = [];
|
||||
}
|
||||
PLACEHOLDERS_FLIPPED_ALIAS[alias].push(type);
|
||||
});
|
||||
});
|
||||
@ -100,6 +100,7 @@ export { default as isImmutable } from "./validators/isImmutable";
|
||||
export { default as isLet } from "./validators/isLet";
|
||||
export { default as isNode } from "./validators/isNode";
|
||||
export { default as isNodesEquivalent } from "./validators/isNodesEquivalent";
|
||||
export { default as isPlaceholderType } from "./validators/isPlaceholderType";
|
||||
export { default as isReferenced } from "./validators/isReferenced";
|
||||
export { default as isScope } from "./validators/isScope";
|
||||
export { default as isSpecifierDefault } from "./validators/isSpecifierDefault";
|
||||
|
||||
@ -2093,6 +2093,20 @@ export function isNoop(node: ?Object, opts?: Object): boolean {
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isPlaceholder(node: ?Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
const nodeType = node.type;
|
||||
if (nodeType === "Placeholder") {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
} else {
|
||||
return shallowEqual(node, opts);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isArgumentPlaceholder(node: ?Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
@ -3280,7 +3294,11 @@ export function isExpression(node: ?Object, opts?: Object): boolean {
|
||||
"BigIntLiteral" === nodeType ||
|
||||
"TSAsExpression" === nodeType ||
|
||||
"TSTypeAssertion" === nodeType ||
|
||||
"TSNonNullExpression" === nodeType
|
||||
"TSNonNullExpression" === nodeType ||
|
||||
(nodeType === "Placeholder" &&
|
||||
("Expression" === node.expectedNode ||
|
||||
"Identifier" === node.expectedNode ||
|
||||
"StringLiteral" === node.expectedNode))
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3331,7 +3349,8 @@ export function isScopable(node: ?Object, opts?: Object): boolean {
|
||||
"ClassExpression" === nodeType ||
|
||||
"ForOfStatement" === nodeType ||
|
||||
"ClassMethod" === nodeType ||
|
||||
"ClassPrivateMethod" === nodeType
|
||||
"ClassPrivateMethod" === nodeType ||
|
||||
(nodeType === "Placeholder" && "BlockStatement" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3362,7 +3381,8 @@ export function isBlockParent(node: ?Object, opts?: Object): boolean {
|
||||
"ArrowFunctionExpression" === nodeType ||
|
||||
"ForOfStatement" === nodeType ||
|
||||
"ClassMethod" === nodeType ||
|
||||
"ClassPrivateMethod" === nodeType
|
||||
"ClassPrivateMethod" === nodeType ||
|
||||
(nodeType === "Placeholder" && "BlockStatement" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3380,7 +3400,8 @@ export function isBlock(node: ?Object, opts?: Object): boolean {
|
||||
if (
|
||||
nodeType === "Block" ||
|
||||
"BlockStatement" === nodeType ||
|
||||
"Program" === nodeType
|
||||
"Program" === nodeType ||
|
||||
(nodeType === "Placeholder" && "BlockStatement" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3442,7 +3463,11 @@ export function isStatement(node: ?Object, opts?: Object): boolean {
|
||||
"TSModuleDeclaration" === nodeType ||
|
||||
"TSImportEqualsDeclaration" === nodeType ||
|
||||
"TSExportAssignment" === nodeType ||
|
||||
"TSNamespaceExportDeclaration" === nodeType
|
||||
"TSNamespaceExportDeclaration" === nodeType ||
|
||||
(nodeType === "Placeholder" &&
|
||||
("Statement" === node.expectedNode ||
|
||||
"Declaration" === node.expectedNode ||
|
||||
"BlockStatement" === node.expectedNode))
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3667,7 +3692,8 @@ export function isPureish(node: ?Object, opts?: Object): boolean {
|
||||
"ArrowFunctionExpression" === nodeType ||
|
||||
"ClassDeclaration" === nodeType ||
|
||||
"ClassExpression" === nodeType ||
|
||||
"BigIntLiteral" === nodeType
|
||||
"BigIntLiteral" === nodeType ||
|
||||
(nodeType === "Placeholder" && "StringLiteral" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3708,7 +3734,8 @@ export function isDeclaration(node: ?Object, opts?: Object): boolean {
|
||||
"TSInterfaceDeclaration" === nodeType ||
|
||||
"TSTypeAliasDeclaration" === nodeType ||
|
||||
"TSEnumDeclaration" === nodeType ||
|
||||
"TSModuleDeclaration" === nodeType
|
||||
"TSModuleDeclaration" === nodeType ||
|
||||
(nodeType === "Placeholder" && "Declaration" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3729,7 +3756,9 @@ export function isPatternLike(node: ?Object, opts?: Object): boolean {
|
||||
"RestElement" === nodeType ||
|
||||
"AssignmentPattern" === nodeType ||
|
||||
"ArrayPattern" === nodeType ||
|
||||
"ObjectPattern" === nodeType
|
||||
"ObjectPattern" === nodeType ||
|
||||
(nodeType === "Placeholder" &&
|
||||
("Pattern" === node.expectedNode || "Identifier" === node.expectedNode))
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3752,7 +3781,9 @@ export function isLVal(node: ?Object, opts?: Object): boolean {
|
||||
"AssignmentPattern" === nodeType ||
|
||||
"ArrayPattern" === nodeType ||
|
||||
"ObjectPattern" === nodeType ||
|
||||
"TSParameterProperty" === nodeType
|
||||
"TSParameterProperty" === nodeType ||
|
||||
(nodeType === "Placeholder" &&
|
||||
("Pattern" === node.expectedNode || "Identifier" === node.expectedNode))
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3770,7 +3801,8 @@ export function isTSEntityName(node: ?Object, opts?: Object): boolean {
|
||||
if (
|
||||
nodeType === "TSEntityName" ||
|
||||
"Identifier" === nodeType ||
|
||||
"TSQualifiedName" === nodeType
|
||||
"TSQualifiedName" === nodeType ||
|
||||
(nodeType === "Placeholder" && "Identifier" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3793,7 +3825,8 @@ export function isLiteral(node: ?Object, opts?: Object): boolean {
|
||||
"BooleanLiteral" === nodeType ||
|
||||
"RegExpLiteral" === nodeType ||
|
||||
"TemplateLiteral" === nodeType ||
|
||||
"BigIntLiteral" === nodeType
|
||||
"BigIntLiteral" === nodeType ||
|
||||
(nodeType === "Placeholder" && "StringLiteral" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3824,7 +3857,8 @@ export function isImmutable(node: ?Object, opts?: Object): boolean {
|
||||
"JSXFragment" === nodeType ||
|
||||
"JSXOpeningFragment" === nodeType ||
|
||||
"JSXClosingFragment" === nodeType ||
|
||||
"BigIntLiteral" === nodeType
|
||||
"BigIntLiteral" === nodeType ||
|
||||
(nodeType === "Placeholder" && "StringLiteral" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
@ -3940,7 +3974,8 @@ export function isPattern(node: ?Object, opts?: Object): boolean {
|
||||
nodeType === "Pattern" ||
|
||||
"AssignmentPattern" === nodeType ||
|
||||
"ArrayPattern" === nodeType ||
|
||||
"ObjectPattern" === nodeType
|
||||
"ObjectPattern" === nodeType ||
|
||||
(nodeType === "Placeholder" && "Pattern" === node.expectedNode)
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
// @flow
|
||||
import shallowEqual from "../utils/shallowEqual";
|
||||
import isType from "./isType";
|
||||
import isPlaceholderType from "./isPlaceholderType";
|
||||
import { FLIPPED_ALIAS_KEYS } from "../definitions";
|
||||
|
||||
/**
|
||||
* Returns whether `node` is of given `type`.
|
||||
@ -11,7 +13,21 @@ export default function is(type: string, node: Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
const matches = isType(node.type, type);
|
||||
if (!matches) return false;
|
||||
if (!matches) {
|
||||
if (!opts && node.type === "Placeholder" && type in FLIPPED_ALIAS_KEYS) {
|
||||
// We can only return true if the placeholder doesn't replace a real node,
|
||||
// but it replaces a category of nodes (an alias).
|
||||
//
|
||||
// t.is("Identifier", node) gives some guarantees about node's shape, so we
|
||||
// can't say that Placeholder(expectedNode: "Identifier") is an identifier
|
||||
// because it doesn't have the same properties.
|
||||
// On the other hand, t.is("Expression", node) doesn't say anything about
|
||||
// the shape of node because Expression can be many different nodes: we can,
|
||||
// and should, safely report expression placeholders as Expressions.
|
||||
return isPlaceholderType(node.expectedNode, type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
|
||||
21
packages/babel-types/src/validators/isPlaceholderType.js
Normal file
21
packages/babel-types/src/validators/isPlaceholderType.js
Normal file
@ -0,0 +1,21 @@
|
||||
// @flow
|
||||
import { PLACEHOLDERS_ALIAS } from "../definitions";
|
||||
|
||||
/**
|
||||
* Test if a `placeholderType` is a `targetType` or if `targetType` is an alias of `placeholderType`.
|
||||
*/
|
||||
export default function isPlaceholderType(
|
||||
placeholderType: ?string,
|
||||
targetType: string,
|
||||
): boolean {
|
||||
if (placeholderType === targetType) return true;
|
||||
|
||||
const aliases: ?Array<string> = PLACEHOLDERS_ALIAS[placeholderType];
|
||||
if (aliases) {
|
||||
for (const alias of aliases) {
|
||||
if (targetType === alias) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -216,4 +216,95 @@ describe("validators", function() {
|
||||
expect(t.isType(undefined, "Expression")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("placeholders", function() {
|
||||
describe("isPlaceholderType", function() {
|
||||
describe("when placeholderType is a specific node type", function() {
|
||||
const placeholder = "Identifier";
|
||||
|
||||
it("returns true if targetType is placeholderType", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "Identifier")).toBe(true);
|
||||
});
|
||||
it("returns true if targetType an alias for placeholderType", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "Expression")).toBe(true);
|
||||
});
|
||||
it("returns false for unrelated types", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "String")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when placeholderType is a generic alias type", function() {
|
||||
const placeholder = "Pattern";
|
||||
|
||||
it("returns true if targetType is placeholderType", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "Pattern")).toBe(true);
|
||||
});
|
||||
it("returns true if targetType an alias for placeholderType", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "LVal")).toBe(true);
|
||||
});
|
||||
it("returns false for unrelated types", function() {
|
||||
expect(t.isPlaceholderType(placeholder, "Expression")).toBe(false);
|
||||
});
|
||||
it("returns false if targetType is aliased by placeholderType", function() {
|
||||
// i.e. a Pattern might not be an Identifier
|
||||
expect(t.isPlaceholderType(placeholder, "Identifier")).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("is", function() {
|
||||
describe("when the placeholder matches a specific node", function() {
|
||||
const identifier = t.placeholder("Identifier", t.identifier("foo"));
|
||||
|
||||
it("returns false if targetType is expectedNode", function() {
|
||||
expect(t.is("Identifier", identifier)).toBe(false);
|
||||
});
|
||||
it("returns true if targetType is an alias", function() {
|
||||
expect(t.is("LVal", identifier)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the placeholder matches a generic alias", function() {
|
||||
const pattern = t.placeholder("Pattern", t.identifier("bar"));
|
||||
|
||||
it("returns false if targetType is aliased as expectedNode", function() {
|
||||
// i.e. a Pattern might not be an Identifier
|
||||
expect(t.is("Identifier", pattern)).toBe(false);
|
||||
});
|
||||
it("returns true if targetType is expectedNode", function() {
|
||||
expect(t.is("Pattern", pattern)).toBe(true);
|
||||
});
|
||||
it("returns true if targetType is an alias for expectedNode", function() {
|
||||
expect(t.is("LVal", pattern)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("is[Type]", function() {
|
||||
describe("when the placeholder matches a specific node", function() {
|
||||
const identifier = t.placeholder("Identifier", t.identifier("foo"));
|
||||
|
||||
it("returns false if targetType is expectedNode", function() {
|
||||
expect(t.isIdentifier(identifier)).toBe(false);
|
||||
});
|
||||
it("returns true if targetType is an alias", function() {
|
||||
expect(t.isLVal(identifier)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the placeholder matches a generic alias", function() {
|
||||
const pattern = t.placeholder("Pattern", t.identifier("bar"));
|
||||
|
||||
it("returns false if targetType is aliased as expectedNode", function() {
|
||||
expect(t.isIdentifier(pattern)).toBe(false);
|
||||
});
|
||||
it("returns true if targetType is expectedNode", function() {
|
||||
expect(t.isPattern(pattern)).toBe(true);
|
||||
});
|
||||
it("returns true if targetType is an alias for expectedNode", function() {
|
||||
expect(t.isLVal(pattern)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user