isAssignmentTarget

tcmts.core.canonicalize.isAssignmentTarget · #4por3bwo · term · runs anywhere

x = …, x += …, x++, [x] = …, ({ x } = …), for (x of …)

import {
  isArrayLiteralExpression as ts_isArrayLiteralExpression, isAsExpression as ts_isAsExpression,
  isBinaryExpression as ts_isBinaryExpression, isForInStatement as ts_isForInStatement,
  isForOfStatement as ts_isForOfStatement, isNonNullExpression as ts_isNonNullExpression,
  isObjectLiteralExpression as ts_isObjectLiteralExpression,
  isParenthesizedExpression as ts_isParenthesizedExpression, isPostfixUnaryExpression as ts_isPostfixUnaryExpression,
  isPrefixUnaryExpression as ts_isPrefixUnaryExpression, isPropertyAssignment as ts_isPropertyAssignment,
  isSatisfiesExpression as ts_isSatisfiesExpression,
  isShorthandPropertyAssignment as ts_isShorthandPropertyAssignment, isSpreadAssignment as ts_isSpreadAssignment,
  isSpreadElement as ts_isSpreadElement, isTypeAssertion as ts_isTypeAssertionExpression, SyntaxKind as ts_SyntaxKind,
} from "typescript/ast";
import type { Node as ts_Node } from "typescript/ast";

export function isAssignmentTarget(node: ts_Node): boolean {
  let n = node;
  for (;;) {
    const p = n.parent;
    if (ts_isParenthesizedExpression(p) || ts_isNonNullExpression(p) || ts_isAsExpression(p) || ts_isSatisfiesExpression(p) || ts_isTypeAssertionExpression(p)) n = p;
    else if (ts_isArrayLiteralExpression(p) || ts_isSpreadElement(p) || ts_isSpreadAssignment(p)) n = p;
    else if (ts_isShorthandPropertyAssignment(p) && p.name === n) n = p.parent;
    else if (ts_isPropertyAssignment(p) && p.initializer === n) n = p.parent;
    else break;
    if (ts_isObjectLiteralExpression(n)) continue;
  }
  const p = n.parent;
  if (ts_isBinaryExpression(p)) return p.left === n && p.operatorToken.kind >= ts_SyntaxKind.FirstAssignment && p.operatorToken.kind <= ts_SyntaxKind.LastAssignment;
  if (ts_isPrefixUnaryExpression(p) || ts_isPostfixUnaryExpression(p)) return p.operator === ts_SyntaxKind.PlusPlusToken || p.operator === ts_SyntaxKind.MinusMinusToken;
  if (ts_isForOfStatement(p) || ts_isForInStatement(p)) return p.initializer === n;
  return false;
}

used by