UNPKG

@eclipse-scout/migrate

Version:

TypeScript migration module

108 lines (98 loc) 4.18 kB
/* * Copyright (c) 2010, 2023 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import jscodeshift from 'jscodeshift'; import {defaultModuleMap, defaultRecastOptions, findClassName, findClassProperty, findParentClassBody, insertMissingImportsForTypes, mapType, removeEmptyLinesBetweenImports} from './common.js'; const j = jscodeshift.withParser('ts'); let referencedTypes; /** * @type import('ts-migrate-server').Plugin<{moduleMap?: object, defaultParamType?: string}> */ const widgetPropertiesPlugin = { name: 'widget-properties-plugin', async run({text, options, sourceFile}) { let root = j(text); const moduleMap = {...defaultModuleMap, ...options.moduleMap}; referencedTypes = new Set(); let result = new Map(); // Find all widget properties for each class in file root.find(j.Declaration) .filter(path => path.node.type === j.ClassMethod.name && path.node.kind === 'constructor') .find(j.Identifier) .filter(path => path.node.name === '_addWidgetProperties' || path.node.name === '_addPreserveOnPropertyChangeProperties') .forEach(path => { let argument = path.parentPath.parentPath.value.arguments[0]; let className = findClassName(path); let widgetProperties = result.get(className); if (!widgetProperties) { widgetProperties = []; result.set(className, widgetProperties); } if (path.node.name === '_addPreserveOnPropertyChangeProperties') { // Don't add resp. remove preserve properties if (argument.type === j.StringLiteral.name) { removeFromArray(widgetProperties, argument.value); } else if (argument.type === j.ArrayExpression.name) { for (let prop of argument.elements.map(elem => elem.value)) { removeFromArray(widgetProperties, prop); } } } else { if (argument.type === j.StringLiteral.name) { widgetProperties.push(argument.value); } else if (argument.type === j.ArrayExpression.name) { widgetProperties.push(...argument.elements.map(element => element.value)); } } }); // Find all setters, use data type of the property and wrap it with the ChildRef type root.find(j.ClassMethod) .filter(path => path.node.key.name.startsWith('set')) .forEach(path => { let className = findClassName(path); let widgetProperties = result.get(className); if (!widgetProperties) { return; } let setter = path.node; let setterName = setter.key.name; let propertyName = setterName.substring(3, 4).toLowerCase() + setterName.substring(4); if (!widgetProperties.includes(propertyName)) { return; } let property = findClassProperty(findParentClassBody(path), propertyName); if (!property) { return; } let typeAnnotation = property.typeAnnotation?.typeAnnotation; if (!typeAnnotation) { return; } let newType; if (typeAnnotation.type === j.TSArrayType.name) { newType = mapType(j, 'scout.ChildRef[]'); newType.type.elementType.typeParameters = j.tsTypeParameterInstantiation([typeAnnotation.elementType]); } else { newType = mapType(j, 'scout.ChildRef'); newType.type.typeParameters = j.tsTypeParameterInstantiation([typeAnnotation]); } setter.params[0].typeAnnotation = j.tsTypeAnnotation(newType.type); referencedTypes.add(newType); }); insertMissingImportsForTypes(j, root, Array.from(referencedTypes), moduleMap, sourceFile.fileName); return removeEmptyLinesBetweenImports(root.toSource(defaultRecastOptions)); } }; function removeFromArray(array, elem) { let index = array.indexOf(elem); if (index > -1) { array.splice(index, 1); } } export default widgetPropertiesPlugin;