UNPKG

@ui5/linter

Version:

A static code analysis tool for UI5

453 lines 25.1 kB
import ts from "typescript"; import { getLogger } from "@ui5/logger"; const { SyntaxKind } = ts; import { toPosStr, UnsupportedModuleError } from "./util.js"; const log = getLogger("linter:ui5Types:amdTranspiler:replaceNodeInParent"); /** * Replaces a node in its parent with another node */ export default function (parent, replacement, nodeFactory) { const { original, substitute } = replacement; log.verbose(`Replacing child of ${ts.SyntaxKind[parent.kind]}\n` + ` Old: ${ts.SyntaxKind[original.kind]}\n` + ` New: ${ts.SyntaxKind[substitute.kind]}`); switch (parent.kind) { case SyntaxKind.ExpressionStatement: return replaceInExpressionStatement(parent, replacement, nodeFactory); case SyntaxKind.ParenthesizedExpression: return replaceInParenthesizedExpression(parent, replacement, nodeFactory); case SyntaxKind.CallExpression: return replaceInCallExpression(parent, replacement, nodeFactory); case SyntaxKind.NewExpression: return replaceInNewExpression(parent, replacement, nodeFactory); case SyntaxKind.BinaryExpression: return replaceInBinaryExpression(parent, replacement, nodeFactory); case SyntaxKind.ConditionalExpression: return replaceInConditionalExpression(parent, replacement, nodeFactory); case SyntaxKind.PrefixUnaryExpression: return replaceInPrefixUnaryExpression(parent, replacement, nodeFactory); case SyntaxKind.PostfixUnaryExpression: return replaceInPostfixUnaryExpression(parent, replacement, nodeFactory); case SyntaxKind.YieldExpression: return replaceInYieldExpression(parent, replacement, nodeFactory); case SyntaxKind.AwaitExpression: return replaceInAwaitExpression(parent, replacement, nodeFactory); case SyntaxKind.VariableStatement: return replaceInVariableStatement(parent, replacement, nodeFactory); case SyntaxKind.VariableDeclaration: return replaceInVariableDeclaration(parent, replacement, nodeFactory); case SyntaxKind.VariableDeclarationList: return replaceInVariableDeclarationList(parent, replacement, nodeFactory); case SyntaxKind.PropertyAssignment: return replaceInPropertyAssignment(parent, replacement, nodeFactory); case SyntaxKind.PropertyDeclaration: return replaceInPropertyDeclaration(parent, replacement, nodeFactory); case SyntaxKind.IfStatement: return replaceInIfStatement(parent, replacement, nodeFactory); case SyntaxKind.WhileStatement: return replaceInWhileStatement(parent, replacement, nodeFactory); case SyntaxKind.DoStatement: return replaceInDoStatement(parent, replacement, nodeFactory); case SyntaxKind.ForStatement: return replaceInForStatement(parent, replacement, nodeFactory); case SyntaxKind.ReturnStatement: return replaceInReturnStatement(parent, replacement, nodeFactory); case SyntaxKind.ArrayLiteralExpression: return replaceInArrayLiteralExpression(parent, replacement, nodeFactory); case SyntaxKind.ObjectLiteralExpression: return replaceInObjectLiteralExpression(parent, replacement, nodeFactory); case SyntaxKind.PropertyAccessExpression: return replaceInPropertyAccessExpression(parent, replacement, nodeFactory); case SyntaxKind.ElementAccessExpression: return replaceInElementAccessExpression(parent, replacement, nodeFactory); case SyntaxKind.Block: return replaceInBlock(parent, replacement, nodeFactory); case SyntaxKind.ArrowFunction: return replaceInArrowFunction(parent, replacement, nodeFactory); case SyntaxKind.FunctionExpression: return replaceInFunctionExpression(parent, replacement, nodeFactory); case SyntaxKind.FunctionDeclaration: return replaceInFunctionDeclaration(parent, replacement, nodeFactory); case SyntaxKind.MethodDeclaration: return replaceInMethodDeclaration(parent, replacement, nodeFactory); case SyntaxKind.ClassDeclaration: return replaceInClassDeclaration(parent, replacement, nodeFactory); case SyntaxKind.ComputedPropertyName: return replaceInComputedPropertyName(parent, replacement, nodeFactory); case SyntaxKind.Parameter: return replaceInParameterDeclaration(parent, replacement, nodeFactory); case SyntaxKind.SourceFile: return replaceInSourceFile(parent, replacement, nodeFactory); default: throw new UnsupportedModuleError(`Unsupported parent node type for replacement operation: ${ts.SyntaxKind[parent.kind]} at ` + `${toPosStr(parent)}`); } } function replaceNodeInArray(original, substitute, array) { // First create a flat copy of the array const newArray = array.slice(); const index = array.indexOf(original); if (index < 0) { throw new Error(`Node not found in array`); } newArray[index] = substitute; return newArray; } function replaceInExpressionStatement(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ExpressionStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateExpressionStatement(node, substitute); } function replaceInParenthesizedExpression(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ParenthesizedExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateParenthesizedExpression(node, substitute); } function replaceInCallExpression(node, { original, substitute }, nodeFactory) { if (node.expression === original) { // Replace expression if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for CallExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateCallExpression(node, substitute, node.typeArguments, node.arguments); } else if (node.arguments.includes(original)) { // Replace argument const args = replaceNodeInArray(original, substitute, node.arguments); return nodeFactory.updateCallExpression(node, node.expression, node.typeArguments, args); } else { throw new UnsupportedModuleError(`Unexpected child node for CallExpression replacement: ${ts.SyntaxKind[original.kind]} at ` + `${toPosStr(original)}`); } } function replaceInNewExpression(node, { original, substitute }, nodeFactory) { if (node.expression === original) { // Replace expression if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for NewExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateNewExpression(node, substitute, node.typeArguments, node.arguments); } else if (node.arguments?.includes(original)) { // Replace argument const args = replaceNodeInArray(original, substitute, node.arguments); return nodeFactory.updateNewExpression(node, node.expression, node.typeArguments, args); } else { throw new UnsupportedModuleError(`Unexpected child node for NewExpression replacement: ${ts.SyntaxKind[original.kind]} at ` + `${toPosStr(original)}`); } } function replaceInBinaryExpression(node, { original, substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for BinaryExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } if (node.left === original) { // Replace left return nodeFactory.updateBinaryExpression(node, substitute, node.operatorToken, node.right); } else { // Must be right // Replace right return nodeFactory.updateBinaryExpression(node, node.left, node.operatorToken, substitute); } } function replaceInConditionalExpression(node, { original, substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ConditionalExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } if (node.condition === original) { // Replace condition return nodeFactory.updateConditionalExpression(node, substitute, node.questionToken, node.whenTrue, node.colonToken, node.whenFalse); } else if (node.whenTrue === original) { // Replace whenTrue return nodeFactory.updateConditionalExpression(node, node.condition, node.questionToken, substitute, node.colonToken, node.whenFalse); } else { // Must be whenFalse // Replace whenFalse return nodeFactory.updateConditionalExpression(node, node.condition, node.questionToken, node.whenTrue, node.colonToken, substitute); } } function replaceInPrefixUnaryExpression(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PrefixUnaryExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePrefixUnaryExpression(node, substitute); } function replaceInPostfixUnaryExpression(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PostfixUnaryExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePostfixUnaryExpression(node, substitute); } function replaceInYieldExpression(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for YieldExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateYieldExpression(node, node.asteriskToken, substitute); } function replaceInAwaitExpression(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for AwaitExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateAwaitExpression(node, substitute); } function replaceInVariableStatement(node, { original, substitute }, nodeFactory) { const declarationList = replaceNodeInArray(original, substitute, node.declarationList.declarations); return nodeFactory.updateVariableStatement(node, node.modifiers, nodeFactory.updateVariableDeclarationList(node.declarationList, declarationList)); } function replaceInVariableDeclaration(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for VariableDeclaration (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateVariableDeclaration(node, node.name, node.exclamationToken, node.type, substitute); } function replaceInVariableDeclarationList(node, { original, substitute }, nodeFactory) { const declarations = replaceNodeInArray(original, substitute, node.declarations); return nodeFactory.updateVariableDeclarationList(node, declarations); } function replaceInPropertyAssignment(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PropertyAssignment (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePropertyAssignment(node, node.name, substitute); } function replaceInPropertyDeclaration(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PropertyDeclaration (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePropertyDeclaration(node, node.modifiers, node.name, node.questionToken ?? node.exclamationToken, node.type, substitute); } function replaceInIfStatement(node, { original, substitute }, nodeFactory) { if (node.expression === original) { // Replace expression if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for IfStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateIfStatement(node, substitute, node.thenStatement, node.elseStatement); } else if (node.thenStatement === original) { // Replace statement if (!ts.isStatement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for IfStatement (expected Statement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateIfStatement(node, node.expression, substitute, node.elseStatement); } else { // Must be elseStatement // Replace statement if (!ts.isStatement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for IfStatement (expected Statement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateIfStatement(node, node.expression, node.thenStatement, substitute); } } function replaceInWhileStatement(node, { original, substitute }, nodeFactory) { if (node.expression === original) { // Replace expression if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for WhileStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateWhileStatement(node, substitute, node.statement); } else { // Must be statement // Replace statement if (!ts.isStatement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for WhileStatement (expected Statement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateWhileStatement(node, node.expression, substitute); } } function replaceInDoStatement(node, { original, substitute }, nodeFactory) { if (node.statement === original) { // Replace statement if (!ts.isStatement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for DoStatement (expected Statement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateDoStatement(node, substitute, node.expression); } else { // Must be expression // Replace expression if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for DoStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateDoStatement(node, node.statement, substitute); } } function replaceInForStatement(node, { original, substitute }, nodeFactory) { if (node.initializer === original) { // Replace initializer if (!ts.isForInitializer(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ForStatement (expected ForInitializer): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateForStatement(node, substitute, node.condition, node.incrementor, node.statement); } else if (node.condition === original) { // Replace condition if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ForStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateForStatement(node, node.initializer, substitute, node.incrementor, node.statement); } else if (node.incrementor === original) { // Replace incrementor if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ForStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateForStatement(node, node.initializer, node.condition, substitute, node.statement); } else { // Must be statement // Replace statement if (!ts.isStatement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ForStatement (expected Statement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateForStatement(node, node.initializer, node.condition, node.incrementor, substitute); } } function replaceInReturnStatement(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ReturnStatement (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateReturnStatement(node, substitute); } function replaceInArrayLiteralExpression(node, { original, substitute }, nodeFactory) { const elements = replaceNodeInArray(original, substitute, node.elements); return nodeFactory.updateArrayLiteralExpression(node, elements); } function replaceInObjectLiteralExpression(node, { original, substitute }, nodeFactory) { const properties = replaceNodeInArray(original, substitute, node.properties); return nodeFactory.updateObjectLiteralExpression(node, properties); } function replaceInPropertyAccessExpression(node, { original, substitute }, nodeFactory) { if (node.name === original) { // Replace name if (!ts.isIdentifier(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PropertyAccessExpression (expected Identifier): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePropertyAccessExpression(node, node.expression, substitute); } else { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for PropertyAccessExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updatePropertyAccessExpression(node, substitute, node.name); } } function replaceInBlock(node, { original, substitute }, nodeFactory) { const statements = replaceNodeInArray(original, substitute, node.statements); return nodeFactory.updateBlock(node, statements); } function replaceInElementAccessExpression(node, { original, substitute }, nodeFactory) { if (node.expression === original) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ElementAccessExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateElementAccessExpression(node, substitute, node.argumentExpression); } else { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ElementAccessExpression (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateElementAccessExpression(node, node.expression, substitute); } } function replaceInArrowFunction(node, { substitute }, nodeFactory) { if (!ts.isBlock(substitute) && !ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ArrowFunction (expected Block or Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateArrowFunction(node, node.modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, substitute); } function replaceInFunctionExpression(node, { substitute }, nodeFactory) { if (!ts.isBlock(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for FunctionExpression (expected Block): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateFunctionExpression(node, node.modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, substitute); } function replaceInFunctionDeclaration(node, { substitute }, nodeFactory) { if (!ts.isBlock(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for FunctionDeclaration (expected Block): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateFunctionDeclaration(node, node.modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, substitute); } function replaceInMethodDeclaration(node, { substitute }, nodeFactory) { if (!ts.isBlock(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for MethodDeclaration (expected Block): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateMethodDeclaration(node, node.modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, substitute); } function replaceInClassDeclaration(node, { original, substitute }, nodeFactory) { if (node.heritageClauses?.includes(original)) { if (!ts.isHeritageClause(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ClassDeclaration (expected HeritageClause): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } const heritageClauses = replaceNodeInArray(original, substitute, node.heritageClauses); return nodeFactory.updateClassDeclaration(node, node.modifiers, node.name, node.typeParameters, heritageClauses, node.members); } else if (node.members.includes(original)) { if (!ts.isClassElement(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ClassDeclaration (expected ClassElement): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } const members = replaceNodeInArray(original, substitute, node.members); return nodeFactory.updateClassDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, members); } else { throw new UnsupportedModuleError(`Unexpected child node for ClassDeclaration replacement: ${ts.SyntaxKind[original.kind]} at ` + `${toPosStr(original)}`); } } function replaceInComputedPropertyName(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ComputedPropertyName (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateComputedPropertyName(node, substitute); } function replaceInParameterDeclaration(node, { substitute }, nodeFactory) { if (!ts.isExpression(substitute)) { throw new UnsupportedModuleError(`Unexpected replacement type for ParameterDeclaration (expected Expression): ` + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); } return nodeFactory.updateParameterDeclaration(node, node.modifiers, node.dotDotDotToken, node.name, node.questionToken, node.type, substitute); } function replaceInSourceFile(node, { original, substitute }, nodeFactory) { const statements = replaceNodeInArray(original, substitute, node.statements); return nodeFactory.updateSourceFile(node, statements); } //# sourceMappingURL=replaceNodeInParent.js.map