@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-core/build-next-bricks",
3
- "version": "1.9.0",
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.2.0"
52
+ "@next-core/brick-manifest": "^0.4.0"
53
53
  },
54
- "gitHead": "618559c95f5a1ef0eaf4d2792b530deaf933d45d"
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
+ }
@@ -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 {BrickManifest}
46
+ * @returns {BrickManifestAndTypes}
20
47
  */
21
48
  export default function makeBrickManifest(name, nodePath, source) {
22
- /** @type {import("@babel/traverse").NodePath<ClassDeclaration>} */
23
- const classPath = nodePath.parentPath;
24
- /** @type {BrickManifest} */
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
- scanFields(manifest, classPath.node.body.body, source);
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 {ProviderManifest}
100
+ * @returns {ProviderManifestAndTypes}
63
101
  */
64
102
  export function makeProviderManifest(name, nodePath, source) {
65
- /** @type {ProviderManifest} */
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 {BrickManifest} manifest
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 '${node.key.name}'`
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
- method.params.push(source.substring(param.start, param.end));
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.return ??= {};
243
- method.return.type = source.substring(
244
- typeAnnotation.start,
245
- typeAnnotation.end
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[]} nodes
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
- const typescriptList = [];
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
- /** @type {Record<string, string[]>} */
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[0];
285
+ const [{ type, value: fullName }, constructor] = args;
272
286
  if (type === "StringLiteral") {
273
287
  collectBrick(fullName);
274
- manifest.providers.push(
275
- makeProviderManifest(fullName, nodePath, content)
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
- if (!node.id) return;
462
- typescriptList.push({
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
- typescriptList.push({
469
- ...(getTypeAnnotation(node, content) || {}),
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
- typescriptList.push({
475
- ...(getTypeAnnotation(node, content) || {}),
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
- bricksImportsInfo[brickFullName] = {
519
- imports,
520
- filePath,
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} type
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 interfaceItem = typescriptList.find(
671
- (item) => isMatch(item.filePath, importPath) && item.name === name
672
- );
728
+ const { declaration, usedReferences } =
729
+ typeDeclarations.find(
730
+ (item) =>
731
+ isMatch(item.filePath, importPath) && item.declaration.name === name
732
+ ) ?? {};
673
733
 
674
- if (interfaceItem) {
675
- importInfo.types = (importInfo.types || []).concat(
676
- ingoreField(interfaceItem)
677
- );
678
- findRefrenceItem(
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
- function findRefrenceItem(list, importInfo, importKeySet, realFilePath = "") {
694
- if (Array.isArray(list) && list.length) {
695
- list.forEach((item) =>
696
- findType(item, importInfo, importKeySet, realFilePath)
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
- if (manifest && manifest.bricks.length) {
702
- manifest.bricks.forEach((brickDoc) => {
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
- const importKeysSet = new Set();
718
- if (Array.isArray(fieldTypes) && fieldTypes.length) {
719
- [...new Set(fieldTypes)].forEach((type) =>
720
- findType(type, importInfo, importKeysSet)
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).map(([k, v]) => {
737
- return [k, v.types];
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
- };