testParensOnlyWhereTheChainGoesOn
tcmts.core.migrate.testParensOnlyWhereTheChainGoesOn · #oxpodtnt · term
import { dropUncontinuedParens, upgradeIR } from "#codebase/tcmts/core/migrate";
import assert from "node:assert/strict";
export const testParensOnlyWhereTheChainGoesOn = () => {
const chain = [
"PropertyAccessExpression",
["expression", ["L", "0"]],
["questionDotToken", ["QuestionDotToken"]],
["name", ["N", "b"]],
];
const paren = ["ParenthesizedExpression", ["expression", chain]];
// `(a?.b) ?? x`: nothing goes on from it, the parentheses go
assert.deepEqual(
dropUncontinuedParens([
"BinaryExpression",
["left", paren],
["operatorToken", ["QuestionQuestionToken"]],
["right", ["Str", "x"]],
]),
[
"BinaryExpression",
["left", chain],
["operatorToken", ["QuestionQuestionToken"]],
["right", ["Str", "x"]],
],
);
// `(a?.b).c` and `(a?.b)()`: the chain goes on, they stay
const member = ["PropertyAccessExpression", ["expression", paren], ["name", ["N", "c"]]];
assert.deepEqual(dropUncontinuedParens(member), member);
const call = ["CallExpression", ["expression", paren], ["arguments", ["["]]];
assert.deepEqual(dropUncontinuedParens(call), call);
const tagged = ["TaggedTemplateExpression", ["tag", paren], ["template", ["Str", "t"]]];
assert.deepEqual(dropUncontinuedParens(tagged), tagged);
// but not when it's an argument: `f((a?.b))`
assert.deepEqual(
dropUncontinuedParens([
"CallExpression",
["expression", ["G", "f"]],
["arguments", ["[", paren]],
]),
["CallExpression", ["expression", ["G", "f"]], ["arguments", ["[", chain]]],
);
assert.deepEqual(upgradeIR(paren, 1, 2), chain);
assert.deepEqual(upgradeIR(paren, 2, 2), paren);
assert.throws(() => upgradeIR(paren, 2, 3), /no way from hash format v2 to v3/);
}
uses