1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | Object.defineProperty(exports, "__esModule", { value: true });
|
13 | const ts = require("./ts-ast");
|
14 | const { parseType, parseParamType } = require('doctrine/lib/typed.js');
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | function closureTypeToTypeScript(closureType, templateTypes = []) {
|
23 | if (!closureType) {
|
24 | return ts.anyType;
|
25 | }
|
26 | let ast;
|
27 | try {
|
28 | ast = parseType(closureType);
|
29 | }
|
30 | catch (_a) {
|
31 | return ts.anyType;
|
32 | }
|
33 | return convert(ast, templateTypes);
|
34 | }
|
35 | exports.closureTypeToTypeScript = closureTypeToTypeScript;
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | function closureParamToTypeScript(name, closureType, templateTypes = []) {
|
46 | if (!closureType) {
|
47 | return new ts.ParamType({
|
48 | name,
|
49 | type: ts.anyType,
|
50 | optional: false,
|
51 | rest: false,
|
52 | });
|
53 | }
|
54 | let ast;
|
55 | try {
|
56 | ast = parseParamType(closureType);
|
57 | }
|
58 | catch (_a) {
|
59 | return new ts.ParamType({
|
60 | name,
|
61 | type: ts.anyType,
|
62 |
|
63 |
|
64 |
|
65 | optional: closureType.endsWith('='),
|
66 | rest: false,
|
67 | });
|
68 | }
|
69 | return convertParam(name, ast, templateTypes);
|
70 | }
|
71 | exports.closureParamToTypeScript = closureParamToTypeScript;
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | function convertParam(name, node, templateTypes) {
|
77 | switch (node.type) {
|
78 | case 'OptionalType':
|
79 | return new ts.ParamType({
|
80 | name,
|
81 | type: convert(node.expression, templateTypes),
|
82 | optional: true,
|
83 | rest: false,
|
84 | });
|
85 | case 'RestType':
|
86 | return new ts.ParamType({
|
87 | name,
|
88 |
|
89 |
|
90 |
|
91 | type: new ts.ArrayType(node.expression !== undefined ?
|
92 | convert(node.expression, templateTypes) :
|
93 | ts.anyType),
|
94 | optional: false,
|
95 | rest: true,
|
96 | });
|
97 | default:
|
98 | return new ts.ParamType({
|
99 | name,
|
100 | type: convert(node, templateTypes),
|
101 | optional: false,
|
102 | rest: false,
|
103 | });
|
104 | }
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 | function convert(node, templateTypes) {
|
110 | let nullable;
|
111 | if (isNullable(node)) {
|
112 | nullable = true;
|
113 | node = node.expression;
|
114 | }
|
115 | else if (isNonNullable(node)) {
|
116 | nullable = false;
|
117 | node = node.expression;
|
118 | }
|
119 | else if (isName(node) && templateTypes.includes(node.name)) {
|
120 |
|
121 |
|
122 |
|
123 | nullable = false;
|
124 | }
|
125 | else {
|
126 | nullable = nullableByDefault(node);
|
127 | }
|
128 | let t;
|
129 | if (isParameterizedArray(node)) {
|
130 | t = convertArray(node, templateTypes);
|
131 | }
|
132 | else if (isParameterizedObject(node)) {
|
133 | t = convertIndexableObject(node, templateTypes);
|
134 | }
|
135 | else if (isBarePromise(node)) {
|
136 |
|
137 |
|
138 | t = new ts.ParameterizedType('Promise', [ts.anyType]);
|
139 | }
|
140 | else if (isParameterizedType(node)) {
|
141 | t = convertParameterizedType(node, templateTypes);
|
142 | }
|
143 | else if (isUnion(node)) {
|
144 | t = convertUnion(node, templateTypes);
|
145 | }
|
146 | else if (isFunction(node)) {
|
147 | t = convertFunction(node, templateTypes);
|
148 | }
|
149 | else if (isBareArray(node)) {
|
150 | t = new ts.ArrayType(ts.anyType);
|
151 | }
|
152 | else if (isRecordType(node)) {
|
153 | t = convertRecord(node, templateTypes);
|
154 | }
|
155 | else if (isAllLiteral(node)) {
|
156 | t = ts.anyType;
|
157 | }
|
158 | else if (isNullableLiteral(node)) {
|
159 | t = ts.anyType;
|
160 | }
|
161 | else if (isNullLiteral(node)) {
|
162 | t = ts.nullType;
|
163 | }
|
164 | else if (isUndefinedLiteral(node)) {
|
165 | t = ts.undefinedType;
|
166 | }
|
167 | else if (isVoidLiteral(node)) {
|
168 | t = new ts.NameType('void');
|
169 | }
|
170 | else if (isName(node)) {
|
171 | t = new ts.NameType(renameMap.get(node.name) || node.name);
|
172 | }
|
173 | else {
|
174 | console.error('Unknown syntax.');
|
175 | return ts.anyType;
|
176 | }
|
177 | if (nullable) {
|
178 | t = new ts.UnionType([t, ts.nullType]);
|
179 | }
|
180 | return t;
|
181 | }
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | const renameMap = new Map([
|
187 |
|
188 |
|
189 |
|
190 | ['Object', 'object'],
|
191 |
|
192 | ['ITemplateArray', 'TemplateStringsArray'],
|
193 | ]);
|
194 |
|
195 |
|
196 |
|
197 | const parameterizedRenameMap = new Map([
|
198 | ['HTMLCollection', 'HTMLCollectionOf'],
|
199 | ['NodeList', 'NodeListOf'],
|
200 | ]);
|
201 |
|
202 |
|
203 |
|
204 |
|
205 | function nullableByDefault(node) {
|
206 | if (isName(node)) {
|
207 | switch (node.name) {
|
208 | case 'string':
|
209 | case 'number':
|
210 | case 'boolean':
|
211 | case 'void':
|
212 | return false;
|
213 | }
|
214 | return true;
|
215 | }
|
216 | return isParameterizedArray(node);
|
217 | }
|
218 | function convertArray(node, templateTypes) {
|
219 | const applications = node.applications;
|
220 | return new ts.ArrayType(applications.length === 1 ? convert(applications[0], templateTypes) :
|
221 | ts.anyType);
|
222 | }
|
223 | function convertIndexableObject(node, templateTypes) {
|
224 | if (node.applications.length !== 2) {
|
225 | console.error('Parameterized Object must have two parameters.');
|
226 | return ts.anyType;
|
227 | }
|
228 | return new ts.IndexableObjectType(convert(node.applications[0], templateTypes), convert(node.applications[1], templateTypes));
|
229 | }
|
230 | function convertParameterizedType(node, templateTypes) {
|
231 | if (!isName(node.expression)) {
|
232 | console.error('Could not find name of parameterized type');
|
233 | return ts.anyType;
|
234 | }
|
235 | const types = node.applications.map((application) => convert(application, templateTypes));
|
236 | const name = renameMap.get(node.expression.name) ||
|
237 | parameterizedRenameMap.get(node.expression.name) || node.expression.name;
|
238 | return new ts.ParameterizedType(name, types);
|
239 | }
|
240 | function convertUnion(node, templateTypes) {
|
241 | return new ts.UnionType(node.elements.map((element) => convert(element, templateTypes)));
|
242 | }
|
243 | function convertFunction(node, templateTypes) {
|
244 | const params = node.params.map((param, idx) => convertParam(
|
245 |
|
246 | 'p' + idx, param, templateTypes));
|
247 | if (node.new) {
|
248 | return new ts.ConstructorType(params,
|
249 |
|
250 |
|
251 |
|
252 | isName(node.this) ? new ts.NameType(node.this.name) : ts.anyType);
|
253 | }
|
254 | else {
|
255 | return new ts.FunctionType(params,
|
256 |
|
257 | node.result ?
|
258 | convert(node.result, templateTypes) :
|
259 | ts.anyType);
|
260 | }
|
261 | }
|
262 | function convertRecord(node, templateTypes) {
|
263 | const fields = [];
|
264 | for (const field of node.fields) {
|
265 | if (field.type !== 'FieldType') {
|
266 | return ts.anyType;
|
267 | }
|
268 | const fieldType = field.value ? convert(field.value, templateTypes) : ts.anyType;
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 | let optional = false;
|
275 | if (fieldType.kind === 'union') {
|
276 | fieldType.members = fieldType.members.filter((member) => {
|
277 | if (member.kind === 'name' && member.name === 'undefined') {
|
278 | optional = true;
|
279 | return false;
|
280 | }
|
281 | return true;
|
282 | });
|
283 |
|
284 | fieldType.simplify();
|
285 | }
|
286 | fields.push(new ts.ParamType({ name: field.key, type: fieldType, optional }));
|
287 | }
|
288 | return new ts.RecordType(fields);
|
289 | }
|
290 | function isParameterizedArray(node) {
|
291 | return node.type === 'TypeApplication' &&
|
292 | node.expression.type === 'NameExpression' &&
|
293 | node.expression.name === 'Array';
|
294 | }
|
295 | function isParameterizedType(node) {
|
296 | return node.type === 'TypeApplication';
|
297 | }
|
298 | function isBareArray(node) {
|
299 | return node.type === 'NameExpression' && node.name === 'Array';
|
300 | }
|
301 | function isBarePromise(node) {
|
302 | return node.type === 'NameExpression' && node.name === 'Promise';
|
303 | }
|
304 |
|
305 |
|
306 |
|
307 | function isParameterizedObject(node) {
|
308 | return node.type === 'TypeApplication' &&
|
309 | node.expression.type === 'NameExpression' &&
|
310 | node.expression.name === 'Object';
|
311 | }
|
312 | function isUnion(node) {
|
313 | return node.type === 'UnionType';
|
314 | }
|
315 | function isFunction(node) {
|
316 | return node.type === 'FunctionType';
|
317 | }
|
318 | function isRecordType(node) {
|
319 | return node.type === 'RecordType';
|
320 | }
|
321 | function isNullable(node) {
|
322 | return node.type === 'NullableType';
|
323 | }
|
324 | function isNonNullable(node) {
|
325 | return node.type === 'NonNullableType';
|
326 | }
|
327 | function isAllLiteral(node) {
|
328 | return node.type === 'AllLiteral';
|
329 | }
|
330 | function isNullLiteral(node) {
|
331 | return node.type === 'NullLiteral';
|
332 | }
|
333 | function isNullableLiteral(node) {
|
334 | return node.type === 'NullableLiteral';
|
335 | }
|
336 | function isUndefinedLiteral(node) {
|
337 | return node.type === 'UndefinedLiteral';
|
338 | }
|
339 | function isVoidLiteral(node) {
|
340 | return node.type === 'VoidLiteral';
|
341 | }
|
342 | function isName(node) {
|
343 | return node.type === 'NameExpression';
|
344 | }
|
345 |
|
\ | No newline at end of file |