@eclipse-scout/migrate 23.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +277 -0
- package/README.md +189 -0
- package/bin/scout-migrate.js +166 -0
- package/package.json +51 -0
- package/src/common.js +666 -0
- package/src/convertToCRLFPlugin.js +34 -0
- package/src/convertToLFPlugin.js +31 -0
- package/src/countMethodsPlugin.js +36 -0
- package/src/declareMissingClassPropertiesPlugin.js +139 -0
- package/src/memberAccessModifierPlugin.js +51 -0
- package/src/menuTypesPlugin.js +77 -0
- package/src/methodsPlugin.js +143 -0
- package/src/printEventMapsPlugin.js +78 -0
- package/src/typedObjectTypePlugin.js +64 -0
- package/src/widgetColumnMapPlugin.js +386 -0
- package/src/widgetPropertiesPlugin.js +107 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type import('ts-migrate-server').Plugin<unknown>
|
|
13
|
+
*/
|
|
14
|
+
import {crlfToLf} from './common.js';
|
|
15
|
+
import {filesConvertedToCrLf} from './convertToCRLFPlugin.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @type import('ts-migrate-server').Plugin<{}>
|
|
19
|
+
*/
|
|
20
|
+
const convertToLFPlugin = {
|
|
21
|
+
name: 'convert-to-lf',
|
|
22
|
+
|
|
23
|
+
run({text, fileName}) {
|
|
24
|
+
if (filesConvertedToCrLf.has(fileName)) {
|
|
25
|
+
// revert line ending style to lf
|
|
26
|
+
return crlfToLf(text);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default convertToLFPlugin;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
import jscodeshift from 'jscodeshift';
|
|
11
|
+
import {methodFilter} from './common.js';
|
|
12
|
+
|
|
13
|
+
const j = jscodeshift.withParser('ts');
|
|
14
|
+
let total = 0;
|
|
15
|
+
/**
|
|
16
|
+
* @type import('ts-migrate-server').Plugin<unknown>
|
|
17
|
+
*/
|
|
18
|
+
const countMethods = {
|
|
19
|
+
name: 'count-methods-plugin',
|
|
20
|
+
|
|
21
|
+
async run({text, fileName}) {
|
|
22
|
+
const root = j(text);
|
|
23
|
+
let count = 0;
|
|
24
|
+
root.find(j.Declaration)
|
|
25
|
+
.filter(path => methodFilter(j, path))
|
|
26
|
+
.forEach(expression => {
|
|
27
|
+
count++;
|
|
28
|
+
});
|
|
29
|
+
total += count;
|
|
30
|
+
console.log(fileName + ': ' + count);
|
|
31
|
+
console.log('Total: ' + total);
|
|
32
|
+
return text;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default countMethods;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Based on https://github.com/airbnb/ts-migrate/blob/master/packages/ts-migrate-plugins/src/plugins/declare-missing-class-properties.ts (MIT License)
|
|
13
|
+
* See readme.md for details.
|
|
14
|
+
*/
|
|
15
|
+
import jscodeshift from 'jscodeshift';
|
|
16
|
+
import {validateAnyAliasOptions} from 'ts-migrate-plugins/build/src/utils/validateOptions.js';
|
|
17
|
+
import {isDiagnosticWithLinePosition} from 'ts-migrate-plugins/build/src/utils/type-guards.js';
|
|
18
|
+
import {defaultModuleMap, defaultParamTypeMap, defaultRecastOptions, findClassProperty, findIndex, findParentClassBody, findParentPath, getTypeFor, inConstructor, insertMissingImportsForTypes, removeEmptyLinesBetweenImports, transformCommentLinesToJsDoc} from './common.js';
|
|
19
|
+
|
|
20
|
+
const j = jscodeshift.withParser('ts');
|
|
21
|
+
let root;
|
|
22
|
+
let referencedTypes;
|
|
23
|
+
const propertyComparator = (a, b) => {
|
|
24
|
+
// Move $ and _ variables to the end
|
|
25
|
+
if (a.startsWith('_') && !b.startsWith('_')) {
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
if (b.startsWith('_') && !a.startsWith('_')) {
|
|
29
|
+
return -1;
|
|
30
|
+
}
|
|
31
|
+
if (a.startsWith('$') && !b.startsWith('$')) {
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
if (b.startsWith('$') && !a.startsWith('$')) {
|
|
35
|
+
return -1;
|
|
36
|
+
}
|
|
37
|
+
return 0;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @type import('ts-migrate-server').Plugin<{ anyAlias?: string, typeMap?: object, moduleMap?: object}>
|
|
42
|
+
*/
|
|
43
|
+
const declareMissingClassPropertiesPlugin = {
|
|
44
|
+
name: 'declare-missing-class-properties',
|
|
45
|
+
|
|
46
|
+
async run({text, fileName, getLanguageService, options, sourceFile}) {
|
|
47
|
+
const diagnostics = getLanguageService()
|
|
48
|
+
.getSemanticDiagnostics(fileName)
|
|
49
|
+
.filter(isDiagnosticWithLinePosition)
|
|
50
|
+
.filter(diagnostic => diagnostic.code === 2339 || diagnostic.code === 2551); // 2339: Property_0_does_not_exist_on_type_1, 2551: Property_0_does_not_exist_on_type_1_Did_you_mean_
|
|
51
|
+
|
|
52
|
+
root = j(text);
|
|
53
|
+
|
|
54
|
+
const toAdd = [];
|
|
55
|
+
const typeMap = {...defaultParamTypeMap, ...options.typeMap};
|
|
56
|
+
const moduleMap = {...defaultModuleMap, ...options.moduleMap};
|
|
57
|
+
referencedTypes = new Set();
|
|
58
|
+
|
|
59
|
+
// Diagnostics are errors reported by typescript -> the plugin only processes missing properties
|
|
60
|
+
diagnostics.forEach(diagnostic => {
|
|
61
|
+
root
|
|
62
|
+
.find(j.Identifier)
|
|
63
|
+
.filter(
|
|
64
|
+
path =>
|
|
65
|
+
(path.node).start === diagnostic.start &&
|
|
66
|
+
(path.node).end === diagnostic.start + diagnostic.length &&
|
|
67
|
+
path.parentPath.node.type === 'MemberExpression' &&
|
|
68
|
+
path.parentPath.node.object.type === 'ThisExpression' &&
|
|
69
|
+
path.parentPath.parentPath.node.type === 'AssignmentExpression' && path.parentPath.parentPath.node.operator === '=' &&
|
|
70
|
+
inConstructor(path)
|
|
71
|
+
)
|
|
72
|
+
.forEach(path => {
|
|
73
|
+
const classBody = findParentClassBody(path);
|
|
74
|
+
if (!classBody) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let item = toAdd.find(cur => cur.classBody === classBody);
|
|
78
|
+
if (!item) {
|
|
79
|
+
item = {classBody, propertyNames: new Map()};
|
|
80
|
+
toAdd.push(item);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let assignment = findParentPath(path, parentPath => parentPath.node.type === 'AssignmentExpression');
|
|
84
|
+
let typeDesc = getTypeFor(j, path.node.name, assignment.node.right, Object.values(typeMap));
|
|
85
|
+
if (typeDesc && typeDesc.module) {
|
|
86
|
+
referencedTypes.add(typeDesc);
|
|
87
|
+
}
|
|
88
|
+
let property = {
|
|
89
|
+
type: typeDesc.type
|
|
90
|
+
};
|
|
91
|
+
if (assignment.parentPath.node.comments) {
|
|
92
|
+
property.comments = assignment.parentPath.node.comments;
|
|
93
|
+
// Remove comment from property assignment
|
|
94
|
+
assignment.parentPath.node.comments = null;
|
|
95
|
+
}
|
|
96
|
+
item.propertyNames.set(path.node.name, property);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
toAdd.forEach(({classBody, propertyNames: properties}) => {
|
|
101
|
+
const /** @type {string[]}*/ propertyNames = Array.from(properties.keys())
|
|
102
|
+
.filter(propertyName => {
|
|
103
|
+
const existingProperty = findClassProperty(classBody, propertyName);
|
|
104
|
+
return existingProperty == null;
|
|
105
|
+
})
|
|
106
|
+
.sort(propertyComparator);
|
|
107
|
+
|
|
108
|
+
// Insert before constructor
|
|
109
|
+
let index = findIndex(classBody.node.body, node => node.type === 'ClassMethod' && node.kind === 'constructor');
|
|
110
|
+
if (index < 0) {
|
|
111
|
+
index = 0;
|
|
112
|
+
}
|
|
113
|
+
classBody.node.body.splice(
|
|
114
|
+
index,
|
|
115
|
+
0,
|
|
116
|
+
...propertyNames.map(propertyName => {
|
|
117
|
+
let propertyDesc = properties.get(propertyName);
|
|
118
|
+
let prop = j.classProperty(
|
|
119
|
+
j.identifier(propertyName),
|
|
120
|
+
null,
|
|
121
|
+
j.tsTypeAnnotation(propertyDesc.type)
|
|
122
|
+
);
|
|
123
|
+
let comments = transformCommentLinesToJsDoc(j, propertyDesc.comments);
|
|
124
|
+
if (comments) {
|
|
125
|
+
prop.comments = comments;
|
|
126
|
+
}
|
|
127
|
+
return prop;
|
|
128
|
+
})
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
insertMissingImportsForTypes(j, root, Array.from(referencedTypes), moduleMap, sourceFile.fileName);
|
|
133
|
+
return removeEmptyLinesBetweenImports(root.toSource(defaultRecastOptions));
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
validate: validateAnyAliasOptions
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export default declareMissingClassPropertiesPlugin;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
import jscodeshift from 'jscodeshift';
|
|
11
|
+
import {defaultRecastOptions} from './common.js';
|
|
12
|
+
|
|
13
|
+
const j = jscodeshift.withParser('ts');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type import('ts-migrate-server').Plugin<unknown>
|
|
17
|
+
*/
|
|
18
|
+
const memberAccessModifierPlugin = {
|
|
19
|
+
name: 'member-access-modifier-plugin',
|
|
20
|
+
|
|
21
|
+
async run({text}) {
|
|
22
|
+
const root = j(text);
|
|
23
|
+
// Declaration is base type for ClassMethod and ClassProperty according to https://github.com/benjamn/ast-types/tree/master/def
|
|
24
|
+
return root.find(j.Declaration)
|
|
25
|
+
.filter(path => path.node.type === j.ClassMethod.name || path.node.type === j.ClassProperty.name)
|
|
26
|
+
.forEach(expression => {
|
|
27
|
+
if (expression.node.accessibility) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let name = expression.node.key.name;
|
|
31
|
+
if (name && name.startsWith('_') && !containsInternalInJsDoc(expression.node)) {
|
|
32
|
+
expression.node.accessibility = 'protected';
|
|
33
|
+
}
|
|
34
|
+
}).toSource(defaultRecastOptions);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function containsInternalInJsDoc(node) {
|
|
39
|
+
let comments = node.comments;
|
|
40
|
+
if (!comments) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return comments.some(comment => {
|
|
44
|
+
if (comment.type !== 'CommentBlock') {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return comment.value.includes('@internal');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default memberAccessModifierPlugin;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// noinspection SpellCheckingInspection
|
|
12
|
+
import jscodeshift from 'jscodeshift';
|
|
13
|
+
import {defaultMenuTypesMap, defaultModuleMap, defaultRecastOptions, insertMissingImportsForTypes, mapType} from './common.js';
|
|
14
|
+
|
|
15
|
+
const j = jscodeshift.withParser('ts');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @type import('ts-migrate-server').Plugin<{menuTypesMap?: object, moduleMap?: object}>
|
|
19
|
+
*/
|
|
20
|
+
const menuTypesPlugin = {
|
|
21
|
+
name: 'menu-types-plugin',
|
|
22
|
+
|
|
23
|
+
async run({text, fileName, options}) {
|
|
24
|
+
let root = j(text),
|
|
25
|
+
referencedTypes = new Set();
|
|
26
|
+
const menuTypesMap = {...defaultMenuTypesMap, ...options.menuTypesMap},
|
|
27
|
+
moduleMap = {...defaultModuleMap, ...options.moduleMap};
|
|
28
|
+
|
|
29
|
+
// noinspection JSCheckFunctionSignatures
|
|
30
|
+
root.find(j.ObjectProperty, {key: {name: 'menuTypes'}})
|
|
31
|
+
.forEach(/** NodePath<ObjectProperty, ObjectProperty> */path => {
|
|
32
|
+
let node = path.node;
|
|
33
|
+
if (!node.value || node.value.type !== 'ArrayExpression') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let elements = node.value.elements;
|
|
37
|
+
for (let i = 0; i < elements.length; i++) {
|
|
38
|
+
let element = elements[i];
|
|
39
|
+
if (!element || element.type !== 'StringLiteral') {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
let menuType = getMenuTypeForStringMenuType(element.value, menuTypesMap, referencedTypes);
|
|
43
|
+
if (!menuType) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
elements.splice(i, 1, menuType);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
insertMissingImportsForTypes(j, root, Array.from(referencedTypes), moduleMap, fileName);
|
|
51
|
+
return root.toSource(defaultRecastOptions);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function getMenuTypeForStringMenuType(menuTypeString, menuTypeMap, referencedTypes) {
|
|
56
|
+
let menuTypeInfo = menuTypeMap[menuTypeString];
|
|
57
|
+
if (!menuTypeInfo) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
let {objectType, menuTypes, menuType} = menuTypeInfo;
|
|
61
|
+
if (!objectType || !menuTypes || !menuType) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// noinspection DuplicatedCode
|
|
66
|
+
let module = 'scout';
|
|
67
|
+
let name = objectType;
|
|
68
|
+
if (objectType.indexOf('.') > -1) {
|
|
69
|
+
[module, name] = objectType.split('.');
|
|
70
|
+
}
|
|
71
|
+
let type = mapType(j, module + '.' + name);
|
|
72
|
+
referencedTypes.add(type);
|
|
73
|
+
|
|
74
|
+
return j.memberExpression(j.memberExpression(j.identifier(name), j.identifier(menuTypes)), j.identifier(menuType));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default menuTypesPlugin;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
import jscodeshift from 'jscodeshift';
|
|
11
|
+
import {defaultModuleMap, defaultParamTypeMap, defaultRecastOptions, defaultReturnTypeMap, findTypeByName, insertMissingImportsForTypes, mapType, methodFilter, removeEmptyLinesBetweenImports} from './common.js';
|
|
12
|
+
|
|
13
|
+
const j = jscodeshift.withParser('ts');
|
|
14
|
+
let referencedTypes;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Processes class methods and exported functions of utilities.
|
|
18
|
+
*
|
|
19
|
+
* Adds parameter and return types based on naming rules defined in type maps (see {@link defaultParamTypeMap} and {@link defaultParamTypeMap}).
|
|
20
|
+
* Custom type rules can be specified with an option.
|
|
21
|
+
*
|
|
22
|
+
* Also adds required imports for the added types.
|
|
23
|
+
* The types in the type maps can be prefixed with a module name that will be mapped to a npm module by the provided moduleMap (see {@link defaultModuleMap}).
|
|
24
|
+
*
|
|
25
|
+
* Finally, the js doc comments are cleaned up, which means the type information is removed.
|
|
26
|
+
*
|
|
27
|
+
* @type import('ts-migrate-server').Plugin<{paramTypeMap?: object, returnTypeMap?: object, moduleMap?: object, defaultReturnType?: string, defaultParamType?: string}>
|
|
28
|
+
*/
|
|
29
|
+
const methodsPlugin = {
|
|
30
|
+
name: 'methods-plugin',
|
|
31
|
+
|
|
32
|
+
async run({text, options, sourceFile}) {
|
|
33
|
+
let root = j(text);
|
|
34
|
+
const paramTypeMap = {...defaultParamTypeMap, ...options.paramTypeMap};
|
|
35
|
+
const returnTypeMap = {...defaultReturnTypeMap, ...options.returnTypeMap};
|
|
36
|
+
const moduleMap = {...defaultModuleMap, ...options.moduleMap};
|
|
37
|
+
const defaultReturnType = options.defaultReturnType;
|
|
38
|
+
const defaultParamType = options.defaultParamType;
|
|
39
|
+
referencedTypes = new Set();
|
|
40
|
+
|
|
41
|
+
root.find(j.Declaration)
|
|
42
|
+
.filter(path => methodFilter(j, path))
|
|
43
|
+
.forEach(expression => {
|
|
44
|
+
let node = expression.node;
|
|
45
|
+
if (node.params) {
|
|
46
|
+
for (let param of node.params) {
|
|
47
|
+
processParamType(param, Object.values(paramTypeMap), defaultParamType);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
processReturnType(node, Object.values(returnTypeMap), defaultReturnType);
|
|
51
|
+
removeJsDocTypes(node);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
insertMissingImportsForTypes(j, root, Array.from(referencedTypes), moduleMap, sourceFile.fileName);
|
|
55
|
+
return removeEmptyLinesBetweenImports(root.toSource(defaultRecastOptions));
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function processReturnType(func, typeMaps, defaultReturnType) {
|
|
60
|
+
let name = func.key ? func.key.name : func.id.name;
|
|
61
|
+
if (func.returnType) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let typeDesc = findTypeByName(j, typeMaps, name);
|
|
65
|
+
if (!typeDesc && defaultReturnType && func.kind !== 'constructor' && func.kind !== 'set') {
|
|
66
|
+
typeDesc = mapType(j, defaultReturnType);
|
|
67
|
+
}
|
|
68
|
+
if (typeDesc) {
|
|
69
|
+
func.returnType = j.tsTypeAnnotation(typeDesc.type);
|
|
70
|
+
if (typeDesc.module) {
|
|
71
|
+
referencedTypes.add(typeDesc);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function processParamType(param, typeMaps, defaultParamType) {
|
|
77
|
+
let name = param.name;
|
|
78
|
+
if (param.typeAnnotation) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
let typeDesc = findTypeByName(j, typeMaps, name);
|
|
82
|
+
if (!typeDesc && defaultParamType) {
|
|
83
|
+
typeDesc = mapType(j, defaultParamType);
|
|
84
|
+
}
|
|
85
|
+
if (typeDesc) {
|
|
86
|
+
param.typeAnnotation = j.tsTypeAnnotation(typeDesc.type);
|
|
87
|
+
if (typeDesc.module) {
|
|
88
|
+
referencedTypes.add(typeDesc);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Removes all types form jsdoc if the types exist as TS types
|
|
95
|
+
*/
|
|
96
|
+
function removeJsDocTypes(func) {
|
|
97
|
+
let comments = func.comments;
|
|
98
|
+
if (!comments) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let replaceReturnType = !!func.returnType;
|
|
102
|
+
let replaceParams = [];
|
|
103
|
+
if (func.params) {
|
|
104
|
+
replaceParams = func.params.filter(param => !!param.typeAnnotation);
|
|
105
|
+
}
|
|
106
|
+
if (!replaceReturnType && replaceParams.length === 0) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
func.comments = comments.map(comment => {
|
|
110
|
+
if (comment.type !== 'CommentBlock') {
|
|
111
|
+
return comment;
|
|
112
|
+
}
|
|
113
|
+
let str = comment.value;
|
|
114
|
+
str = str.replaceAll(/ +\*/g, ''); // remove * at start of lines, makes the upcoming processing easier
|
|
115
|
+
let beforeReplace = str;
|
|
116
|
+
if (replaceReturnType) {
|
|
117
|
+
str = str.replace(/(@return[s]?) ({.*})/, '@returns'); // remove type from @return
|
|
118
|
+
str = str.replace(/@returns[\s]*$/, ''); // remove empty return at the end
|
|
119
|
+
}
|
|
120
|
+
for (let param of replaceParams) {
|
|
121
|
+
str = str.replace(new RegExp(`@param {.*} \\[?${param.name}\\]?`), `@param ${param.name}`); // remove type from @param
|
|
122
|
+
str = str.replace(new RegExp(`@param \\[?${param.name}\\]? {.*}`), `@param ${param.name}`); // consider reverse typing as well (@param [var] {type} instead of @param {type} [var]
|
|
123
|
+
str = str.replace(new RegExp(`@param \\[${param.name}\\]`), `@param ${param.name}`); // remove brackets even without type
|
|
124
|
+
str = str.replace(new RegExp(`@param ${param.name}[\\s]*$`), ''); // remove empty param at end
|
|
125
|
+
str = str.replace(new RegExp(`@param ${param.name}[\\s]*@param`), '@param'); // remove empty param before param
|
|
126
|
+
str = str.replace(new RegExp(`@param ${param.name}[\\s]*@return`), '@return'); // remove empty param before return
|
|
127
|
+
}
|
|
128
|
+
if (beforeReplace === str) {
|
|
129
|
+
// Do nothing if nothing was replaced
|
|
130
|
+
return comment;
|
|
131
|
+
}
|
|
132
|
+
str = str.replace(/\r\n +$/, '\r\n'); // remove whitespaces at the end (keep new line)
|
|
133
|
+
str = str.replaceAll(/\r\n/g, '\r\n *'); // add * again
|
|
134
|
+
str = str.replace(/\r\n \*$/, '\r\n'); // Remove last * that was added by the line before. It will be added automatically by the block comment.
|
|
135
|
+
if (str.trim() === '*') {
|
|
136
|
+
// Remove empty comments
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return j.commentBlock(str);
|
|
140
|
+
}).filter(comment => comment !== null);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default methodsPlugin;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
import jscodeshift from 'jscodeshift';
|
|
11
|
+
import {findClassProperty, findParentClassBody, getNameForType, isOneOf} from './common.js';
|
|
12
|
+
|
|
13
|
+
const j = jscodeshift.withParser('ts');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type import('ts-migrate-server').Plugin<{}>
|
|
17
|
+
*/
|
|
18
|
+
const printEventMapsPlugin = {
|
|
19
|
+
name: 'print-event-maps-plugin',
|
|
20
|
+
|
|
21
|
+
async run({text, fileName, options}) {
|
|
22
|
+
let root = j(text);
|
|
23
|
+
|
|
24
|
+
let eventLines = new Set();
|
|
25
|
+
let propEvents = new Map();
|
|
26
|
+
let className = fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.'));
|
|
27
|
+
|
|
28
|
+
root.find(j.CallExpression)
|
|
29
|
+
.filter(path =>
|
|
30
|
+
path.value.callee.type === 'MemberExpression'
|
|
31
|
+
&& path.value.callee.object.type === 'ThisExpression'
|
|
32
|
+
&& isOneOf(path.value.callee.property.name, 'setProperty', '_setProperty', 'trigger')
|
|
33
|
+
)
|
|
34
|
+
.forEach(expression => {
|
|
35
|
+
let funcName = expression.value.callee.property.name;
|
|
36
|
+
let eventName = expression.value.arguments[0]?.value;
|
|
37
|
+
if (isOneOf(funcName, 'setProperty', '_setProperty')) {
|
|
38
|
+
let type = '?';
|
|
39
|
+
let property = findClassProperty(findParentClassBody(expression), eventName);
|
|
40
|
+
if (property) {
|
|
41
|
+
let typeAnnotation = property.typeAnnotation;
|
|
42
|
+
type = typeAnnotation ? getNameForType(j, typeAnnotation?.typeAnnotation) || '?' : '?';
|
|
43
|
+
}
|
|
44
|
+
let value = propEvents.get(eventName);
|
|
45
|
+
if (value && !value.includes('<?>')) {
|
|
46
|
+
// Don't replace existing value if it already has a type
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
propEvents.set(eventName, `'propertyChange:${eventName}': PropertyChangeEvent<${type}>;`);
|
|
50
|
+
} else {
|
|
51
|
+
let eventObj = expression.value.arguments[1];
|
|
52
|
+
let event = '?';
|
|
53
|
+
if (!eventObj) {
|
|
54
|
+
event = `Event<${className}>`;
|
|
55
|
+
}
|
|
56
|
+
if (!eventName) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
eventLines.add(`'${eventName}': ${event};`);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (eventLines.size > 0 || propEvents.size > 0) {
|
|
64
|
+
console.log(`${className}EventMap`);
|
|
65
|
+
if (eventLines.size > 0) {
|
|
66
|
+
console.log(Array.from(eventLines).sort().join('\n'));
|
|
67
|
+
}
|
|
68
|
+
if (propEvents.size > 0) {
|
|
69
|
+
console.log(Array.from(propEvents.values()).sort().join('\n'));
|
|
70
|
+
}
|
|
71
|
+
console.log('\n');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return text;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default printEventMapsPlugin;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made
|
|
5
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
6
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
9
|
+
*/
|
|
10
|
+
import jscodeshift from 'jscodeshift';
|
|
11
|
+
import {defaultModuleMap, defaultRecastOptions, insertMissingImportsForTypes, isOneOf, mapType, removeEmptyLinesBetweenImports} from './common.js';
|
|
12
|
+
|
|
13
|
+
const j = jscodeshift.withParser('ts');
|
|
14
|
+
let referencedTypes;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @type import('ts-migrate-server').Plugin<{moduleMap?: object}>
|
|
18
|
+
*/
|
|
19
|
+
const typedObjectTypePlugin = {
|
|
20
|
+
name: 'typed-object-type-plugin',
|
|
21
|
+
|
|
22
|
+
async run({text, options, sourceFile}) {
|
|
23
|
+
let root = j(text);
|
|
24
|
+
const moduleMap = {...defaultModuleMap, ...options.moduleMap};
|
|
25
|
+
referencedTypes = new Set();
|
|
26
|
+
|
|
27
|
+
root.find(j.ObjectProperty)
|
|
28
|
+
.filter(path =>
|
|
29
|
+
isOneOf(path.value.key.name, 'objectType', 'logicalGrid', 'lookupCall') &&
|
|
30
|
+
path.value.value.type === j.StringLiteral.name)
|
|
31
|
+
.forEach(path => {
|
|
32
|
+
let objectType = path.value.value.value;
|
|
33
|
+
path.node.value = getTypeForStringObjectType(objectType);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
root.find(j.CallExpression)
|
|
37
|
+
.filter(path =>
|
|
38
|
+
path.value.callee.type === j.MemberExpression.name &&
|
|
39
|
+
path.value.callee.object.name === 'scout' &&
|
|
40
|
+
path.value.callee.property.name === 'create' &&
|
|
41
|
+
path.value.arguments[0].type === j.StringLiteral.name)
|
|
42
|
+
.forEach(path => {
|
|
43
|
+
let objectType = path.value.arguments[0].value;
|
|
44
|
+
path.node.arguments[0] = getTypeForStringObjectType(objectType);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
insertMissingImportsForTypes(j, root, Array.from(referencedTypes), moduleMap, sourceFile.fileName);
|
|
48
|
+
return removeEmptyLinesBetweenImports(root.toSource(defaultRecastOptions));
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function getTypeForStringObjectType(objectType) {
|
|
53
|
+
// noinspection DuplicatedCode
|
|
54
|
+
let module = 'scout';
|
|
55
|
+
let name = objectType;
|
|
56
|
+
if (objectType.indexOf('.') > -1) {
|
|
57
|
+
[module, name] = objectType.split('.');
|
|
58
|
+
}
|
|
59
|
+
let type = mapType(j, module + '.' + name);
|
|
60
|
+
referencedTypes.add(type);
|
|
61
|
+
return j.identifier(name);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default typedObjectTypePlugin;
|