@next-core/build-next-bricks 1.9.0 → 1.11.0
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/package.json +3 -3
- package/src/getTypeDeclaration.js +377 -0
- package/src/makeBrickManifest.js +246 -18
- package/src/scanBricks.js +136 -77
- package/src/utils.js +0 -227
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next-core/build-next-bricks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Build next bricks",
|
|
5
5
|
"homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/build-next-bricks",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"webpack": "^5.84.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@next-core/brick-manifest": "^0.
|
|
52
|
+
"@next-core/brick-manifest": "^0.4.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "93ee03d986df5388568ed2ea424833718d6fc7eb"
|
|
55
55
|
}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { parseTypeComment } from "./makeBrickManifest.js";
|
|
3
|
+
|
|
4
|
+
/** @typedef {import("@babel/types").Node} Node */
|
|
5
|
+
/** @typedef {import("@next-core/brick-manifest").Declaration} Declaration */
|
|
6
|
+
/** @typedef {import("@next-core/brick-manifest").Annotation} Annotation */
|
|
7
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationTypeParameterDeclaration} AnnotationTypeParameterDeclaration */
|
|
8
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationTypeParameterInstantiation} AnnotationTypeParameterInstantiation */
|
|
9
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationExpressionWithTypeArguments} AnnotationExpressionWithTypeArguments */
|
|
10
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationEnumMember} AnnotationEnumMember */
|
|
11
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationTypeParameter} AnnotationTypeParameter */
|
|
12
|
+
/** @typedef {import("@next-core/brick-manifest").AnnotationPropertySignature} AnnotationPropertySignature */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Node | null | undefined} node
|
|
16
|
+
* @param {string} source
|
|
17
|
+
* @param {Set<string>} usedReferences
|
|
18
|
+
* @returns {Declaration | undefined}
|
|
19
|
+
*/
|
|
20
|
+
export default function getTypeDeclaration(node, source, usedReferences) {
|
|
21
|
+
switch (node.type) {
|
|
22
|
+
case "TSInterfaceDeclaration":
|
|
23
|
+
// interface A { ... }
|
|
24
|
+
return {
|
|
25
|
+
type: "interface",
|
|
26
|
+
name: node.id.name,
|
|
27
|
+
typeParameters:
|
|
28
|
+
/** @type {AnnotationTypeParameterDeclaration | undefined} */
|
|
29
|
+
(getTypeAnnotation(node.typeParameters, source, usedReferences)),
|
|
30
|
+
body: node.body.body.map(
|
|
31
|
+
(item) =>
|
|
32
|
+
/** @type {AnnotationPropertySignature} */
|
|
33
|
+
(getTypeAnnotation(item, source, usedReferences))
|
|
34
|
+
),
|
|
35
|
+
extends:
|
|
36
|
+
/** @type {AnnotationExpressionWithTypeArguments[] | undefined} */
|
|
37
|
+
(
|
|
38
|
+
node.extends?.map((item) =>
|
|
39
|
+
getTypeAnnotation(item, source, usedReferences)
|
|
40
|
+
)
|
|
41
|
+
),
|
|
42
|
+
...parseTypeComment(node, source),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
case "TSTypeAliasDeclaration":
|
|
46
|
+
// type A = B
|
|
47
|
+
return {
|
|
48
|
+
type: "typeAlias",
|
|
49
|
+
name: node.id.name,
|
|
50
|
+
typeParameters:
|
|
51
|
+
/** @type {AnnotationTypeParameterDeclaration | undefined} */
|
|
52
|
+
(getTypeAnnotation(node.typeParameters, source, usedReferences)),
|
|
53
|
+
annotation: getTypeAnnotation(
|
|
54
|
+
node.typeAnnotation,
|
|
55
|
+
source,
|
|
56
|
+
usedReferences
|
|
57
|
+
),
|
|
58
|
+
...parseTypeComment(node, source),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
case "TSEnumDeclaration":
|
|
62
|
+
// enum A { ... }
|
|
63
|
+
return {
|
|
64
|
+
type: "enum",
|
|
65
|
+
name: node.id.name,
|
|
66
|
+
members:
|
|
67
|
+
/** @type {AnnotationEnumMember[] | undefined} */
|
|
68
|
+
(
|
|
69
|
+
node.members.map((item) =>
|
|
70
|
+
getTypeAnnotation(item, source, usedReferences)
|
|
71
|
+
)
|
|
72
|
+
),
|
|
73
|
+
...parseTypeComment(node, source),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Node | null | undefined} entryNode
|
|
80
|
+
* @param {string} source
|
|
81
|
+
* @param {Set<string>} usedReferences
|
|
82
|
+
* @returns {Annotation | undefined}
|
|
83
|
+
*/
|
|
84
|
+
export function getTypeAnnotation(entryNode, source, usedReferences) {
|
|
85
|
+
/**
|
|
86
|
+
* @param {Node | null | undefined} node
|
|
87
|
+
* @param {Boolean =} isRef
|
|
88
|
+
* @returns {Annotation | undefined}
|
|
89
|
+
*/
|
|
90
|
+
function get(node, isRef) {
|
|
91
|
+
if (!node) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
switch (node.type) {
|
|
95
|
+
case "TSEnumMember":
|
|
96
|
+
// enum A { b = "B", c = "C" }
|
|
97
|
+
// ^^^^^^^
|
|
98
|
+
return {
|
|
99
|
+
type: "enumMember",
|
|
100
|
+
id: get(node.id),
|
|
101
|
+
initializer: get(node.initializer),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
case "TSTypeAnnotation":
|
|
105
|
+
// let a: MyType
|
|
106
|
+
// ^^^^^^
|
|
107
|
+
return get(node.typeAnnotation);
|
|
108
|
+
|
|
109
|
+
case "TSTypeReference":
|
|
110
|
+
// type A = B
|
|
111
|
+
// ^
|
|
112
|
+
return {
|
|
113
|
+
type: "reference",
|
|
114
|
+
typeName: get(node.typeName, true),
|
|
115
|
+
typeParameters:
|
|
116
|
+
/** @type {AnnotationTypeParameterInstantiation | undefined} */
|
|
117
|
+
(get(node.typeParameters)),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
case "TSQualifiedName":
|
|
121
|
+
// type A = B.C
|
|
122
|
+
// ^^^
|
|
123
|
+
return {
|
|
124
|
+
type: "qualifiedName",
|
|
125
|
+
left: get(node.left, true),
|
|
126
|
+
right: get(node.right),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
case "TSUnionType":
|
|
130
|
+
// type A = string | number
|
|
131
|
+
// ^^^^^^^^^^^^^^^
|
|
132
|
+
return {
|
|
133
|
+
type: "union",
|
|
134
|
+
types: node.types.map((item) => get(item)),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
case "TSArrayType":
|
|
138
|
+
// type A = string[]
|
|
139
|
+
// ^^^^^^^^
|
|
140
|
+
return {
|
|
141
|
+
type: "array",
|
|
142
|
+
elementType: get(node.elementType),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
case "TSTupleType":
|
|
146
|
+
// type A = [string, number]
|
|
147
|
+
// ^^^^^^^^^^^^^^^^
|
|
148
|
+
return {
|
|
149
|
+
type: "tuple",
|
|
150
|
+
elementTypes: node.elementTypes.map((item) => get(item)),
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
case "TSNamedTupleMember":
|
|
154
|
+
// type A = [x: number, y: number]
|
|
155
|
+
// ^^^^^^^^^
|
|
156
|
+
return {
|
|
157
|
+
type: "namedTupleMember",
|
|
158
|
+
label: node.label.name,
|
|
159
|
+
optional: node.optional,
|
|
160
|
+
elementType: get(node.elementType),
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
case "TSIntersectionType":
|
|
164
|
+
// type A = B & C
|
|
165
|
+
// ^^^^^
|
|
166
|
+
return {
|
|
167
|
+
type: "intersection",
|
|
168
|
+
types: node.types.map((item) => get(item)),
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
case "TSTypeLiteral":
|
|
172
|
+
// type A = { prop: number }
|
|
173
|
+
// ^^^^^^^^^^^^^^^^
|
|
174
|
+
return {
|
|
175
|
+
type: "typeLiteral",
|
|
176
|
+
members: node.members.map((item) => get(item)),
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
case "TSPropertySignature":
|
|
180
|
+
// interface A { prop: number }
|
|
181
|
+
// ^^^^^^^^^^^^
|
|
182
|
+
return {
|
|
183
|
+
type: "propertySignature",
|
|
184
|
+
key: get(node.key),
|
|
185
|
+
annotation: get(node.typeAnnotation),
|
|
186
|
+
// initializer: get(node.initializer),
|
|
187
|
+
optional: node.optional,
|
|
188
|
+
computed: node.computed,
|
|
189
|
+
readonly: node.readonly,
|
|
190
|
+
kind: node.kind,
|
|
191
|
+
...parseTypeComment(node, source),
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
case "TSMethodSignature":
|
|
195
|
+
// interface A { call(a: number): void }
|
|
196
|
+
// ^^^^^^^^^^^^^^^^^^^^^
|
|
197
|
+
return {
|
|
198
|
+
type: "methodSignature",
|
|
199
|
+
key: get(node.key),
|
|
200
|
+
typeParameters:
|
|
201
|
+
/** @type {AnnotationTypeParameterDeclaration | undefined} */
|
|
202
|
+
(get(node.typeParameters)),
|
|
203
|
+
parameters: node.parameters.map((item) => get(item)),
|
|
204
|
+
annotation: get(node.typeAnnotation),
|
|
205
|
+
optional: node.optional,
|
|
206
|
+
computed: node.computed,
|
|
207
|
+
kind: node.kind,
|
|
208
|
+
...parseTypeComment(node, source),
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
case "TSIndexSignature":
|
|
212
|
+
// interface A { [k: string]: number }
|
|
213
|
+
// ^^^^^^^^^^^^^^^^^^^
|
|
214
|
+
return {
|
|
215
|
+
type: "indexSignature",
|
|
216
|
+
parameter: get(node.parameters[0]),
|
|
217
|
+
annotation: get(node.typeAnnotation),
|
|
218
|
+
...parseTypeComment(node, source),
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
case "TSIndexedAccessType":
|
|
222
|
+
// type A = B["C"]
|
|
223
|
+
// ^^^^^^
|
|
224
|
+
return {
|
|
225
|
+
type: "indexedAccess",
|
|
226
|
+
objectType: get(node.objectType),
|
|
227
|
+
indexType: get(node.indexType),
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
case "TSTypeParameterDeclaration":
|
|
231
|
+
// interface A<T, P> {}
|
|
232
|
+
// ^^^^^^
|
|
233
|
+
return {
|
|
234
|
+
type: "typeParameterDeclaration",
|
|
235
|
+
params:
|
|
236
|
+
/** @type {AnnotationTypeParameter[]} */
|
|
237
|
+
(node.params.map((item) => get(item))),
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
case "TSTypeParameterInstantiation":
|
|
241
|
+
// type A = B<T, P>
|
|
242
|
+
// ^^^^^^
|
|
243
|
+
return {
|
|
244
|
+
type: "typeParameterInstantiation",
|
|
245
|
+
params: node.params.map((item) => get(item)),
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
case "TSTypeParameter":
|
|
249
|
+
// interface A<T extends string = "", P> {}
|
|
250
|
+
// ^^^^^^^^^^^^^^^^^^^^^
|
|
251
|
+
return {
|
|
252
|
+
type: "typeParameter",
|
|
253
|
+
name: node.name,
|
|
254
|
+
default: get(node.default),
|
|
255
|
+
constraint: get(node.constraint),
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
case "TSLiteralType":
|
|
259
|
+
return get(node.literal);
|
|
260
|
+
|
|
261
|
+
case "TSTypeOperator":
|
|
262
|
+
// type A = keyof B
|
|
263
|
+
// ^^^^^^^
|
|
264
|
+
return {
|
|
265
|
+
type: "typeOperator",
|
|
266
|
+
operator: node.operator,
|
|
267
|
+
annotation: get(node.typeAnnotation),
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
case "TSTypeQuery":
|
|
271
|
+
// type A = typeof B<T>
|
|
272
|
+
// ^^^^^^^^^^^
|
|
273
|
+
return {
|
|
274
|
+
type: "typeQuery",
|
|
275
|
+
exprName: get(node.exprName),
|
|
276
|
+
typeParameters:
|
|
277
|
+
/** @type {AnnotationTypeParameterInstantiation | undefined} */
|
|
278
|
+
(get(node.typeParameters)),
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
case "TSExpressionWithTypeArguments":
|
|
282
|
+
// interface A extends B<T>, C
|
|
283
|
+
// ^^^^
|
|
284
|
+
return {
|
|
285
|
+
type: "expressionWithTypeArguments",
|
|
286
|
+
expression: get(node.expression),
|
|
287
|
+
typeParameters:
|
|
288
|
+
/** @type {AnnotationTypeParameterInstantiation | undefined} */
|
|
289
|
+
(get(node.typeParameters)),
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
case "Identifier":
|
|
293
|
+
// interface A { call(a: number) => void }
|
|
294
|
+
// ^^^^^^^^^
|
|
295
|
+
if (isRef) {
|
|
296
|
+
usedReferences.add(node.name);
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
type: "identifier",
|
|
300
|
+
name: node.name,
|
|
301
|
+
annotation: get(node.typeAnnotation),
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
case "RestElement":
|
|
305
|
+
// interface A { call(a, ...rest: unknown[]) => void }
|
|
306
|
+
// ^^^^^^^^^^^^^^^^^^
|
|
307
|
+
return {
|
|
308
|
+
type: "restElement",
|
|
309
|
+
argument: get(node.argument),
|
|
310
|
+
annotation: get(node.typeAnnotation),
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
case "TSFunctionType":
|
|
314
|
+
// interface A { call: (a: number) => void }
|
|
315
|
+
// ^^^^^^^^^^^^^^^^^^^
|
|
316
|
+
return {
|
|
317
|
+
type: "function",
|
|
318
|
+
typeParameters:
|
|
319
|
+
/** @type {AnnotationTypeParameterDeclaration | undefined} */
|
|
320
|
+
(get(node.typeParameters)),
|
|
321
|
+
parameters: node.parameters.map((item) => get(item)),
|
|
322
|
+
annotation: get(node.typeAnnotation),
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
case "StringLiteral":
|
|
326
|
+
case "NumericLiteral":
|
|
327
|
+
case "BooleanLiteral":
|
|
328
|
+
return {
|
|
329
|
+
type: "jsLiteral",
|
|
330
|
+
value: node.value,
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
case "NullLiteral":
|
|
334
|
+
return {
|
|
335
|
+
type: "jsLiteral",
|
|
336
|
+
value: null,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// <!-- Keywords start
|
|
340
|
+
case "TSAnyKeyword":
|
|
341
|
+
return { type: "keyword", value: "any" };
|
|
342
|
+
case "TSBooleanKeyword":
|
|
343
|
+
return { type: "keyword", value: "boolean" };
|
|
344
|
+
case "TSBigIntKeyword":
|
|
345
|
+
return { type: "keyword", value: "bigint" };
|
|
346
|
+
case "TSNullKeyword":
|
|
347
|
+
return { type: "keyword", value: "null" };
|
|
348
|
+
case "TSNumberKeyword":
|
|
349
|
+
return { type: "keyword", value: "number" };
|
|
350
|
+
case "TSObjectKeyword":
|
|
351
|
+
return { type: "keyword", value: "object" };
|
|
352
|
+
case "TSStringKeyword":
|
|
353
|
+
return { type: "keyword", value: "string" };
|
|
354
|
+
case "TSUndefinedKeyword":
|
|
355
|
+
return { type: "keyword", value: "undefined" };
|
|
356
|
+
case "TSUnknownKeyword":
|
|
357
|
+
return { type: "keyword", value: "unknown" };
|
|
358
|
+
case "TSVoidKeyword":
|
|
359
|
+
return { type: "keyword", value: "void" };
|
|
360
|
+
case "TSSymbolKeyword":
|
|
361
|
+
return { type: "keyword", value: "symbol" };
|
|
362
|
+
case "TSNeverKeyword":
|
|
363
|
+
return { type: "keyword", value: "never" };
|
|
364
|
+
// Keywords end -->
|
|
365
|
+
|
|
366
|
+
default:
|
|
367
|
+
return {
|
|
368
|
+
type: "unsupported",
|
|
369
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
370
|
+
// @ts-ignore
|
|
371
|
+
source: source.substring(node.start, node.end),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return get(entryNode);
|
|
377
|
+
}
|
package/src/makeBrickManifest.js
CHANGED
|
@@ -1,33 +1,67 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import { parse } from "doctrine";
|
|
3
|
+
import { getTypeAnnotation } from "./getTypeDeclaration.js";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* @typedef {import("@next-core/brick-manifest").BrickManifest} BrickManifest
|
|
5
7
|
* @typedef {import("@next-core/brick-manifest").PropertyManifest} PropertyManifest
|
|
6
8
|
* @typedef {import("@next-core/brick-manifest").EventManifest} EventManifest
|
|
7
9
|
* @typedef {import("@next-core/brick-manifest").MethodManifest} MethodManifest
|
|
10
|
+
* @typedef {import("@next-core/brick-manifest").MethodParamManifest} MethodParamManifest
|
|
8
11
|
* @typedef {import("@next-core/brick-manifest").ProviderManifest} ProviderManifest
|
|
12
|
+
* @typedef {import("@next-core/brick-manifest").Annotation} Annotation
|
|
9
13
|
* @typedef {import("@babel/types").Node} Node
|
|
10
14
|
* @typedef {import("@babel/traverse").NodePath} NodePath
|
|
11
15
|
* @typedef {import("@babel/types").ClassDeclaration} ClassDeclaration
|
|
16
|
+
* @typedef {import("@babel/types").Identifier} Identifier
|
|
12
17
|
* @typedef {import("doctrine").Tag} Tag
|
|
18
|
+
* @typedef {BrickManifest & { types: BrickTypes; }} BrickManifestAndTypes
|
|
19
|
+
* @typedef {{ name: string; annotation?: Annotation }} BrickPropertyWithAnnotation
|
|
20
|
+
* @typedef {{ name: string; detail: { annotation: Annotation } }} BrickEventWithAnnotation
|
|
21
|
+
* @typedef {{ name: string; params: BrickMethodParamWithAnnotation[]; returns: { annotation?: Annotation } }} BrickMethodWithAnnotation
|
|
22
|
+
* @typedef {{ name: string; annotation?: Annotation }} BrickMethodParamWithAnnotation
|
|
23
|
+
* @typedef {{
|
|
24
|
+
* properties: BrickPropertyWithAnnotation[];
|
|
25
|
+
* events: BrickEventWithAnnotation[];
|
|
26
|
+
* methods: BrickMethodWithAnnotation[];
|
|
27
|
+
* usedReferences?: Set<string>;
|
|
28
|
+
* }} BrickTypes
|
|
29
|
+
* @typedef {ProviderManifest & {
|
|
30
|
+
* params: (MethodParamManifest & {
|
|
31
|
+
* annotation?: Annotation;
|
|
32
|
+
* })[];
|
|
33
|
+
* returns?: {
|
|
34
|
+
* description?: string;
|
|
35
|
+
* annotation?: Annotation;
|
|
36
|
+
* };
|
|
37
|
+
* typeParameters?: Annotation;
|
|
38
|
+
* usedReferences?: Set<string>;
|
|
39
|
+
* }} ProviderManifestAndTypes
|
|
13
40
|
*/
|
|
14
41
|
|
|
15
42
|
/**
|
|
16
43
|
* @param {string} name
|
|
17
44
|
* @param {NodePath} nodePath
|
|
18
45
|
* @param {string} source
|
|
19
|
-
* @returns {
|
|
46
|
+
* @returns {BrickManifestAndTypes}
|
|
20
47
|
*/
|
|
21
48
|
export default function makeBrickManifest(name, nodePath, source) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
49
|
+
const classPath =
|
|
50
|
+
/** @type {import("@babel/traverse").NodePath<ClassDeclaration>} */ (
|
|
51
|
+
nodePath.parentPath
|
|
52
|
+
);
|
|
53
|
+
/** @type {BrickManifestAndTypes} */
|
|
25
54
|
const manifest = {
|
|
26
55
|
name,
|
|
27
56
|
properties: [],
|
|
28
57
|
events: [],
|
|
29
58
|
slots: [],
|
|
30
59
|
methods: [],
|
|
60
|
+
types: {
|
|
61
|
+
properties: [],
|
|
62
|
+
events: [],
|
|
63
|
+
methods: [],
|
|
64
|
+
},
|
|
31
65
|
};
|
|
32
66
|
|
|
33
67
|
const docComment = findDocComment(nodePath, source);
|
|
@@ -50,7 +84,11 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
50
84
|
}
|
|
51
85
|
}
|
|
52
86
|
|
|
53
|
-
|
|
87
|
+
manifest.types.usedReferences = scanFields(
|
|
88
|
+
manifest,
|
|
89
|
+
classPath.node.body.body,
|
|
90
|
+
source
|
|
91
|
+
);
|
|
54
92
|
|
|
55
93
|
return manifest;
|
|
56
94
|
}
|
|
@@ -59,18 +97,74 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
59
97
|
* @param {string} name
|
|
60
98
|
* @param {NodePath} nodePath
|
|
61
99
|
* @param {string} source
|
|
62
|
-
* @returns {
|
|
100
|
+
* @returns {ProviderManifestAndTypes}
|
|
63
101
|
*/
|
|
64
102
|
export function makeProviderManifest(name, nodePath, source) {
|
|
65
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* @type {ProviderManifestAndTypes}
|
|
105
|
+
*/
|
|
66
106
|
const manifest = {
|
|
67
107
|
name,
|
|
108
|
+
type: "provider",
|
|
109
|
+
params: [],
|
|
110
|
+
usedReferences: new Set(),
|
|
68
111
|
};
|
|
112
|
+
|
|
69
113
|
const docComment = findDocComment(nodePath, source);
|
|
70
114
|
if (docComment) {
|
|
71
115
|
manifest.description = docComment.description;
|
|
72
116
|
manifest.deprecated = getDeprecatedInfo(docComment.tags);
|
|
73
117
|
}
|
|
118
|
+
|
|
119
|
+
const fn = /** @type {import("@babel/types").FunctionDeclaration} */ (
|
|
120
|
+
nodePath.node
|
|
121
|
+
);
|
|
122
|
+
let index = 0;
|
|
123
|
+
for (const param of fn.params) {
|
|
124
|
+
const annotation = getTypeAnnotation(
|
|
125
|
+
param.typeAnnotation,
|
|
126
|
+
source,
|
|
127
|
+
manifest.usedReferences
|
|
128
|
+
);
|
|
129
|
+
if (param.type === "Identifier") {
|
|
130
|
+
manifest.params.push({
|
|
131
|
+
name: param.name,
|
|
132
|
+
description: docComment?.tags.find(
|
|
133
|
+
(tag) => tag.title === "param" && tag.name === param.name
|
|
134
|
+
)?.description,
|
|
135
|
+
annotation,
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
const paramTag = docComment?.tags.filter(
|
|
139
|
+
(tag) => tag.title === "param"
|
|
140
|
+
)?.[index];
|
|
141
|
+
manifest.params.push({
|
|
142
|
+
name: paramTag?.name ?? `param_${index + 1}`,
|
|
143
|
+
description: paramTag?.description,
|
|
144
|
+
isRestElement: param.type === "RestElement",
|
|
145
|
+
annotation,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
index++;
|
|
149
|
+
}
|
|
150
|
+
const returnAnnotation = getTypeAnnotation(
|
|
151
|
+
fn.returnType,
|
|
152
|
+
source,
|
|
153
|
+
manifest.usedReferences
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
manifest.returns = {
|
|
157
|
+
description: docComment?.tags.find((tag) => tag.title === "returns")
|
|
158
|
+
?.description,
|
|
159
|
+
annotation: returnAnnotation,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
manifest.typeParameters = getTypeAnnotation(
|
|
163
|
+
fn.typeParameters,
|
|
164
|
+
source,
|
|
165
|
+
manifest.usedReferences
|
|
166
|
+
);
|
|
167
|
+
|
|
74
168
|
return manifest;
|
|
75
169
|
}
|
|
76
170
|
|
|
@@ -91,11 +185,14 @@ function findDocComment({ node, parentPath }, source) {
|
|
|
91
185
|
}
|
|
92
186
|
|
|
93
187
|
/**
|
|
94
|
-
* @param {
|
|
188
|
+
* @param {BrickManifestAndTypes} manifest
|
|
95
189
|
* @param {Node[]} nodes
|
|
96
190
|
* @param {string} source
|
|
191
|
+
* @returns {Set<string>}
|
|
97
192
|
*/
|
|
98
193
|
function scanFields(manifest, nodes, source) {
|
|
194
|
+
/** @type {Set<string>} */
|
|
195
|
+
const usedReferences = new Set();
|
|
99
196
|
for (const node of nodes) {
|
|
100
197
|
if (node.type === "ClassAccessorProperty" && node.decorators?.length) {
|
|
101
198
|
for (const { expression } of node.decorators) {
|
|
@@ -107,7 +204,7 @@ function scanFields(manifest, nodes, source) {
|
|
|
107
204
|
case "property": {
|
|
108
205
|
/** @type {PropertyManifest} */
|
|
109
206
|
const prop = {
|
|
110
|
-
name: node.key.name,
|
|
207
|
+
name: /** @type {Identifier} */ (node.key).name,
|
|
111
208
|
};
|
|
112
209
|
const docComment = parseDocComment(node, source);
|
|
113
210
|
if (docComment) {
|
|
@@ -145,6 +242,18 @@ function scanFields(manifest, nodes, source) {
|
|
|
145
242
|
) {
|
|
146
243
|
const { typeAnnotation } = node.typeAnnotation;
|
|
147
244
|
prop.type = getTypeWithoutUndefined(typeAnnotation, source);
|
|
245
|
+
|
|
246
|
+
const annotation = getTypeAnnotation(
|
|
247
|
+
getNodeWithoutUndefined(typeAnnotation),
|
|
248
|
+
source,
|
|
249
|
+
usedReferences
|
|
250
|
+
);
|
|
251
|
+
if (annotation) {
|
|
252
|
+
manifest.types.properties.push({
|
|
253
|
+
name: prop.name,
|
|
254
|
+
annotation,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
148
257
|
}
|
|
149
258
|
if (node.value && !prop.default) {
|
|
150
259
|
prop.default = source.substring(
|
|
@@ -158,7 +267,7 @@ function scanFields(manifest, nodes, source) {
|
|
|
158
267
|
|
|
159
268
|
case "event": {
|
|
160
269
|
/** @type {EventManifest} */
|
|
161
|
-
const event = {};
|
|
270
|
+
const event = { name: undefined };
|
|
162
271
|
|
|
163
272
|
// Find out the `type` option for the event.
|
|
164
273
|
if (expression.arguments.length > 0) {
|
|
@@ -181,7 +290,9 @@ function scanFields(manifest, nodes, source) {
|
|
|
181
290
|
}
|
|
182
291
|
if (event.name === undefined) {
|
|
183
292
|
throw new Error(
|
|
184
|
-
`Invalid @event() call: no literal type option in event '${
|
|
293
|
+
`Invalid @event() call: no literal type option in event '${
|
|
294
|
+
/** @type {Identifier} */ (node.key).name
|
|
295
|
+
}'`
|
|
185
296
|
);
|
|
186
297
|
}
|
|
187
298
|
const docComment = parseDocComment(node, source);
|
|
@@ -209,6 +320,21 @@ function scanFields(manifest, nodes, source) {
|
|
|
209
320
|
const param = typeAnnotation.typeParameters.params[0];
|
|
210
321
|
event.detail ??= {};
|
|
211
322
|
event.detail.type = source.substring(param.start, param.end);
|
|
323
|
+
|
|
324
|
+
const annotation = getTypeAnnotation(
|
|
325
|
+
param,
|
|
326
|
+
source,
|
|
327
|
+
usedReferences
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
if (annotation) {
|
|
331
|
+
manifest.types.events.push({
|
|
332
|
+
name: event.name,
|
|
333
|
+
detail: {
|
|
334
|
+
annotation,
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
}
|
|
212
338
|
}
|
|
213
339
|
}
|
|
214
340
|
manifest.events.push(event);
|
|
@@ -226,34 +352,99 @@ function scanFields(manifest, nodes, source) {
|
|
|
226
352
|
) {
|
|
227
353
|
/** @type {MethodManifest} */
|
|
228
354
|
const method = {
|
|
229
|
-
name: node.key.name,
|
|
355
|
+
name: /** @type {Identifier} */ (node.key).name,
|
|
230
356
|
params: [],
|
|
231
357
|
};
|
|
232
358
|
const docComment = parseDocComment(node, source);
|
|
233
359
|
if (docComment) {
|
|
234
360
|
method.description = docComment.description;
|
|
235
361
|
method.deprecated = getDeprecatedInfo(docComment.tags);
|
|
362
|
+
method.returns = {
|
|
363
|
+
description: docComment.tags.find(
|
|
364
|
+
(tag) => tag.title === "returns"
|
|
365
|
+
)?.description,
|
|
366
|
+
};
|
|
236
367
|
}
|
|
368
|
+
|
|
369
|
+
let index = 0;
|
|
370
|
+
/** @type {BrickMethodParamWithAnnotation[]} */
|
|
371
|
+
const typedParams = [];
|
|
237
372
|
for (const param of node.params) {
|
|
238
|
-
|
|
373
|
+
const typeAnnotation =
|
|
374
|
+
/** @type {Identifier} */
|
|
375
|
+
(param).typeAnnotation;
|
|
376
|
+
const annotation = getTypeAnnotation(
|
|
377
|
+
typeAnnotation,
|
|
378
|
+
source,
|
|
379
|
+
usedReferences
|
|
380
|
+
);
|
|
381
|
+
const paramType =
|
|
382
|
+
typeAnnotation.type === "TSTypeAnnotation"
|
|
383
|
+
? source.substring(
|
|
384
|
+
typeAnnotation.typeAnnotation.start,
|
|
385
|
+
typeAnnotation.typeAnnotation.end
|
|
386
|
+
)
|
|
387
|
+
: undefined;
|
|
388
|
+
/** @type {string} */
|
|
389
|
+
let paramName;
|
|
390
|
+
if (param.type === "Identifier") {
|
|
391
|
+
paramName = param.name;
|
|
392
|
+
method.params.push({
|
|
393
|
+
name: paramName,
|
|
394
|
+
description: docComment?.tags.find(
|
|
395
|
+
(tag) => tag.title === "param" && tag.name === param.name
|
|
396
|
+
)?.description,
|
|
397
|
+
type: paramType,
|
|
398
|
+
});
|
|
399
|
+
} else {
|
|
400
|
+
const paramTag = docComment?.tags.filter(
|
|
401
|
+
(tag) => tag.title === "param"
|
|
402
|
+
)?.[index];
|
|
403
|
+
paramName = paramTag?.name ?? `param_${index + 1}`;
|
|
404
|
+
method.params.push({
|
|
405
|
+
name: paramName,
|
|
406
|
+
description: paramTag?.description,
|
|
407
|
+
type: paramType,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
typedParams.push({
|
|
411
|
+
name: paramName,
|
|
412
|
+
annotation,
|
|
413
|
+
});
|
|
414
|
+
index++;
|
|
239
415
|
}
|
|
416
|
+
|
|
417
|
+
/** @type {{ annotation?: Annotation }} */
|
|
418
|
+
const typedReturns = {};
|
|
240
419
|
if (node.returnType && node.returnType.type === "TSTypeAnnotation") {
|
|
241
420
|
const { typeAnnotation } = node.returnType;
|
|
242
|
-
method.
|
|
243
|
-
|
|
244
|
-
typeAnnotation.start,
|
|
245
|
-
|
|
421
|
+
method.returns = {
|
|
422
|
+
...method.returns,
|
|
423
|
+
type: source.substring(typeAnnotation.start, typeAnnotation.end),
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
typedReturns.annotation = getTypeAnnotation(
|
|
427
|
+
typeAnnotation,
|
|
428
|
+
source,
|
|
429
|
+
usedReferences
|
|
246
430
|
);
|
|
247
431
|
}
|
|
432
|
+
manifest.types.methods.push({
|
|
433
|
+
name: method.name,
|
|
434
|
+
params: typedParams,
|
|
435
|
+
returns: typedReturns,
|
|
436
|
+
});
|
|
248
437
|
manifest.methods.push(method);
|
|
249
438
|
}
|
|
250
439
|
}
|
|
251
440
|
}
|
|
252
441
|
}
|
|
442
|
+
|
|
443
|
+
return usedReferences;
|
|
253
444
|
}
|
|
254
445
|
|
|
255
446
|
/**
|
|
256
|
-
* @param {Node
|
|
447
|
+
* @param {Node} node
|
|
257
448
|
* @param {string} source
|
|
258
449
|
*/
|
|
259
450
|
export function parseDocComment(node, source) {
|
|
@@ -269,6 +460,21 @@ export function parseDocComment(node, source) {
|
|
|
269
460
|
}
|
|
270
461
|
}
|
|
271
462
|
|
|
463
|
+
/**
|
|
464
|
+
* @param {Node} node
|
|
465
|
+
* @param {string} source
|
|
466
|
+
* @returns {undefined | { description?: string; deprecated?: boolean | string; }}
|
|
467
|
+
*/
|
|
468
|
+
export function parseTypeComment(node, source) {
|
|
469
|
+
const docComment = parseDocComment(node, source);
|
|
470
|
+
if (docComment) {
|
|
471
|
+
return {
|
|
472
|
+
description: docComment.description,
|
|
473
|
+
deprecated: getDeprecatedInfo(docComment.tags),
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
272
478
|
/**
|
|
273
479
|
* @param {Node} node
|
|
274
480
|
* @param {string} source
|
|
@@ -287,6 +493,28 @@ function getTypeWithoutUndefined(node, source) {
|
|
|
287
493
|
return source.substring(node.start, node.end);
|
|
288
494
|
}
|
|
289
495
|
|
|
496
|
+
/**
|
|
497
|
+
* @param {Node} node
|
|
498
|
+
* @returns {Node}
|
|
499
|
+
*/
|
|
500
|
+
function getNodeWithoutUndefined(node) {
|
|
501
|
+
if (node.type === "TSUnionType") {
|
|
502
|
+
const filteredTypes = node.types.filter(
|
|
503
|
+
(type) => type.type !== "TSUndefinedKeyword"
|
|
504
|
+
);
|
|
505
|
+
if (filteredTypes.length < node.types.length) {
|
|
506
|
+
if (filteredTypes.length === 1) {
|
|
507
|
+
return filteredTypes[0];
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
...node,
|
|
511
|
+
types: filteredTypes,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return node;
|
|
516
|
+
}
|
|
517
|
+
|
|
290
518
|
/**
|
|
291
519
|
* @param {Tag[]} tags
|
|
292
520
|
* @param {string} title
|
package/src/scanBricks.js
CHANGED
|
@@ -8,17 +8,22 @@ import getCamelPackageName from "./getCamelPackageName.js";
|
|
|
8
8
|
import makeBrickManifest, {
|
|
9
9
|
makeProviderManifest,
|
|
10
10
|
} from "./makeBrickManifest.js";
|
|
11
|
-
import { BASE_TYPE, TS_KEYWORD_LIST, getTypeAnnotation } from "./utils.js";
|
|
12
11
|
import {
|
|
13
12
|
isImportDefaultSpecifier,
|
|
14
13
|
isImportDeclaration,
|
|
15
14
|
isImportSpecifier,
|
|
16
15
|
} from "@babel/types";
|
|
16
|
+
import getTypeDeclaration from "./getTypeDeclaration.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import("@babel/traverse").NodePath} NodePath
|
|
19
21
|
* @typedef {import("@next-core/brick-manifest").PackageManifest} PackageManifest
|
|
22
|
+
* @typedef {import("@next-core/brick-manifest").ProviderManifest} ProviderManifest
|
|
23
|
+
* @typedef {import("@next-core/brick-manifest").Declaration} Declaration
|
|
20
24
|
* @typedef {{import: string; name: string; noNamespace?: boolean;}} Expose
|
|
21
25
|
* @typedef {Record<string, Expose>} Exposes
|
|
26
|
+
* @typedef {import("./makeBrickManifest.js").BrickManifestAndTypes} BrickManifestAndTypes
|
|
22
27
|
*/
|
|
23
28
|
|
|
24
29
|
const { default: traverse } = babelTraverse;
|
|
@@ -71,10 +76,14 @@ export default async function scanBricks(packageDir) {
|
|
|
71
76
|
/** @type {Map<string, Set<string>} */
|
|
72
77
|
const importsMap = new Map();
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
/** @type {{ filePath: string; declaration: Declaration; usedReferences: Set<string> }[]} */
|
|
80
|
+
const typeDeclarations = [];
|
|
75
81
|
|
|
76
82
|
const bricksImportsInfo = {};
|
|
77
83
|
|
|
84
|
+
/** @type {ProviderManifest[]} */
|
|
85
|
+
const providerTypes = [];
|
|
86
|
+
|
|
78
87
|
/**
|
|
79
88
|
*
|
|
80
89
|
* @param {string} filePath
|
|
@@ -93,7 +102,12 @@ export default async function scanBricks(packageDir) {
|
|
|
93
102
|
const extname = path.extname(filePath);
|
|
94
103
|
const content = await readFile(filePath, "utf-8");
|
|
95
104
|
|
|
96
|
-
|
|
105
|
+
// Record top level functions for providers
|
|
106
|
+
/** @type {Map<string, NodePath} */
|
|
107
|
+
const topLevelFunctions = new Map();
|
|
108
|
+
/** @type {Map<string, string>} */
|
|
109
|
+
const providerMap = new Map();
|
|
110
|
+
|
|
97
111
|
/** @type {string} */
|
|
98
112
|
let brickFullName;
|
|
99
113
|
/** @type {ReturnType<typeof import("@babel/parser").parse>} */
|
|
@@ -268,12 +282,20 @@ export default async function scanBricks(packageDir) {
|
|
|
268
282
|
callee.property.name === "define" &&
|
|
269
283
|
args.length === 2
|
|
270
284
|
) {
|
|
271
|
-
const { type, value: fullName } = args
|
|
285
|
+
const [{ type, value: fullName }, constructor] = args;
|
|
272
286
|
if (type === "StringLiteral") {
|
|
273
287
|
collectBrick(fullName);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
288
|
+
if (
|
|
289
|
+
constructor.type === "CallExpression" &&
|
|
290
|
+
constructor.callee.type === "Identifier" &&
|
|
291
|
+
constructor.callee.name === "createProviderClass" &&
|
|
292
|
+
constructor.arguments.length > 0 &&
|
|
293
|
+
constructor.arguments[0].type === "Identifier"
|
|
294
|
+
) {
|
|
295
|
+
providerMap.set(fullName, constructor.arguments[0].name);
|
|
296
|
+
} else {
|
|
297
|
+
manifest.providers.push({ name: fullName });
|
|
298
|
+
}
|
|
277
299
|
} else {
|
|
278
300
|
throw new Error(
|
|
279
301
|
"Please call `customElements.define()` only with literal string"
|
|
@@ -425,6 +447,17 @@ export default async function scanBricks(packageDir) {
|
|
|
425
447
|
});
|
|
426
448
|
}
|
|
427
449
|
},
|
|
450
|
+
FunctionDeclaration(nodePath) {
|
|
451
|
+
const { node, parent } = nodePath;
|
|
452
|
+
if (
|
|
453
|
+
node.id &&
|
|
454
|
+
(parent.type === "Program" ||
|
|
455
|
+
parent.type === "ExportNamedDeclaration" ||
|
|
456
|
+
parent.type === "ExportDefaultDeclaration")
|
|
457
|
+
) {
|
|
458
|
+
topLevelFunctions.set(node.id.name, nodePath);
|
|
459
|
+
}
|
|
460
|
+
},
|
|
428
461
|
ImportDeclaration({ node: { source, importKind } }) {
|
|
429
462
|
// Match `import "..."`
|
|
430
463
|
if (
|
|
@@ -458,22 +491,27 @@ export default async function scanBricks(packageDir) {
|
|
|
458
491
|
}
|
|
459
492
|
},
|
|
460
493
|
TSInterfaceDeclaration({ node }) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
...(getTypeAnnotation(node, content) || {}),
|
|
494
|
+
const usedReferences = new Set();
|
|
495
|
+
typeDeclarations.push({
|
|
464
496
|
filePath,
|
|
497
|
+
declaration: getTypeDeclaration(node, content, usedReferences),
|
|
498
|
+
usedReferences,
|
|
465
499
|
});
|
|
466
500
|
},
|
|
467
501
|
TSTypeAliasDeclaration({ node }) {
|
|
468
|
-
|
|
469
|
-
|
|
502
|
+
const usedReferences = new Set();
|
|
503
|
+
typeDeclarations.push({
|
|
470
504
|
filePath,
|
|
505
|
+
declaration: getTypeDeclaration(node, content, usedReferences),
|
|
506
|
+
usedReferences,
|
|
471
507
|
});
|
|
472
508
|
},
|
|
473
509
|
TSEnumDeclaration: ({ node }) => {
|
|
474
|
-
|
|
475
|
-
|
|
510
|
+
const usedReferences = new Set();
|
|
511
|
+
typeDeclarations.push({
|
|
476
512
|
filePath,
|
|
513
|
+
declaration: getTypeDeclaration(node, content, usedReferences),
|
|
514
|
+
usedReferences,
|
|
477
515
|
});
|
|
478
516
|
},
|
|
479
517
|
});
|
|
@@ -484,7 +522,7 @@ export default async function scanBricks(packageDir) {
|
|
|
484
522
|
)
|
|
485
523
|
);
|
|
486
524
|
|
|
487
|
-
if (brickFullName) {
|
|
525
|
+
if (brickFullName || providerMap.size > 0) {
|
|
488
526
|
const imports = ast.program.body
|
|
489
527
|
.map((item) => {
|
|
490
528
|
if (isImportDeclaration(item)) {
|
|
@@ -515,10 +553,36 @@ export default async function scanBricks(packageDir) {
|
|
|
515
553
|
})
|
|
516
554
|
.filter(Boolean);
|
|
517
555
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
556
|
+
if (brickFullName) {
|
|
557
|
+
bricksImportsInfo[brickFullName] = {
|
|
558
|
+
imports,
|
|
559
|
+
filePath,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
for (const providerName of providerMap.keys()) {
|
|
563
|
+
bricksImportsInfo[providerName] = {
|
|
564
|
+
imports,
|
|
565
|
+
filePath,
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (providerMap.size > 0) {
|
|
571
|
+
for (const [providerName, providerConstructor] of providerMap) {
|
|
572
|
+
const nodePath = topLevelFunctions.get(providerConstructor);
|
|
573
|
+
if (nodePath) {
|
|
574
|
+
const { description, deprecated, ...restTypes } =
|
|
575
|
+
makeProviderManifest(providerName, nodePath, content);
|
|
576
|
+
providerTypes.push(restTypes);
|
|
577
|
+
manifest.providers.push({
|
|
578
|
+
name: providerName,
|
|
579
|
+
description,
|
|
580
|
+
deprecated,
|
|
581
|
+
});
|
|
582
|
+
} else {
|
|
583
|
+
manifest.providers.push({ name: providerName });
|
|
584
|
+
}
|
|
585
|
+
}
|
|
522
586
|
}
|
|
523
587
|
}
|
|
524
588
|
|
|
@@ -618,9 +682,6 @@ export default async function scanBricks(packageDir) {
|
|
|
618
682
|
if (analyzedFiles.has(filePath)) {
|
|
619
683
|
return;
|
|
620
684
|
}
|
|
621
|
-
if (brickName === "button-with-icon") {
|
|
622
|
-
console.log("scan:", filePath);
|
|
623
|
-
}
|
|
624
685
|
analyzedFiles.add(filePath);
|
|
625
686
|
for (const dep of usingWrappedBricks.get(filePath) ?? []) {
|
|
626
687
|
// Do not dependent on itself
|
|
@@ -638,9 +699,6 @@ export default async function scanBricks(packageDir) {
|
|
|
638
699
|
}
|
|
639
700
|
}
|
|
640
701
|
|
|
641
|
-
function ingoreField(obj) {
|
|
642
|
-
return _.omit(obj, ["filePath", "reference"]);
|
|
643
|
-
}
|
|
644
702
|
function isMatch(importPath, filePath) {
|
|
645
703
|
return (
|
|
646
704
|
importPath.replace(/\.[^.]+$/, "") === filePath.replace(/\.[^.]+$/, "")
|
|
@@ -649,11 +707,11 @@ export default async function scanBricks(packageDir) {
|
|
|
649
707
|
|
|
650
708
|
/**
|
|
651
709
|
*
|
|
652
|
-
* @param {string}
|
|
710
|
+
* @param {string} name
|
|
653
711
|
* @param {Record<string, unknown} importInfo
|
|
654
712
|
* @param {Set<string>} importKeysSet
|
|
655
713
|
* @param {string} realFilePath
|
|
656
|
-
* @returns void
|
|
714
|
+
* @returns {void}
|
|
657
715
|
*/
|
|
658
716
|
function findType(name, importInfo, importKeysSet, realFilePath = "") {
|
|
659
717
|
if (importKeysSet.has(name)) return;
|
|
@@ -667,60 +725,43 @@ export default async function scanBricks(packageDir) {
|
|
|
667
725
|
? importItem.path
|
|
668
726
|
: filePath;
|
|
669
727
|
|
|
670
|
-
const
|
|
671
|
-
(
|
|
672
|
-
|
|
728
|
+
const { declaration, usedReferences } =
|
|
729
|
+
typeDeclarations.find(
|
|
730
|
+
(item) =>
|
|
731
|
+
isMatch(item.filePath, importPath) && item.declaration.name === name
|
|
732
|
+
) ?? {};
|
|
673
733
|
|
|
674
|
-
if (
|
|
675
|
-
importInfo.types = (importInfo.types || []).concat(
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
interfaceItem.extends,
|
|
680
|
-
importInfo,
|
|
681
|
-
importKeysSet,
|
|
682
|
-
importPath
|
|
683
|
-
);
|
|
684
|
-
findRefrenceItem(
|
|
685
|
-
interfaceItem.reference,
|
|
686
|
-
importInfo,
|
|
687
|
-
importKeysSet,
|
|
688
|
-
importPath
|
|
689
|
-
);
|
|
734
|
+
if (declaration) {
|
|
735
|
+
importInfo.types = (importInfo.types || []).concat(declaration);
|
|
736
|
+
for (const ref of usedReferences) {
|
|
737
|
+
findType(ref, importInfo, importKeysSet, importPath);
|
|
738
|
+
}
|
|
690
739
|
}
|
|
691
740
|
}
|
|
692
741
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
742
|
+
manifest.bricks.forEach((/** @type {BrickManifestAndTypes} */ brickDoc) => {
|
|
743
|
+
const {
|
|
744
|
+
name,
|
|
745
|
+
types: { usedReferences, ...types },
|
|
746
|
+
} = brickDoc;
|
|
747
|
+
const importInfo = bricksImportsInfo[name];
|
|
748
|
+
Object.assign(importInfo, types);
|
|
749
|
+
|
|
750
|
+
const importKeysSet = new Set();
|
|
751
|
+
for (const ref of usedReferences) {
|
|
752
|
+
findType(ref, importInfo, importKeysSet);
|
|
698
753
|
}
|
|
699
|
-
|
|
754
|
+
delete brickDoc.types;
|
|
755
|
+
});
|
|
700
756
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const { name, properties } = brickDoc;
|
|
704
|
-
const importInfo = bricksImportsInfo[name];
|
|
705
|
-
const fieldTypes = properties
|
|
706
|
-
.map(
|
|
707
|
-
({ type }) =>
|
|
708
|
-
type &&
|
|
709
|
-
type
|
|
710
|
-
.match(/\w+/g)
|
|
711
|
-
.filter(
|
|
712
|
-
(item) => !(BASE_TYPE[item] || TS_KEYWORD_LIST.includes(item))
|
|
713
|
-
)
|
|
714
|
-
)
|
|
715
|
-
.flat(1);
|
|
757
|
+
for (const providerDoc of providerTypes) {
|
|
758
|
+
const importInfo = bricksImportsInfo[providerDoc.name];
|
|
716
759
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
});
|
|
760
|
+
const importKeysSet = new Set();
|
|
761
|
+
for (const ref of providerDoc.usedReferences) {
|
|
762
|
+
findType(ref, importInfo, importKeysSet);
|
|
763
|
+
}
|
|
764
|
+
delete providerDoc.usedReferences;
|
|
724
765
|
}
|
|
725
766
|
|
|
726
767
|
// console.log("exposes:", exposes);
|
|
@@ -733,9 +774,27 @@ export default async function scanBricks(packageDir) {
|
|
|
733
774
|
},
|
|
734
775
|
manifest,
|
|
735
776
|
types: Object.fromEntries(
|
|
736
|
-
Object.entries(bricksImportsInfo)
|
|
737
|
-
|
|
738
|
-
|
|
777
|
+
Object.entries(bricksImportsInfo)
|
|
778
|
+
.map(([k, v]) => {
|
|
779
|
+
return [
|
|
780
|
+
k,
|
|
781
|
+
{
|
|
782
|
+
properties: v.properties,
|
|
783
|
+
events: v.events,
|
|
784
|
+
methods: v.methods,
|
|
785
|
+
types: v.types,
|
|
786
|
+
},
|
|
787
|
+
];
|
|
788
|
+
})
|
|
789
|
+
.concat(
|
|
790
|
+
providerTypes.map(({ name, ...types }) => [
|
|
791
|
+
name,
|
|
792
|
+
{
|
|
793
|
+
...types,
|
|
794
|
+
types: bricksImportsInfo[name]?.types,
|
|
795
|
+
},
|
|
796
|
+
])
|
|
797
|
+
)
|
|
739
798
|
),
|
|
740
799
|
};
|
|
741
800
|
}
|
package/src/utils.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isIdentifier,
|
|
3
|
-
isStringLiteral,
|
|
4
|
-
isTSArrayType,
|
|
5
|
-
isTSEnumDeclaration,
|
|
6
|
-
isTSEnumMember,
|
|
7
|
-
isTSIndexSignature,
|
|
8
|
-
isTSIndexedAccessType,
|
|
9
|
-
isTSInterfaceDeclaration,
|
|
10
|
-
isTSIntersectionType,
|
|
11
|
-
isTSLiteralType,
|
|
12
|
-
isTSPropertySignature,
|
|
13
|
-
isTSQualifiedName,
|
|
14
|
-
isTSTupleType,
|
|
15
|
-
isTSTypeAliasDeclaration,
|
|
16
|
-
isTSTypeAnnotation,
|
|
17
|
-
isTSTypeLiteral,
|
|
18
|
-
isTSTypeParameter,
|
|
19
|
-
isTSTypeParameterDeclaration,
|
|
20
|
-
isTSTypeReference,
|
|
21
|
-
isTSUnionType,
|
|
22
|
-
} from "@babel/types";
|
|
23
|
-
import _ from "lodash";
|
|
24
|
-
import { parseDocComment } from "./makeBrickManifest.js";
|
|
25
|
-
|
|
26
|
-
export const BASE_TYPE = {
|
|
27
|
-
any: "any",
|
|
28
|
-
boolean: "boolean",
|
|
29
|
-
undefined: "undefined",
|
|
30
|
-
bigint: "bigint",
|
|
31
|
-
null: "null",
|
|
32
|
-
number: "number",
|
|
33
|
-
object: "object",
|
|
34
|
-
string: "string",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const TS_KEYWORD_LIST = ["Record", "Array", "unknow", "void"];
|
|
38
|
-
const TS_BASIC_TYPE = {
|
|
39
|
-
TSAnyKeyword: BASE_TYPE.any,
|
|
40
|
-
TSBooleanKeyword: BASE_TYPE.boolean,
|
|
41
|
-
TSBigIntKeyword: BASE_TYPE.bigint,
|
|
42
|
-
TSNullKeyword: BASE_TYPE.null,
|
|
43
|
-
TSNumberKeyword: BASE_TYPE.number,
|
|
44
|
-
TSObjectKeyword: BASE_TYPE.object,
|
|
45
|
-
TSStringKeyword: BASE_TYPE.string,
|
|
46
|
-
TSUndefinedKeyword: BASE_TYPE.undefined,
|
|
47
|
-
TSUnknownKeyword: BASE_TYPE.any,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
function getTSBasicType(annotation) {
|
|
51
|
-
return annotation && TS_BASIC_TYPE[annotation.type];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const getDocComment = (typeAnnotation, source) => {
|
|
55
|
-
return parseDocComment(typeAnnotation, source) || {};
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
* @param {import("@babel/types").typeAnnotation} typeAnnotation
|
|
61
|
-
* @param {string} source
|
|
62
|
-
* @param {Set<string>} reference
|
|
63
|
-
* @returns
|
|
64
|
-
*/
|
|
65
|
-
export const getTypeAnnotation = (
|
|
66
|
-
typeAnnotation,
|
|
67
|
-
source,
|
|
68
|
-
reference = new Set()
|
|
69
|
-
) => {
|
|
70
|
-
const makeResultWithDocComment = (result) => {
|
|
71
|
-
return {
|
|
72
|
-
...result,
|
|
73
|
-
...getDocComment(typeAnnotation, source),
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* @param {import("@babel/types").typeAnnotation} typeAnnotation
|
|
78
|
-
*/
|
|
79
|
-
const walkTypeAnnotation = (typeAnnotation) => {
|
|
80
|
-
if (isTSInterfaceDeclaration(typeAnnotation)) {
|
|
81
|
-
const {
|
|
82
|
-
id,
|
|
83
|
-
body,
|
|
84
|
-
extends: extendsItems,
|
|
85
|
-
typeParameters,
|
|
86
|
-
} = typeAnnotation;
|
|
87
|
-
if (!id) return;
|
|
88
|
-
return makeResultWithDocComment({
|
|
89
|
-
name: id.name,
|
|
90
|
-
type: "interface",
|
|
91
|
-
typeParameters: typeParameters && walkTypeAnnotation(typeParameters),
|
|
92
|
-
annotation: body.body.map(walkTypeAnnotation),
|
|
93
|
-
extends: extendsItems?.map((item) => item.expression.name),
|
|
94
|
-
reference: [...reference],
|
|
95
|
-
});
|
|
96
|
-
} else if (isTSTypeAliasDeclaration(typeAnnotation)) {
|
|
97
|
-
const { id, typeParameters } = typeAnnotation;
|
|
98
|
-
return makeResultWithDocComment({
|
|
99
|
-
name: id.name,
|
|
100
|
-
type: "typeAlias",
|
|
101
|
-
typeParameters: typeParameters && walkTypeAnnotation(typeParameters),
|
|
102
|
-
annotation: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
103
|
-
reference: [...reference],
|
|
104
|
-
});
|
|
105
|
-
} else if (isTSEnumDeclaration(typeAnnotation)) {
|
|
106
|
-
const { id, members } = typeAnnotation;
|
|
107
|
-
return makeResultWithDocComment({
|
|
108
|
-
name: id.name,
|
|
109
|
-
type: "enums",
|
|
110
|
-
members: members?.map(walkTypeAnnotation),
|
|
111
|
-
reference: [...reference],
|
|
112
|
-
});
|
|
113
|
-
} else if (isTSEnumMember(typeAnnotation)) {
|
|
114
|
-
return {
|
|
115
|
-
name: walkTypeAnnotation(typeAnnotation.id),
|
|
116
|
-
value: walkTypeAnnotation(typeAnnotation.initializer),
|
|
117
|
-
};
|
|
118
|
-
} else if (isTSTypeAnnotation(typeAnnotation)) {
|
|
119
|
-
return walkTypeAnnotation(typeAnnotation.typeAnnotation);
|
|
120
|
-
} else if (isTSTypeReference(typeAnnotation)) {
|
|
121
|
-
const { typeName, typeParameters } = typeAnnotation;
|
|
122
|
-
const qualified = isTSQualifiedName(typeName)
|
|
123
|
-
? walkTypeAnnotation(typeName)
|
|
124
|
-
: undefined;
|
|
125
|
-
const name = typeName.name;
|
|
126
|
-
reference.add(name);
|
|
127
|
-
const params =
|
|
128
|
-
typeParameters?.params && typeParameters.params.map(walkTypeAnnotation);
|
|
129
|
-
return makeResultWithDocComment({
|
|
130
|
-
type: "reference",
|
|
131
|
-
typeName: name,
|
|
132
|
-
typeParameters: params,
|
|
133
|
-
qualified,
|
|
134
|
-
});
|
|
135
|
-
} else if (isTSQualifiedName(typeAnnotation)) {
|
|
136
|
-
const left = walkTypeAnnotation(typeAnnotation.left);
|
|
137
|
-
if (typeof left === "string") {
|
|
138
|
-
reference.add(left);
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
type: "qualifiedName",
|
|
142
|
-
left: left,
|
|
143
|
-
right: walkTypeAnnotation(typeAnnotation.right),
|
|
144
|
-
};
|
|
145
|
-
} else if (isTSUnionType(typeAnnotation)) {
|
|
146
|
-
return makeResultWithDocComment({
|
|
147
|
-
type: "union",
|
|
148
|
-
types: typeAnnotation.types.map(walkTypeAnnotation),
|
|
149
|
-
});
|
|
150
|
-
} else if (isTSArrayType(typeAnnotation)) {
|
|
151
|
-
return makeResultWithDocComment({
|
|
152
|
-
type: "array",
|
|
153
|
-
elementType: walkTypeAnnotation(typeAnnotation.elementType),
|
|
154
|
-
});
|
|
155
|
-
} else if (isTSTupleType(typeAnnotation)) {
|
|
156
|
-
return makeResultWithDocComment({
|
|
157
|
-
type: "tuple",
|
|
158
|
-
elementTypes: typeAnnotation.elementTypes.map(walkTypeAnnotation),
|
|
159
|
-
});
|
|
160
|
-
} else if (isTSIntersectionType(typeAnnotation)) {
|
|
161
|
-
return makeResultWithDocComment({
|
|
162
|
-
type: "intersection",
|
|
163
|
-
types: typeAnnotation.types.map(walkTypeAnnotation),
|
|
164
|
-
});
|
|
165
|
-
} else if (isTSTypeLiteral(typeAnnotation)) {
|
|
166
|
-
return makeResultWithDocComment({
|
|
167
|
-
type: "typeLiteral",
|
|
168
|
-
members: typeAnnotation.members.map(walkTypeAnnotation),
|
|
169
|
-
});
|
|
170
|
-
} else if (isTSPropertySignature(typeAnnotation)) {
|
|
171
|
-
return makeResultWithDocComment({
|
|
172
|
-
type: "propertySignature",
|
|
173
|
-
name: typeAnnotation.key.name,
|
|
174
|
-
property: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
175
|
-
});
|
|
176
|
-
} else if (isTSIndexSignature(typeAnnotation)) {
|
|
177
|
-
return makeResultWithDocComment({
|
|
178
|
-
type: "indexSignature",
|
|
179
|
-
parameters: {
|
|
180
|
-
name: typeAnnotation.parameters[0].name,
|
|
181
|
-
...walkTypeAnnotation(typeAnnotation.parameters[0].typeAnnotation),
|
|
182
|
-
},
|
|
183
|
-
property: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
184
|
-
});
|
|
185
|
-
} else if (isTSIndexedAccessType(typeAnnotation)) {
|
|
186
|
-
return makeResultWithDocComment({
|
|
187
|
-
type: "indexedAccess",
|
|
188
|
-
objectType: walkTypeAnnotation(typeAnnotation.objectType),
|
|
189
|
-
indexType: walkTypeAnnotation(typeAnnotation.indexType),
|
|
190
|
-
});
|
|
191
|
-
} else if (isTSTypeParameterDeclaration(typeAnnotation)) {
|
|
192
|
-
return makeResultWithDocComment({
|
|
193
|
-
type: "typeParameterDeclaration",
|
|
194
|
-
params: typeAnnotation.params.map(walkTypeAnnotation),
|
|
195
|
-
});
|
|
196
|
-
} else if (isTSTypeParameter(typeAnnotation)) {
|
|
197
|
-
return makeResultWithDocComment({
|
|
198
|
-
type: "typeParameter",
|
|
199
|
-
value: typeAnnotation.name,
|
|
200
|
-
default:
|
|
201
|
-
typeAnnotation.default && walkTypeAnnotation(typeAnnotation.default),
|
|
202
|
-
});
|
|
203
|
-
} else if (isTSLiteralType(typeAnnotation)) {
|
|
204
|
-
return makeResultWithDocComment({
|
|
205
|
-
type: "literal",
|
|
206
|
-
value: typeAnnotation.literal.value,
|
|
207
|
-
});
|
|
208
|
-
} else if (isIdentifier(typeAnnotation)) {
|
|
209
|
-
return {
|
|
210
|
-
type: "identifier",
|
|
211
|
-
value: typeAnnotation.name,
|
|
212
|
-
};
|
|
213
|
-
} else if (isStringLiteral(typeAnnotation)) {
|
|
214
|
-
return {
|
|
215
|
-
type: "stringLiteral",
|
|
216
|
-
value: typeAnnotation.value,
|
|
217
|
-
};
|
|
218
|
-
} else if (getTSBasicType(typeAnnotation)) {
|
|
219
|
-
return makeResultWithDocComment({
|
|
220
|
-
type: "keyword",
|
|
221
|
-
value: getTSBasicType(typeAnnotation),
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
return walkTypeAnnotation(typeAnnotation);
|
|
227
|
-
};
|