Matches pattern cleanup (#5826)
* Extract duplicated function into babel-types Also reimplements in a sane way. * Add tests * cleanup
This commit is contained in:
parent
8df5514083
commit
5cc1cbf3bc
@ -12,54 +12,7 @@ import * as t from "babel-types";
|
||||
*/
|
||||
|
||||
export function matchesPattern(pattern: string, allowPartial?: boolean): boolean {
|
||||
// not a member expression
|
||||
if (!this.isMemberExpression()) return false;
|
||||
|
||||
const parts = pattern.split(".");
|
||||
const search = [this.node];
|
||||
let i = 0;
|
||||
|
||||
function matches(name) {
|
||||
const part = parts[i];
|
||||
return part === "*" || name === part;
|
||||
}
|
||||
|
||||
while (search.length) {
|
||||
const node = search.shift();
|
||||
|
||||
if (allowPartial && i === parts.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isIdentifier(node)) {
|
||||
// this part doesn't match
|
||||
if (!matches(node.name)) return false;
|
||||
} else if (t.isLiteral(node)) {
|
||||
// this part doesn't match
|
||||
if (!matches(node.value)) return false;
|
||||
} else if (t.isMemberExpression(node)) {
|
||||
if (node.computed && !t.isLiteral(node.property)) {
|
||||
// we can't deal with this
|
||||
return false;
|
||||
} else {
|
||||
search.unshift(node.property);
|
||||
search.unshift(node.object);
|
||||
continue;
|
||||
}
|
||||
} else if (t.isThisExpression(node)) {
|
||||
if (!matches("this")) return false;
|
||||
} else {
|
||||
// we can't deal with this
|
||||
return false;
|
||||
}
|
||||
|
||||
// too many parts
|
||||
if (++i > parts.length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return i === parts.length;
|
||||
return t.matchesPattern(this.node, pattern, allowPartial);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -314,6 +314,51 @@ export function cloneDeep(node: Object): Object {
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the input node `member` matches the
|
||||
* input `match`.
|
||||
*
|
||||
* For example, given the match `React.createClass` it would match the
|
||||
* parsed nodes of `React.createClass` and `React["createClass"]`.
|
||||
*/
|
||||
|
||||
export function matchesPattern(
|
||||
member: Object,
|
||||
match: string | Array<string>,
|
||||
allowPartial?: boolean
|
||||
): boolean {
|
||||
// not a member expression
|
||||
if (!t.isMemberExpression(member)) return false;
|
||||
|
||||
const parts = Array.isArray(match) ? match : match.split(".");
|
||||
const nodes = [];
|
||||
|
||||
let node;
|
||||
for (node = member; t.isMemberExpression(node); node = node.object) {
|
||||
nodes.push(node.property);
|
||||
}
|
||||
nodes.push(node);
|
||||
|
||||
if (nodes.length < parts.length) return false;
|
||||
if (!allowPartial && nodes.length > parts.length) return false;
|
||||
|
||||
for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
|
||||
const node = nodes[j];
|
||||
let value;
|
||||
if (t.isIdentifier(node)) {
|
||||
value = node.name;
|
||||
} else if (t.isStringLiteral(node)) {
|
||||
value = node.value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts[i] !== value) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a function that when called will return whether or not the
|
||||
* input `node` `MemberExpression` matches the input `match`.
|
||||
@ -322,50 +367,10 @@ export function cloneDeep(node: Object): Object {
|
||||
* parsed nodes of `React.createClass` and `React["createClass"]`.
|
||||
*/
|
||||
|
||||
export function buildMatchMemberExpression(match:string, allowPartial?: boolean): Function {
|
||||
export function buildMatchMemberExpression(match: string, allowPartial?: boolean): (Object) => boolean {
|
||||
const parts = match.split(".");
|
||||
|
||||
return function (member) {
|
||||
// not a member expression
|
||||
if (!t.isMemberExpression(member)) return false;
|
||||
|
||||
const search = [member];
|
||||
let i = 0;
|
||||
|
||||
while (search.length) {
|
||||
const node = search.shift();
|
||||
|
||||
if (allowPartial && i === parts.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isIdentifier(node)) {
|
||||
// this part doesn't match
|
||||
if (parts[i] !== node.name) return false;
|
||||
} else if (t.isStringLiteral(node)) {
|
||||
// this part doesn't match
|
||||
if (parts[i] !== node.value) return false;
|
||||
} else if (t.isMemberExpression(node)) {
|
||||
if (node.computed && !t.isStringLiteral(node.property)) {
|
||||
// we can't deal with this
|
||||
return false;
|
||||
} else {
|
||||
search.push(node.object);
|
||||
search.push(node.property);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// we can't deal with this
|
||||
return false;
|
||||
}
|
||||
|
||||
// too many parts
|
||||
if (++i > parts.length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return matchesPattern(member, parts, allowPartial);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
45
packages/babel-types/test/misc.js
Normal file
45
packages/babel-types/test/misc.js
Normal file
@ -0,0 +1,45 @@
|
||||
import * as t from "../lib";
|
||||
import { assert } from "chai";
|
||||
import { parse } from "babylon";
|
||||
|
||||
function parseCode(string) {
|
||||
return parse(string, {
|
||||
allowReturnOutsideFunction: true,
|
||||
}).program.body[0];
|
||||
}
|
||||
|
||||
describe("misc helpers", function () {
|
||||
describe("matchesPattern", function () {
|
||||
it("matches explicitly", function () {
|
||||
const ast = parseCode("a.b.c.d").expression;
|
||||
assert(t.matchesPattern(ast, "a.b.c.d"));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c"));
|
||||
assert.isFalse(t.matchesPattern(ast, "b.c.d"));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c.d.e"));
|
||||
});
|
||||
|
||||
it("matches partially", function () {
|
||||
const ast = parseCode("a.b.c.d").expression;
|
||||
assert(t.matchesPattern(ast, "a.b.c.d", true));
|
||||
assert(t.matchesPattern(ast, "a.b.c", true));
|
||||
assert.isFalse(t.matchesPattern(ast, "b.c.d", true));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c.d.e", true));
|
||||
});
|
||||
|
||||
it("matches string literal expressions", function () {
|
||||
const ast = parseCode("a['b'].c.d").expression;
|
||||
assert(t.matchesPattern(ast, "a.b.c.d"));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c"));
|
||||
assert.isFalse(t.matchesPattern(ast, "b.c.d"));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c.d.e"));
|
||||
});
|
||||
|
||||
it("matches string literal expressions partially", function () {
|
||||
const ast = parseCode("a['b'].c.d").expression;
|
||||
assert(t.matchesPattern(ast, "a.b.c.d", true));
|
||||
assert(t.matchesPattern(ast, "a.b.c", true));
|
||||
assert.isFalse(t.matchesPattern(ast, "b.c.d", true));
|
||||
assert.isFalse(t.matchesPattern(ast, "a.b.c.d.e", true));
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user