@lcap/nasl-language-server-core 4.4.2-rc.5 → 4.5.0-beta.2

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.
Files changed (40) hide show
  1. package/out/checker.d.ts.map +1 -1
  2. package/out/checker.js +29 -15
  3. package/out/checker.js.map +1 -1
  4. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  5. package/out/reference-manager/reference-manager.js +14 -0
  6. package/out/reference-manager/reference-manager.js.map +1 -1
  7. package/out/typer/collectGlobalDefs.d.ts.map +1 -1
  8. package/out/typer/collectGlobalDefs.js +55 -7
  9. package/out/typer/collectGlobalDefs.js.map +1 -1
  10. package/out/typer/component-def-manager/component-def-manager.d.ts +65 -7
  11. package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
  12. package/out/typer/component-def-manager/component-def-manager.js +400 -8
  13. package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
  14. package/out/typer/dispatch-call.d.ts.map +1 -1
  15. package/out/typer/dispatch-call.js +7 -0
  16. package/out/typer/dispatch-call.js.map +1 -1
  17. package/out/typer/dispatch-view.d.ts.map +1 -1
  18. package/out/typer/dispatch-view.js +335 -141
  19. package/out/typer/dispatch-view.js.map +1 -1
  20. package/out/typer/overload-helper.d.ts.map +1 -1
  21. package/out/typer/overload-helper.js +0 -3
  22. package/out/typer/overload-helper.js.map +1 -1
  23. package/out/typer/subster.d.ts.map +1 -1
  24. package/out/typer/subster.js +54 -35
  25. package/out/typer/subster.js.map +1 -1
  26. package/out/typer/type-predicate.d.ts +14 -1
  27. package/out/typer/type-predicate.d.ts.map +1 -1
  28. package/out/typer/type-predicate.js +303 -3
  29. package/out/typer/type-predicate.js.map +1 -1
  30. package/out/typer/typer.d.ts +1 -0
  31. package/out/typer/typer.d.ts.map +1 -1
  32. package/out/typer/typer.js.map +1 -1
  33. package/out/typer/unifier.d.ts +8 -0
  34. package/out/typer/unifier.d.ts.map +1 -1
  35. package/out/typer/unifier.js +32 -0
  36. package/out/typer/unifier.js.map +1 -1
  37. package/out/utils/file-node-cache.d.ts.map +1 -1
  38. package/out/utils/file-node-cache.js +5 -4
  39. package/out/utils/file-node-cache.js.map +1 -1
  40. package/package.json +6 -6
@@ -9,8 +9,20 @@ type NormalizedTag = string & {
9
9
  };
10
10
  export declare function isViewElementDefinition(def: SyntaxNode): def is ViewElementDefinition;
11
11
  export declare function isGeneralViewElementDefinition(def: SyntaxNode): def is GeneralViewElementDefinition;
12
+ export declare class ComponentTagUtils {
13
+ /**
14
+ * 1. 将 kebab-case 转换为 PascalCase
15
+ * 2. 将 PascalCase 转换为 PascalCase
16
+ * 3. 将 camelCase 转换为 PascalCase
17
+ * @param tag
18
+ * @returns
19
+ */
20
+ static normalizeTag(tag: string): NormalizedTag;
21
+ static extractBusinessComponentQNameAsTag(nd: BusinessComponent): NormalizedTag;
22
+ }
12
23
  export declare class ComponentDefManager {
13
24
  private gComponents;
25
+ private typeParamMetaCache;
14
26
  private defToTag;
15
27
  /**
16
28
  * 清空一切组件定义
@@ -60,6 +72,11 @@ export declare class ComponentDefManager {
60
72
  * @returns 属性标题,如果没有则返回属性名本身
61
73
  */
62
74
  getPropTitle(componentTag: string, propName: string): string;
75
+ /**
76
+ * 获取某个组件的 TypeParamMeta 映射(rawName → meta),带懒缓存。
77
+ * 不需要实例化 ViewElementDefinitionHelper,可安全在 checker 中使用。
78
+ */
79
+ getTypeParamMetaMap(componentTag: string): Map<string, TypeParamMeta> | undefined;
63
80
  private queryByNormalizedTag;
64
81
  /**
65
82
  * 根据ViewElement,查询组件的定义(若有多个返回最先注册的一个)
@@ -75,15 +92,36 @@ type RenamedTypeParamWrapper = {
75
92
  rawName: string;
76
93
  renamed: TypeAnnotation;
77
94
  };
95
+ /**
96
+ * 类型变元在组件中的结构性角色,完全通过分析 d.ts 定义的类型结构自动识别,
97
+ * 不依赖类型参数名称(T/V/C/M/P 等)。
98
+ *
99
+ * - dataItem: 出现在 `{ list: List<X>, total: Integer } | List<X>` 模式中,代表行/列表项类型
100
+ * - valueResult: 是某个 `(item: DataItem) => X` 函数属性的返回类型,代表值字段类型
101
+ * - booleanFlag: 在 typeParams 声明中带有 `extends Boolean` 约束,代表布尔开关类型
102
+ */
103
+ export type TypeParamRole = 'dataItem' | 'valueResult' | 'booleanFlag' | 'converterLiteral';
104
+ /**
105
+ * 单个类型变元的兜底策略配置,完全由结构分析自动生成。
106
+ */
107
+ export interface TypeParamMeta {
108
+ role: TypeParamRole;
109
+ /** 该类型参数是否拥有自己的数据源,用于区分"自有数据"和"从祖先继承" */
110
+ hasOwnDataSource: boolean;
111
+ /** 该类型参数对应的数据源属性名(若 hasOwnDataSource 为 true) */
112
+ dataSourcePropName?: string;
113
+ /** 当类型变元在完全求解后仍然 unresolved 时,统一到的默认类型 */
114
+ defaultWhenUnresolved?: TypeAnnotation;
115
+ /** 当某个初始化属性缺省/为空时,根据该属性的值推导出一个默认类型 */
116
+ defaultFromProp?: {
117
+ propName: string;
118
+ mode: 'booleanFlag' | 'converterLiteral' | 'stringLiteral';
119
+ };
120
+ }
78
121
  declare class ViewElementDefinitionHelper {
79
- /**
80
- * 如有必要,重命名了类型变量后的组件定义
81
- */
82
122
  private renamedDef;
83
- /**
84
- * 原始组件定义
85
- */
86
123
  private rawDef;
124
+ private typeParamMetaMap;
87
125
  readonly implicitToStringPropsSet: ReadonlySet<string>;
88
126
  constructor(option: {
89
127
  def: ViewElementDefinition;
@@ -114,6 +152,12 @@ declare class ViewElementDefinitionHelper {
114
152
  * @returns
115
153
  */
116
154
  getInitPropsTypeAnnotation(): TypeAnnotation | undefined;
155
+ /**
156
+ * 根据 slotTarget 获取slot的scope类型
157
+ * @param slotTarget
158
+ * @returns
159
+ */
160
+ getSlotPropBySlotTarget(slotTarget: string): StructureProperty | undefined;
117
161
  /**
118
162
  * 根据 slotTarget 获取slot的参数类型
119
163
  * @param slotTarget
@@ -122,11 +166,25 @@ declare class ViewElementDefinitionHelper {
122
166
  * 1. 返回 非null,表示需要引入current
123
167
  * 2. 返回 null, 表示不需要引入current
124
168
  */
125
- getSlotScopeTypeBySlotTarget(slotTarget: string): [{
169
+ getSlotScopeType(slotProp: StructureProperty): [{
126
170
  name: string;
127
171
  type: TypeAnnotation;
128
172
  }] | null;
129
173
  getRenamedTypeParamWrappers(): RenamedTypeParamWrapper[];
174
+ /**
175
+ * 获取某个原始类型参数名对应的兜底策略配置。
176
+ */
177
+ getTypeParamMeta(rawName: string): TypeParamMeta | undefined;
178
+ /**
179
+ * 基于原始组件定义的类型结构,自动识别每个 typeParam 的角色并生成兜底策略。
180
+ * 完全不依赖 typeParam 的名字(T/V/C/M/P 等),只依赖类型结构模式匹配。
181
+ */
182
+ private buildTypeParamMeta;
130
183
  }
184
+ /**
185
+ * 基于原始组件定义的类型结构,自动识别每个 typeParam 的角色并生成兜底策略。
186
+ * 独立于 ViewElementDefinitionHelper 实例,可在不实例化的场景下使用(如 checker)。
187
+ */
188
+ export declare function buildTypeParamMetaFromRawDef(rawDef: ViewElementDefinition): Map<string, TypeParamMeta>;
131
189
  export {};
132
190
  //# sourceMappingURL=component-def-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-def-manager.d.ts","sourceRoot":"","sources":["../../../src/typer/component-def-manager/component-def-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,OAAO,EAAE,iBAAiB,EAAmB,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,wBAAwB,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnL,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAapE,MAAM,MAAM,4BAA4B,GACpC,qBAAqB,GACrB,aAAa,GACb,wBAAwB,CAAC;AAE7B,OAAO,CAAC,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC;AAC3C,KAAK,aAAa,GAAG,MAAM,GAAG;IAAE,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAO3D,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,UAAU,GAAG,GAAG,IAAI,qBAAqB,CASrF;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,UAAU,GACd,GAAG,IAAI,4BAA4B,CAErC;AAoBD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAqC;IAExD,OAAO,CAAC,QAAQ;IAmBhB;;OAEG;IACH,QAAQ;IAIR,SAAS,CAAC,GAAG,EAAE,sBAAsB,EAAE,WAAW,CAAC,EAAE,MAAM;IAI3D;;;;;OAKG;IACH,6BAA6B,CAAC,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE,qBAAqB;IAY/E,0BAA0B,CAAC,EAAE,EAAE,iBAAiB;IAKhD;;;;;OAKG;IACH,GAAG,CACD,GAAG,EAAE,4BAA4B,GAAG;QAAE,OAAO,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EACvF,WAAW,CAAC,EAAE,MAAM;IA0CtB,oBAAoB,CAAC,GAAG,EAAE,4BAA4B;IAStD,OAAO,CAAC,kBAAkB;IAI1B;;;OAGG;IACH,qBAAqB;IAIrB,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,YAAY;IAcpB;;;;;OAKG;IACH,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAMvE;;;;;OAKG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAM5D,OAAO,CAAC,oBAAoB;IAuB5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,EAAE,WAAW;;;;CAQnC;AAED,KAAK,uBAAuB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAgB5E,cAAM,2BAA2B;IAC/B;;OAEG;IACH,OAAO,CAAC,UAAU,CAAwB;IAC1C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAwB;IACtC,QAAQ,CAAC,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;gBAErD,MAAM,EAAE;QAAE,GAAG,EAAE,qBAAqB,CAAC;QAAC,wBAAwB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAE,EAC7E,GAAG,EAAE,MAAM;IAmBb;;;;;;OAMG;IACH,OAAO,CAAC,+BAA+B;IAoEvC;;;OAGG;IACH,gBAAgB;IAIhB,YAAY,CAAC,QAAQ,EAAE,MAAM;IAI7B;;;;OAIG;IACH,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAGrD;;;OAGG;IACH,0BAA0B;IAI1B;;;;;;;OAOG;IACH,4BAA4B,CAC1B,UAAU,EAAE,MAAM,GACjB,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,GAAG,IAAI;IA0BlD,2BAA2B,IAAI,uBAAuB,EAAE;CASzD"}
1
+ {"version":3,"file":"component-def-manager.d.ts","sourceRoot":"","sources":["../../../src/typer/component-def-manager/component-def-manager.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComponentDefManager = exports.isGeneralViewElementDefinition = exports.isViewElementDefinition = void 0;
3
+ exports.buildTypeParamMetaFromRawDef = exports.ComponentDefManager = exports.ComponentTagUtils = exports.isGeneralViewElementDefinition = exports.isViewElementDefinition = void 0;
4
4
  const type_manager_1 = require("../type-manager");
5
5
  const lodash_1 = require("lodash");
6
6
  const nasl_utils_1 = require("@lcap/nasl-utils");
@@ -15,11 +15,17 @@ function kebabToPascal(input) {
15
15
  }
16
16
  function isViewElementDefinition(def) {
17
17
  // FIXME: 处理一下这个函数
18
+ const ty = def;
18
19
  return (def.concept === 'TypeAnnotation' &&
19
20
  // 排除 nasl.ui.showMessage 这种函数
20
- def.typeKind !== 'function' &&
21
+ ty.typeKind !== 'function' &&
22
+ // 类型别名(conditional / union 等)不是 View 组件;否则误入 compDefMgr,gQNameDefs 中缺失(如 DateConverterToType)
23
+ ty.typeKind !== 'conditional' &&
24
+ ty.typeKind !== 'union' &&
25
+ // 带泛参的 DTS:仅 props 为匿名结构的为 UI 组件;类型别名包装体 returnType 为 conditional 等,须归入 gQNameDefs
26
+ (ty.typeKind !== 'generic' || ty.returnType?.[0]?.typeKind === 'anonymousStructure') &&
21
27
  // 排除 组件的Options 类
22
- !def.typeName?.endsWith('Options'));
28
+ !ty.typeName?.endsWith('Options'));
23
29
  }
24
30
  exports.isViewElementDefinition = isViewElementDefinition;
25
31
  function isGeneralViewElementDefinition(def) {
@@ -43,9 +49,11 @@ class ComponentTagUtils {
43
49
  return qName;
44
50
  }
45
51
  }
52
+ exports.ComponentTagUtils = ComponentTagUtils;
46
53
  class ComponentDefManager {
47
54
  constructor() {
48
55
  this.gComponents = new Map();
56
+ this.typeParamMetaCache = new Map();
49
57
  }
50
58
  defToTag(def) {
51
59
  switch (def.concept) {
@@ -214,6 +222,22 @@ class ComponentDefManager {
214
222
  const group = this.gComponents.get(normalizedTag);
215
223
  return group?.propTitles?.get(propName) ?? propName;
216
224
  }
225
+ /**
226
+ * 获取某个组件的 TypeParamMeta 映射(rawName → meta),带懒缓存。
227
+ * 不需要实例化 ViewElementDefinitionHelper,可安全在 checker 中使用。
228
+ */
229
+ getTypeParamMetaMap(componentTag) {
230
+ const normalizedTag = ComponentTagUtils.normalizeTag(componentTag);
231
+ const cached = this.typeParamMetaCache.get(normalizedTag);
232
+ if (cached)
233
+ return cached;
234
+ const result = this.queryByNormalizedTag(normalizedTag);
235
+ if (!result)
236
+ return undefined;
237
+ const meta = buildTypeParamMetaFromRawDef(result.rawDef);
238
+ this.typeParamMetaCache.set(normalizedTag, meta);
239
+ return meta;
240
+ }
217
241
  queryByNormalizedTag(tag) {
218
242
  // 返回最先注册的一个。没有特殊的原因,返回最后一个注册的也可以。
219
243
  const rawDef = (0, lodash_1.head)(this.gComponents.get(tag)?.defs)?.def;
@@ -254,6 +278,219 @@ class NameTransformer {
254
278
  return name.replace(/^\S/, (s) => s.toUpperCase());
255
279
  }
256
280
  }
281
+ // ─── 结构化类型参数角色识别工具 ──────────────────────────────────────
282
+ // 以下函数通过分析 initProps 的类型结构(而非类型参数名字)来识别角色。
283
+ /**
284
+ * 检查一个 TypeAnnotation 是否引用了指定的 typeParam(按 typeName 匹配)。
285
+ */
286
+ function isTyRef(ty, paramName) {
287
+ return ty?.typeKind === 'typeParam' && ty.typeName === paramName;
288
+ }
289
+ /**
290
+ * 从匿名结构 `{ list: List<X>, ... }` 中提取 typeParam 名。
291
+ * 仅匹配包含 `list: List<X>` 属性的匿名结构——这是 dataSource 的标志性结构。
292
+ * 不匹配独立的 `List<X>`(如 `values: List<V>`),避免把 value 类型错误识别为 dataItem。
293
+ */
294
+ function extractTypeParamFromStructuredList(ty, typeParamNames) {
295
+ if (!ty)
296
+ return undefined;
297
+ if (ty.typeKind === 'anonymousStructure' && ty.properties?.length) {
298
+ const listProp = ty.properties.find((p) => p.name === 'list');
299
+ if (listProp?.typeAnnotation?.typeName === 'List' &&
300
+ listProp.typeAnnotation.typeNamespace === 'nasl.collection' &&
301
+ listProp.typeAnnotation.typeArguments?.[0]?.typeKind === 'typeParam') {
302
+ const name = listProp.typeAnnotation.typeArguments[0].typeName;
303
+ if (name && typeParamNames.has(name))
304
+ return name;
305
+ }
306
+ }
307
+ return undefined;
308
+ }
309
+ /**
310
+ * 在一个可能是 union 的类型里搜索 dataSource 模式。
311
+ * 仅当类型中包含 `{ list: List<X>, ... }` 匿名结构时才认定为 dataSource 模式。
312
+ *
313
+ * 匹配以下结构:
314
+ * - `{ list: List<X>, total: Integer }` (直接结构)
315
+ * - `{ list: List<X>, total: Integer } | List<X>` (union 包含结构)
316
+ * - `{ list: List<X>, total: Integer } | List<X> | OtherType` (union 多分支)
317
+ *
318
+ * 不匹配:
319
+ * - `List<V>` (独立 List,如 values: List<V>、pageSizeOptions: List<Integer>)
320
+ * - `List<V> | null` (没有 { list: List<X> } 的 union)
321
+ */
322
+ function extractDataItemFromType(ty, typeParamNames) {
323
+ if (!ty)
324
+ return undefined;
325
+ if (ty.typeKind === 'union' && ty.typeArguments?.length) {
326
+ for (const alt of ty.typeArguments) {
327
+ const found = extractTypeParamFromStructuredList(alt, typeParamNames);
328
+ if (found)
329
+ return found;
330
+ }
331
+ }
332
+ return extractTypeParamFromStructuredList(ty, typeParamNames);
333
+ }
334
+ /**
335
+ * 扫描所有 initProps,找出所有"数据项"类型参数。
336
+ * 返回 Map<typeParamName, dataSourcePropName>。
337
+ *
338
+ * 匹配两种数据源模式:
339
+ * 1. `{ list: List<T>, total: Integer }` 结构模式(如 UTableView)
340
+ * 2. `dataSource: List<T>` 直接 List 模式(如 USelectableSteps)
341
+ */
342
+ function findDataItemTypeParams(props, typeParamNames) {
343
+ const result = new Map();
344
+ for (const prop of props) {
345
+ const found = extractDataItemFromType(prop.typeAnnotation, typeParamNames);
346
+ if (found && !result.has(found)) {
347
+ result.set(found, prop.name);
348
+ continue;
349
+ }
350
+ // 直接 List<T> 模式:dataSource: nasl.collection.List<T>
351
+ if (prop.name === 'dataSource') {
352
+ const ty = prop.typeAnnotation;
353
+ if (ty?.typeName === 'List' &&
354
+ ty.typeNamespace === 'nasl.collection' &&
355
+ ty.typeArguments?.[0]?.typeKind === 'typeParam') {
356
+ const paramName = ty.typeArguments[0].typeName;
357
+ if (paramName && typeParamNames.has(paramName) && !result.has(paramName)) {
358
+ result.set(paramName, prop.name);
359
+ }
360
+ }
361
+ }
362
+ }
363
+ return result;
364
+ }
365
+ /**
366
+ * 扫描所有 initProps,找出"值字段结果"类型参数。
367
+ * 匹配模式: 某个属性类型为 `(item: DataItem) => X`,其中 X 是一个 typeParam。
368
+ */
369
+ function findValueResultTypeParams(props, typeParamNames, dataItemParamNames) {
370
+ const result = new Set();
371
+ for (const prop of props) {
372
+ const ty = prop.typeAnnotation;
373
+ if (ty?.typeKind !== 'function' || !ty.fnArgs?.length || !ty.returnType?.length)
374
+ continue;
375
+ const firstArgType = ty.fnArgs[0]?.type;
376
+ if (!firstArgType || firstArgType.typeKind !== 'typeParam')
377
+ continue;
378
+ if (!dataItemParamNames.has(firstArgType.typeName ?? ''))
379
+ continue;
380
+ const retTy = ty.returnType[0];
381
+ if (retTy?.typeKind === 'typeParam' && retTy.typeName && typeParamNames.has(retTy.typeName)) {
382
+ result.add(retTy.typeName);
383
+ }
384
+ }
385
+ return result;
386
+ }
387
+ /**
388
+ * 检测带有 `extends Boolean` 约束的类型参数。
389
+ * 在 rawDef.typeParams 上判断 constraints 字段。
390
+ */
391
+ function findBooleanConstraintTypeParams(typeParams) {
392
+ const result = new Set();
393
+ for (const tp of typeParams) {
394
+ const name = tp.typeName;
395
+ if (!name)
396
+ continue;
397
+ // constraints 是单个 TypeAnnotation(多个约束时为 union 类型)
398
+ const constraint = tp.constraints;
399
+ if (!constraint)
400
+ continue;
401
+ const isBooleanConstraint = (c) => c.typeNamespace === 'nasl.core' && c.typeName === 'Boolean';
402
+ if (isBooleanConstraint(constraint)) {
403
+ result.add(name);
404
+ }
405
+ else if (constraint.typeKind === 'union' && constraint.typeArguments?.some(isBooleanConstraint)) {
406
+ result.add(name);
407
+ }
408
+ }
409
+ return result;
410
+ }
411
+ /**
412
+ * 为 booleanFlag 类型参数找到对应的属性名。
413
+ * 策略:在 initProps 中找到类型直接是该 typeParam 的属性(排除已被识别为 dataItem/valueResult 的)。
414
+ */
415
+ function findBooleanPropForTypeParam(paramName, props, excludeParams) {
416
+ if (excludeParams.has(paramName))
417
+ return undefined;
418
+ for (const prop of props) {
419
+ if (isTyRef(prop.typeAnnotation, paramName)) {
420
+ return prop.name;
421
+ }
422
+ }
423
+ return undefined;
424
+ }
425
+ /** 类型参数约束为字面量 union(如 C extends 'auto' | 'string'),用于识别 converter / picker 的 type 等 */
426
+ function hasStringLiteralUnionConstraint(tp) {
427
+ const c = tp.constraints;
428
+ if (!c)
429
+ return false;
430
+ const ok = (ty) => {
431
+ if (!ty)
432
+ return false;
433
+ if (ty.typeKind === 'literal')
434
+ return typeof ty.literal === 'string';
435
+ if (ty.typeKind === 'union' && ty.typeArguments?.length) {
436
+ return ty.typeArguments.every((a) => ok(a));
437
+ }
438
+ return false;
439
+ };
440
+ return ok(c);
441
+ }
442
+ /**
443
+ * 扫描属性类型中的条件类型,找出用作 checkType 的类型参数。
444
+ * 例如 `value: C extends '' ? List<V> : String` 中,C 是条件标志。
445
+ * 返回 Map<typeParamName, { extendsType, propName? }>。
446
+ */
447
+ function findConditionalFlagTypeParams(props, typeParamNames, assignedParams) {
448
+ const result = new Map();
449
+ for (const prop of props) {
450
+ const ty = prop.typeAnnotation;
451
+ if (ty?.typeKind !== 'conditional')
452
+ continue;
453
+ const checkType = ty.checkType;
454
+ if (checkType?.typeKind === 'typeParam' &&
455
+ checkType.typeName &&
456
+ typeParamNames.has(checkType.typeName) &&
457
+ !assignedParams.has(checkType.typeName) &&
458
+ ty.extendsType) {
459
+ result.set(checkType.typeName, { extendsType: ty.extendsType, propName: undefined });
460
+ }
461
+ }
462
+ for (const [paramName, info] of result) {
463
+ const lit = info.extendsType;
464
+ if (lit.typeKind === 'literal') {
465
+ for (const prop of props) {
466
+ const pty = prop.typeAnnotation;
467
+ if (!pty)
468
+ continue;
469
+ if (pty.typeKind === 'union' &&
470
+ pty.typeArguments?.some((a) => a.typeKind === 'literal' && a.literal === lit.literal)) {
471
+ info.propName = prop.name;
472
+ break;
473
+ }
474
+ if (pty.typeKind === 'literal' && pty.literal === lit.literal) {
475
+ info.propName = prop.name;
476
+ break;
477
+ }
478
+ }
479
+ }
480
+ // modelValue 等:外层条件是 DT extends 'date',但 init 里是 type: DT(类型参数),
481
+ // 不是字面量 union,上面匹配不到;用「属性类型即该类型参数」补上(如 el-date-picker)。
482
+ if (!info.propName) {
483
+ for (const prop of props) {
484
+ if (isTyRef(prop.typeAnnotation, paramName)) {
485
+ info.propName = prop.name;
486
+ break;
487
+ }
488
+ }
489
+ }
490
+ }
491
+ return result;
492
+ }
493
+ // ─── ViewElementDefinitionHelper ──────────────────────────────────
257
494
  class ViewElementDefinitionHelper {
258
495
  constructor(option, env) {
259
496
  this.rawDef = option.def;
@@ -267,6 +504,7 @@ class ViewElementDefinitionHelper {
267
504
  env.unifier.inPlaceRenameTy(defWithTypeParams);
268
505
  }
269
506
  this.renamedDef = defWithTypeParams;
507
+ this.typeParamMetaMap = this.buildTypeParamMeta();
270
508
  }
271
509
  /**
272
510
  * 为组件定义增加 _if: boolean 属性
@@ -358,6 +596,15 @@ class ViewElementDefinitionHelper {
358
596
  getInitPropsTypeAnnotation() {
359
597
  return this.renamedDef.typeArguments?.[0];
360
598
  }
599
+ /**
600
+ * 根据 slotTarget 获取slot的scope类型
601
+ * @param slotTarget
602
+ * @returns
603
+ */
604
+ getSlotPropBySlotTarget(slotTarget) {
605
+ const slotMethodName = `slot${NameTransformer.toFirstUpper(NameTransformer.toHump(slotTarget))}`;
606
+ return this.getInitPropsTypeAnnotation()?.properties?.find((prop) => prop.name === slotMethodName);
607
+ }
361
608
  /**
362
609
  * 根据 slotTarget 获取slot的参数类型
363
610
  * @param slotTarget
@@ -366,14 +613,11 @@ class ViewElementDefinitionHelper {
366
613
  * 1. 返回 非null,表示需要引入current
367
614
  * 2. 返回 null, 表示不需要引入current
368
615
  */
369
- getSlotScopeTypeBySlotTarget(slotTarget) {
370
- const slotMethodName = `slot${NameTransformer.toFirstUpper(NameTransformer.toHump(slotTarget))}`;
371
- const slotProp = this.getInitPropsTypeAnnotation()?.properties?.find((prop) => prop.name === slotMethodName);
616
+ getSlotScopeType(slotProp) {
372
617
  if (slotProp?.typeAnnotation?.typeKind === 'function' &&
373
618
  slotProp.typeAnnotation.fnArgs?.length) {
374
- // 如果slotProp.typeAnnotation.fnArgs[0]?.name !== 'current',那么报错提示一下用户
375
619
  if (slotProp.typeAnnotation.fnArgs[0]?.name !== 'current') {
376
- console.error(`[getSlotParamTypeBySlotTarget] slotTarget: ${slotTarget}, 目前只支持current作为slot变量的名字,请使用current作为slot变量的名字`);
620
+ console.error(`[getSlotScopeType] slotProp: ${slotProp.name}, 目前只支持current作为slot变量的名字,请使用current作为slot变量的名字`);
377
621
  }
378
622
  return [
379
623
  {
@@ -392,5 +636,153 @@ class ViewElementDefinitionHelper {
392
636
  return { rawName, renamed: x };
393
637
  }) ?? []);
394
638
  }
639
+ /**
640
+ * 获取某个原始类型参数名对应的兜底策略配置。
641
+ */
642
+ getTypeParamMeta(rawName) {
643
+ return this.typeParamMetaMap.get(rawName);
644
+ }
645
+ /**
646
+ * 基于原始组件定义的类型结构,自动识别每个 typeParam 的角色并生成兜底策略。
647
+ * 完全不依赖 typeParam 的名字(T/V/C/M/P 等),只依赖类型结构模式匹配。
648
+ */
649
+ buildTypeParamMeta() {
650
+ return buildTypeParamMetaFromRawDef(this.rawDef);
651
+ }
652
+ }
653
+ /**
654
+ * 基于原始组件定义的类型结构,自动识别每个 typeParam 的角色并生成兜底策略。
655
+ * 独立于 ViewElementDefinitionHelper 实例,可在不实例化的场景下使用(如 checker)。
656
+ */
657
+ function buildTypeParamMetaFromRawDef(rawDef) {
658
+ const map = new Map();
659
+ const rawTypeParams = rawDef.typeParams ?? [];
660
+ if (!rawTypeParams.length)
661
+ return map;
662
+ const rawInitProps = rawDef.typeArguments?.[0]?.properties ?? [];
663
+ const typeParamNames = new Set(rawTypeParams.map((tp) => tp.typeName).filter((n) => !!n));
664
+ const dataItemMap = findDataItemTypeParams(rawInitProps, typeParamNames);
665
+ const dataItemNames = new Set(dataItemMap.keys());
666
+ const valueResultNames = findValueResultTypeParams(rawInitProps, typeParamNames, dataItemNames);
667
+ const booleanNames = findBooleanConstraintTypeParams(rawTypeParams);
668
+ const assignedParams = new Set([...dataItemNames, ...valueResultNames]);
669
+ const conditionalFlagExcludes = new Set([...assignedParams, ...booleanNames]);
670
+ const conditionalFlags = findConditionalFlagTypeParams(rawInitProps, typeParamNames, conditionalFlagExcludes);
671
+ rawTypeParams.forEach((tp) => {
672
+ const name = tp.typeName;
673
+ if (!name)
674
+ return;
675
+ if (dataItemNames.has(name)) {
676
+ map.set(name, {
677
+ role: 'dataItem',
678
+ hasOwnDataSource: true,
679
+ dataSourcePropName: dataItemMap.get(name),
680
+ defaultWhenUnresolved: type_manager_1.naslStringTy,
681
+ });
682
+ }
683
+ else if (valueResultNames.has(name)) {
684
+ map.set(name, {
685
+ role: 'valueResult',
686
+ hasOwnDataSource: false,
687
+ defaultWhenUnresolved: type_manager_1.naslStringTy,
688
+ });
689
+ }
690
+ else if (booleanNames.has(name)) {
691
+ const propName = findBooleanPropForTypeParam(name, rawInitProps, assignedParams);
692
+ map.set(name, {
693
+ role: 'booleanFlag',
694
+ hasOwnDataSource: false,
695
+ defaultFromProp: propName ? { propName, mode: 'booleanFlag' } : undefined,
696
+ // 当无法通过结构匹配找到对应的 Boolean 属性时(如 van-pickerson 的 M 对应 multiple,
697
+ // 但 multiple 类型是 Boolean 而非 M),提供 false 作为兜底默认值,
698
+ // 确保条件类型(如 M extends true ? List<V> : V)能够正确解出。
699
+ defaultWhenUnresolved: propName ? undefined : nasl_concepts_1.TypeAnnotation.createLiteral(false),
700
+ });
701
+ }
702
+ else if (conditionalFlags.has(name)) {
703
+ const flagInfo = conditionalFlags.get(name);
704
+ const constraint = tp.constraints;
705
+ map.set(name, {
706
+ role: 'converterLiteral',
707
+ hasOwnDataSource: false,
708
+ defaultFromProp: flagInfo.propName
709
+ ? { propName: flagInfo.propName, mode: 'converterLiteral' }
710
+ : undefined,
711
+ // 有对应 init 属性(如 type: DT)时,缺省应用整个字面量约束 union,而不是仅 extends 分支上的字面量(如 'date')
712
+ defaultWhenUnresolved: flagInfo.propName && constraint ? constraint : flagInfo.extendsType,
713
+ });
714
+ }
715
+ });
716
+ rawTypeParams.forEach((tp) => {
717
+ const name = tp.typeName;
718
+ if (!name || map.has(name))
719
+ return;
720
+ const usedInFieldOrSlot = rawInitProps.some((prop) => {
721
+ const ty = prop.typeAnnotation;
722
+ if (!ty || ty.typeKind !== 'function' || !ty.fnArgs?.length)
723
+ return false;
724
+ const firstArgName = ty.fnArgs[0]?.name;
725
+ if (firstArgName !== 'item' && firstArgName !== 'current')
726
+ return false;
727
+ if (isTyRef(ty.fnArgs[0]?.type, name))
728
+ return true;
729
+ const argTy = ty.fnArgs[0]?.type;
730
+ if (argTy?.typeArguments?.some((a) => isTyRef(a, name)))
731
+ return true;
732
+ return false;
733
+ });
734
+ if (usedInFieldOrSlot) {
735
+ map.set(name, {
736
+ role: 'dataItem',
737
+ hasOwnDataSource: false,
738
+ defaultWhenUnresolved: type_manager_1.naslStringTy,
739
+ });
740
+ }
741
+ });
742
+ rawTypeParams.forEach((tp) => {
743
+ const name = tp.typeName;
744
+ if (!name || map.has(name))
745
+ return;
746
+ const usedInSlotCurrentStruct = rawInitProps.some((prop) => {
747
+ const ty = prop.typeAnnotation;
748
+ if (!ty || ty.typeKind !== 'function' || !ty.fnArgs?.length)
749
+ return false;
750
+ const firstArgName = ty.fnArgs[0]?.name;
751
+ if (firstArgName !== 'item' && firstArgName !== 'current')
752
+ return false;
753
+ const argTy = ty.fnArgs[0]?.type;
754
+ if (argTy?.typeKind === 'anonymousStructure') {
755
+ return argTy.properties?.some((p) => isTyRef(p.typeAnnotation, name)) ?? false;
756
+ }
757
+ return false;
758
+ });
759
+ if (usedInSlotCurrentStruct) {
760
+ map.set(name, {
761
+ role: 'valueResult',
762
+ hasOwnDataSource: false,
763
+ defaultWhenUnresolved: type_manager_1.naslStringTy,
764
+ });
765
+ }
766
+ });
767
+ // converter: C 等:未出现在顶层 conditional 的 checkType 上,但 init 上有「属性类型即该类型参数」
768
+ rawTypeParams.forEach((tp) => {
769
+ const name = tp.typeName;
770
+ if (!name || map.has(name))
771
+ return;
772
+ if (!hasStringLiteralUnionConstraint(tp))
773
+ return;
774
+ const directProp = rawInitProps.find((p) => isTyRef(p.typeAnnotation, name));
775
+ if (!directProp)
776
+ return;
777
+ const constraint = tp.constraints;
778
+ map.set(name, {
779
+ role: 'converterLiteral',
780
+ hasOwnDataSource: false,
781
+ defaultFromProp: { propName: directProp.name, mode: 'converterLiteral' },
782
+ defaultWhenUnresolved: constraint ?? type_manager_1.naslStringTy,
783
+ });
784
+ });
785
+ return map;
395
786
  }
787
+ exports.buildTypeParamMetaFromRawDef = buildTypeParamMetaFromRawDef;
396
788
  //# sourceMappingURL=component-def-manager.js.map