@lcap/nasl-language-server-core 4.4.0-beta.18 → 4.4.0-beta.20

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 (97) hide show
  1. package/out/checker.d.ts.map +1 -1
  2. package/out/checker.js +143 -4
  3. package/out/checker.js.map +1 -1
  4. package/out/index.d.ts +1 -1
  5. package/out/index.d.ts.map +1 -1
  6. package/out/index.js +5 -3
  7. package/out/index.js.map +1 -1
  8. package/out/reference-manager/build-q-name-def.js +2 -2
  9. package/out/reference-manager/build-q-name-def.js.map +1 -1
  10. package/out/reference-manager/builtin-q-name.js +2 -2
  11. package/out/reference-manager/builtin-q-name.js.map +1 -1
  12. package/out/reference-manager/collect-q-name.d.ts +1 -1
  13. package/out/reference-manager/collect-q-name.d.ts.map +1 -1
  14. package/out/reference-manager/collect-q-name.js +58 -24
  15. package/out/reference-manager/collect-q-name.js.map +1 -1
  16. package/out/reference-manager/def-key-helpers.d.ts +38 -0
  17. package/out/reference-manager/def-key-helpers.d.ts.map +1 -0
  18. package/out/reference-manager/{get-q-name.js → def-key-helpers.js} +176 -29
  19. package/out/reference-manager/def-key-helpers.js.map +1 -0
  20. package/out/reference-manager/helper.js +2 -2
  21. package/out/reference-manager/helper.js.map +1 -1
  22. package/out/reference-manager/reference-manager.d.ts +24 -52
  23. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  24. package/out/reference-manager/reference-manager.js +222 -219
  25. package/out/reference-manager/reference-manager.js.map +1 -1
  26. package/out/reference-manager/remove-q-name.d.ts +1 -1
  27. package/out/reference-manager/remove-q-name.d.ts.map +1 -1
  28. package/out/reference-manager/remove-q-name.js +7 -10
  29. package/out/reference-manager/remove-q-name.js.map +1 -1
  30. package/out/reference-manager/rename-q-name.d.ts +26 -26
  31. package/out/reference-manager/rename-q-name.d.ts.map +1 -1
  32. package/out/reference-manager/rename-q-name.js +48 -167
  33. package/out/reference-manager/rename-q-name.js.map +1 -1
  34. package/out/reference-manager/symbol-type.d.ts +4 -4
  35. package/out/reference-manager/symbol-type.d.ts.map +1 -1
  36. package/out/reference-manager/symbol-type.js +1 -1
  37. package/out/reference-manager/symbol-type.js.map +1 -1
  38. package/out/reference-manager/update-nasl-fragment.js +4 -4
  39. package/out/reference-manager/update-nasl-fragment.js.map +1 -1
  40. package/out/typer/collectGlobalDefs.js +3 -3
  41. package/out/typer/collectGlobalDefs.js.map +1 -1
  42. package/out/typer/component-def-manager/component-def-manager.d.ts +16 -0
  43. package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
  44. package/out/typer/component-def-manager/component-def-manager.js +63 -2
  45. package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
  46. package/out/typer/component-def-manager/utils.d.ts.map +1 -1
  47. package/out/typer/component-def-manager/utils.js +3 -2
  48. package/out/typer/component-def-manager/utils.js.map +1 -1
  49. package/out/typer/dispatch-all.js +3 -3
  50. package/out/typer/dispatch-all.js.map +1 -1
  51. package/out/typer/dispatch-call.js +3 -3
  52. package/out/typer/dispatch-call.js.map +1 -1
  53. package/out/typer/dispatch-def.js +3 -3
  54. package/out/typer/dispatch-def.js.map +1 -1
  55. package/out/typer/dispatch-expr.d.ts.map +1 -1
  56. package/out/typer/dispatch-expr.js +29 -30
  57. package/out/typer/dispatch-expr.js.map +1 -1
  58. package/out/typer/dispatch-process.js +3 -3
  59. package/out/typer/dispatch-process.js.map +1 -1
  60. package/out/typer/dispatch-view.d.ts.map +1 -1
  61. package/out/typer/dispatch-view.js +8 -13
  62. package/out/typer/dispatch-view.js.map +1 -1
  63. package/out/typer/get-oql-files.js +1 -1
  64. package/out/typer/get-oql-files.js.map +1 -1
  65. package/out/typer/incremental-update.js +8 -8
  66. package/out/typer/incremental-update.js.map +1 -1
  67. package/out/typer/overload-helper.js +2 -2
  68. package/out/typer/overload-helper.js.map +1 -1
  69. package/out/typer/solver.d.ts +5 -1
  70. package/out/typer/solver.d.ts.map +1 -1
  71. package/out/typer/solver.js +29 -9
  72. package/out/typer/solver.js.map +1 -1
  73. package/out/typer/subster.d.ts.map +1 -1
  74. package/out/typer/subster.js +39 -6
  75. package/out/typer/subster.js.map +1 -1
  76. package/out/typer/topo-sort.js +4 -4
  77. package/out/typer/topo-sort.js.map +1 -1
  78. package/out/typer/type-manager.d.ts.map +1 -1
  79. package/out/typer/type-manager.js +3 -3
  80. package/out/typer/type-manager.js.map +1 -1
  81. package/out/typer/type-predicate.js +4 -4
  82. package/out/typer/type-predicate.js.map +1 -1
  83. package/out/typer/typer.d.ts +2 -2
  84. package/out/typer/typer.d.ts.map +1 -1
  85. package/out/typer/typer.js +38 -29
  86. package/out/typer/typer.js.map +1 -1
  87. package/out/typer/unifier.d.ts.map +1 -1
  88. package/out/typer/unifier.js +19 -20
  89. package/out/typer/unifier.js.map +1 -1
  90. package/package.json +6 -6
  91. package/out/reference-manager/get-q-name.d.ts +0 -14
  92. package/out/reference-manager/get-q-name.d.ts.map +0 -1
  93. package/out/reference-manager/get-q-name.js.map +0 -1
  94. package/out/reference-manager/view-elem-logic.d.ts +0 -44
  95. package/out/reference-manager/view-elem-logic.d.ts.map +0 -1
  96. package/out/reference-manager/view-elem-logic.js +0 -181
  97. package/out/reference-manager/view-elem-logic.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAC4C,QAAQ,EAC5B,IAAI,EAQ+E,GAAG,EAMxH,QAAQ,EAGT,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACgE,cAAc,EAGpF,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAWpE,oBAAY,QAAQ;IAClB,IAAI,YAAY;IAChB,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAEnE,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAMF,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAMrE,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAqBF,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,yBAAyB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/C,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAkPF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe;oCAslKpB,OAAO;sDAPW,gBAAgB,EAAE;;;;sBAhBjD,UAAU,GAAG,SAAS;;;8BA4Df,UAAU;2BAyBb,UAAU;;iDAtwFY,GAAG,KAAG,IAAI;;iBAixFjD,MAAM;kBACL,MAAM;kBACN,MAAM;qBACH,MAAM;;kBAvmKF,UAAU,WAAW,MAAM,YAAY,YAAY;sCA21D/B,IAAI,GAAG,QAAQ;2CA+yGxC,UAAU,gBACV,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,gBAC/C,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,qBACvB,MAAM,EAAE,oBACT,CAAC,YAAY,EAAE,UAAU,KAAK,UAAU,EAAE,KAC3D,kBAAkB,GAAG,IAAI;EAwF7B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IAEX,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,mBAAmB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACvC,qBAAqB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;CAC1C;AAMD,eAAO,MAAM,6BAA6B,aAC9B,UAAU,+DAGnB,MAAM,gBAAgB,CAyCxB,CAAC;AAMF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAC4C,QAAQ,EAC5B,IAAI,EAQ+E,GAAG,EAMxH,QAAQ,EAGT,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACgE,cAAc,EAGpF,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAYpE,oBAAY,QAAQ;IAClB,IAAI,YAAY;IAChB,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAEnE,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAMF,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAMrE,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAqBF,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,yBAAyB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/C,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAkPF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe;oCAoqKpB,OAAO;sDAPW,gBAAgB,EAAE;;;;sBAhBjD,UAAU,GAAG,SAAS;;;8BA4Df,UAAU;2BAyBb,UAAU;;iDAzxFY,GAAG,KAAG,IAAI;;iBAoyFjD,MAAM;kBACL,MAAM;kBACN,MAAM;qBACH,MAAM;;kBArrKF,UAAU,WAAW,MAAM,YAAY,YAAY;sCAu3D/B,IAAI,GAAG,QAAQ;2CAi2GxC,UAAU,gBACV,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,gBAC/C,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,qBACvB,MAAM,EAAE,oBACT,CAAC,YAAY,EAAE,UAAU,KAAK,UAAU,EAAE,KAC3D,kBAAkB,GAAG,IAAI;EAwF7B;AAqED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IAEX,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,mBAAmB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACvC,qBAAqB,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;CAC1C;AAMD,eAAO,MAAM,6BAA6B,aAC9B,UAAU,+DAGnB,MAAM,gBAAgB,CAyCxB,CAAC;AAMF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
package/out/checker.js CHANGED
@@ -14,6 +14,7 @@ const lodash_1 = require("lodash");
14
14
  const asserts_1 = require("@lcap/nasl-concepts/asserts");
15
15
  const helper_1 = require("./typer/helper");
16
16
  const semantic_rules_1 = require("./semantic-rules");
17
+ const view_element_field_attrs_1 = require("@lcap/nasl-concepts/view-element-field-attrs");
17
18
  const regeExp = new nasl_utils_1.ExpressionLexer();
18
19
  regeExp.profile = nasl_utils_1.profiles.js;
19
20
  var Severity;
@@ -775,6 +776,31 @@ function createErrorDiagnoser(context) {
775
776
  }
776
777
  return false;
777
778
  }
779
+ /**
780
+ * 获取 ViewElement 的数据源类型(T 或 T1)
781
+ * 参考 util.js 中的 getDataTypeOfViewElement 实现
782
+ */
783
+ function getDataSourceTypeAnnotation(viewElement) {
784
+ // 向上查找定义了数据源类型的祖先组件
785
+ let currentNode = viewElement;
786
+ let depth = 0;
787
+ const maxSearchDepth = 5;
788
+ while (currentNode?.concept === 'ViewElement' && depth <= maxSearchDepth) {
789
+ // 使用 __ViewElementTV 获取类型,与 IDE 前端 getDataTypeOfViewElement 保持一致
790
+ if (currentNode.__TypeAnnotation && currentNode.__ViewElementTV?.length) {
791
+ // 先查找 T1(动态列),若无再查找 T(普通数据源组件)
792
+ const t1 = currentNode.__ViewElementTV.find((x) => x.rawName === 'T1');
793
+ if (t1?.renamed)
794
+ return t1.renamed;
795
+ const t = currentNode.__ViewElementTV.find((x) => x.rawName === 'T');
796
+ if (t?.renamed)
797
+ return t.renamed;
798
+ }
799
+ currentNode = currentNode.parentNode;
800
+ depth++;
801
+ }
802
+ return undefined;
803
+ }
778
804
  /**
779
805
  * 是否在赋值左侧
780
806
  * @param node
@@ -1843,6 +1869,9 @@ function createErrorDiagnoser(context) {
1843
1869
  * @param node
1844
1870
  */
1845
1871
  function* checkEnum(node) {
1872
+ if (!node.valueType) {
1873
+ error(node, `枚举 ${node.name} 缺少值类型定义`);
1874
+ }
1846
1875
  if (node.enumItems?.length) {
1847
1876
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.enumItems, function* (node) {
1848
1877
  yield* checkNode(node);
@@ -2353,6 +2382,31 @@ function createErrorDiagnoser(context) {
2353
2382
  }
2354
2383
  yield* checkPlayground(node.playground);
2355
2384
  yield* checkBindExpressions(node);
2385
+ // 检查数据源上的字段属性是否在类型上存在
2386
+ // 判断条件:
2387
+ // 1. 属性的 setter 是 PropertySelectSetter(从组件定义的 ViewComponentDeclaration 中获取)
2388
+ // 2. 或者属性在 FIELD_ATTRS_BY_COMPONENT 配置中(兼容老版本组件配置)
2389
+ if (node.type === 'string' && typeof node.value === 'string' && node.value) {
2390
+ const viewElement = node.parentNode;
2391
+ if (viewElement?.concept === 'ViewElement') {
2392
+ // 优先检查组件定义中的 PropertySelectSetter
2393
+ const isPropertySelect = env.refMgr.compDefMgr.isPropertySelectSetter(viewElement.tag, node.name);
2394
+ // 同时兼容 FIELD_ATTRS_BY_COMPONENT 配置
2395
+ const needsFieldCheck = isPropertySelect || (0, view_element_field_attrs_1.shouldCheckFieldExists)(viewElement.tag, node.name);
2396
+ if (needsFieldCheck) {
2397
+ const dataSourceType = getDataSourceTypeAnnotation(viewElement);
2398
+ if (dataSourceType) {
2399
+ const { exists, missingField } = checkFieldExistsInType(env, dataSourceType, node.value);
2400
+ if (!exists && missingField) {
2401
+ // 优先从组件定义中获取属性标题,兜底使用硬编码配置
2402
+ const attrTitle = env.refMgr.compDefMgr.getPropTitle(viewElement.tag, node.name)
2403
+ || (0, view_element_field_attrs_1.getFieldAttrTitle)(node.name);
2404
+ error(node, `${attrTitle} "${missingField}" 在数据类型上不存在`);
2405
+ }
2406
+ }
2407
+ }
2408
+ }
2409
+ }
2356
2410
  // 检查不可复制属性开启双向绑定
2357
2411
  if ((node.model || node.sync) && node.expression) {
2358
2412
  const bindExpression = node.expression;
@@ -2448,6 +2502,11 @@ function createErrorDiagnoser(context) {
2448
2502
  // 任务完成人为空会有一个提示信息
2449
2503
  error(node, `${title}为空`);
2450
2504
  }
2505
+ if (Array.isArray(node.fromLogics)) {
2506
+ yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.fromLogics, function* (node) {
2507
+ yield* checkNode(node);
2508
+ });
2509
+ }
2451
2510
  }
2452
2511
  /**
2453
2512
  * 检查 元素指令
@@ -3021,8 +3080,8 @@ function createErrorDiagnoser(context) {
3021
3080
  }
3022
3081
  }
3023
3082
  if (!isSame) {
3024
- const macthed = exportInterface.concept === 'McpInterface';
3025
- const key = macthed ? 'exportMcpInterface' : 'exportInterface';
3083
+ const matched = exportInterface.concept === 'McpInterface';
3084
+ const key = matched ? 'exportMcpInterface' : 'exportInterface';
3026
3085
  error(node, `逻辑已变更,请确认请求类型无误后重新导出${'${event}'}`, {
3027
3086
  severity: Severity.ERROR,
3028
3087
  events: [
@@ -3383,17 +3442,30 @@ function createErrorDiagnoser(context) {
3383
3442
  for (let i = 1; i < nd.arguments.length; i++) {
3384
3443
  const expr = nd.arguments[i].expression;
3385
3444
  let resTy;
3445
+ const reportArgError = (targetExpr) => {
3446
+ const actualTy = targetExpr ? env.getType(targetExpr) || type_manager_1.naslAnyTy : type_manager_1.naslAnyTy;
3447
+ error(nd.arguments[i], (0, sem_diag_1.mkIncompatibleTyErr)(env, actualTy, expectTy));
3448
+ };
3386
3449
  if (expr?.concept === 'AnonymousFunction') {
3387
3450
  resTy = env.getType(expr.body);
3388
3451
  if (!nasl_concepts_1.asserts.isNewComposite(expr.body)) {
3389
- error(nd.arguments[i], (0, sem_diag_1.mkIncompatibleTyErr)(env, env.getType(expr) || type_manager_1.naslAnyTy, expectTy));
3452
+ reportArgError(expr);
3390
3453
  }
3391
3454
  }
3392
3455
  else if (expr?.concept === 'SubLogic') {
3393
3456
  resTy = env.getType(expr.returns?.[0]);
3394
3457
  }
3458
+ else if (expr?.concept === 'Identifier') {
3459
+ const ty = env.getType(expr);
3460
+ if ((0, type_predicate_1.isFuncTy)(ty)) {
3461
+ resTy = ty;
3462
+ }
3463
+ else {
3464
+ reportArgError(expr);
3465
+ }
3466
+ }
3395
3467
  else {
3396
- error(nd.arguments[i], (0, sem_diag_1.mkIncompatibleTyErr)(env, env.getType(expr) || type_manager_1.naslAnyTy, expectTy));
3468
+ reportArgError(expr);
3397
3469
  }
3398
3470
  const byTy = resTy?.properties?.find((prop) => prop.name === 'by')?.typeAnnotation;
3399
3471
  if (byTy?.typeKind === 'union') {
@@ -3788,12 +3860,18 @@ function createErrorDiagnoser(context) {
3788
3860
  */
3789
3861
  function* checkForEachStatement(node) {
3790
3862
  env.enterScope(node);
3863
+ if (ensureNodeKeyExists(node, 'item')) {
3864
+ yield* checkNode(node.item);
3865
+ }
3791
3866
  if (ensureNodeKeyExists(node, 'each')) {
3792
3867
  yield* checkNode(node.each);
3793
3868
  }
3794
3869
  if (ensureNodeKeyExists(node, 'start')) {
3795
3870
  yield* checkNode(node.start);
3796
3871
  }
3872
+ if (node.end) {
3873
+ yield* checkNode(node.end);
3874
+ }
3797
3875
  if (node.body?.length) {
3798
3876
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.body, function* (node) {
3799
3877
  yield* checkNode(node);
@@ -4544,6 +4622,9 @@ function createErrorDiagnoser(context) {
4544
4622
  yield* checkNode(node);
4545
4623
  });
4546
4624
  }
4625
+ else {
4626
+ error(node, 'Join 子句的关联关系不能为空');
4627
+ }
4547
4628
  if (node.joinParts?.length) {
4548
4629
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.joinParts, function* (node) {
4549
4630
  yield* checkNode(node);
@@ -5384,6 +5465,64 @@ function createErrorDiagnoser(context) {
5384
5465
  };
5385
5466
  }
5386
5467
  exports.createErrorDiagnoser = createErrorDiagnoser;
5468
+ /**
5469
+ * 检查字段路径是否在类型上存在
5470
+ * 类似于 s-component-attr-form.vue 中的 findPropertyNode 功能
5471
+ * @param env 语义环境
5472
+ * @param dataType 数据源类型
5473
+ * @param fieldPath 字段路径,如 "name" 或 "user.name"
5474
+ * @returns { exists: boolean, missingField?: string } 如果字段不存在,返回第一个不存在的字段名
5475
+ */
5476
+ function checkFieldExistsInType(env, dataType, fieldPath) {
5477
+ if (!dataType || !fieldPath) {
5478
+ return { exists: true }; // 没有类型信息或字段路径时,跳过检查
5479
+ }
5480
+ const fieldParts = fieldPath.split('.');
5481
+ let currentType = dataType;
5482
+ for (const fieldName of fieldParts) {
5483
+ if (!currentType) {
5484
+ return { exists: false, missingField: fieldName };
5485
+ }
5486
+ // 获取类型的 properties
5487
+ let properties;
5488
+ if (currentType.typeKind === 'anonymousStructure') {
5489
+ properties = currentType.properties;
5490
+ }
5491
+ else if (currentType.typeKind === 'reference') {
5492
+ // 对于引用类型,需要解析引用
5493
+ const resolved = env.resolveRef(currentType);
5494
+ // @ts-expect-error
5495
+ properties = resolved?.properties;
5496
+ }
5497
+ else if (currentType.typeKind === 'generic' && currentType.typeName === 'List') {
5498
+ // 对于 List<T>,检查 T 的属性
5499
+ currentType = currentType.typeArguments?.[0];
5500
+ if (currentType?.typeKind === 'anonymousStructure') {
5501
+ properties = currentType.properties;
5502
+ }
5503
+ else if (currentType?.typeKind === 'reference') {
5504
+ const resolved = env.resolveRef(currentType);
5505
+ // @ts-expect-error
5506
+ properties = resolved?.properties;
5507
+ }
5508
+ }
5509
+ if (!properties) {
5510
+ // 类型没有 properties,可能是基本类型或未解析的类型
5511
+ // 对于未解析的类型,跳过检查
5512
+ if ((0, type_predicate_1.isTyAnnTyParam)(currentType) || (0, type_predicate_1.isAnyTy)(currentType)) {
5513
+ return { exists: true };
5514
+ }
5515
+ return { exists: false, missingField: fieldName };
5516
+ }
5517
+ const prop = properties.find((p) => p.name === fieldName);
5518
+ if (!prop) {
5519
+ return { exists: false, missingField: fieldName };
5520
+ }
5521
+ // 继续检查下一级
5522
+ currentType = prop.typeAnnotation;
5523
+ }
5524
+ return { exists: true };
5525
+ }
5387
5526
  function deduplicateDiagnostics(diagnostics) {
5388
5527
  return (0, lodash_1.uniqWith)(diagnostics, (a, b) => a.node === b.node && a.message === b.message);
5389
5528
  }