@lcap/nasl-language-server-core 4.1.0-beta.1 → 4.1.0-beta.10

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 (175) hide show
  1. package/README.md +85 -0
  2. package/out/checker.d.ts +1 -1
  3. package/out/checker.d.ts.map +1 -1
  4. package/out/checker.js +172 -56
  5. package/out/checker.js.map +1 -1
  6. package/out/index.d.ts +5 -2
  7. package/out/index.d.ts.map +1 -1
  8. package/out/index.js +9 -2
  9. package/out/index.js.map +1 -1
  10. package/out/module/graph.js +6 -6
  11. package/out/module/graph.js.map +1 -1
  12. package/out/module/module.d.ts.map +1 -1
  13. package/out/module/module.js +3 -6
  14. package/out/module/module.js.map +1 -1
  15. package/out/query/context-variable-query.d.ts +31 -0
  16. package/out/query/context-variable-query.d.ts.map +1 -0
  17. package/out/query/context-variable-query.js +105 -0
  18. package/out/query/context-variable-query.js.map +1 -0
  19. package/out/query/index.d.ts +2 -0
  20. package/out/query/index.d.ts.map +1 -0
  21. package/out/query/index.js +18 -0
  22. package/out/query/index.js.map +1 -0
  23. package/out/reference-manager/builtin-q-name.d.ts +10 -3
  24. package/out/reference-manager/builtin-q-name.d.ts.map +1 -1
  25. package/out/reference-manager/builtin-q-name.js +67 -9
  26. package/out/reference-manager/builtin-q-name.js.map +1 -1
  27. package/out/reference-manager/collect-q-name.d.ts +4 -2
  28. package/out/reference-manager/collect-q-name.d.ts.map +1 -1
  29. package/out/reference-manager/collect-q-name.js +30 -17
  30. package/out/reference-manager/collect-q-name.js.map +1 -1
  31. package/out/reference-manager/get-q-name.d.ts +0 -2
  32. package/out/reference-manager/get-q-name.d.ts.map +1 -1
  33. package/out/reference-manager/get-q-name.js +35 -49
  34. package/out/reference-manager/get-q-name.js.map +1 -1
  35. package/out/reference-manager/reference-manager.d.ts +36 -19
  36. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  37. package/out/reference-manager/reference-manager.js +350 -163
  38. package/out/reference-manager/reference-manager.js.map +1 -1
  39. package/out/reference-manager/remove-q-name.d.ts +31 -28
  40. package/out/reference-manager/remove-q-name.d.ts.map +1 -1
  41. package/out/reference-manager/remove-q-name.js +73 -51
  42. package/out/reference-manager/remove-q-name.js.map +1 -1
  43. package/out/reference-manager/rename-q-name.d.ts +4 -2
  44. package/out/reference-manager/rename-q-name.d.ts.map +1 -1
  45. package/out/reference-manager/rename-q-name.js +43 -36
  46. package/out/reference-manager/rename-q-name.js.map +1 -1
  47. package/out/reference-manager/symbol-type.d.ts +7 -3
  48. package/out/reference-manager/symbol-type.d.ts.map +1 -1
  49. package/out/reference-manager/symbol-type.js +22 -10
  50. package/out/reference-manager/symbol-type.js.map +1 -1
  51. package/out/reference-manager/update-nasl-fragment.d.ts +2 -1
  52. package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
  53. package/out/reference-manager/update-nasl-fragment.js +18 -9
  54. package/out/reference-manager/update-nasl-fragment.js.map +1 -1
  55. package/out/symbol/graph.js +2 -2
  56. package/out/symbol/graph.js.map +1 -1
  57. package/out/symbol/traverse/concepts/index.d.ts +1 -1
  58. package/out/symbol/traverse/concepts/index.d.ts.map +1 -1
  59. package/out/typer/collectGlobalDefs.d.ts +1 -1
  60. package/out/typer/collectGlobalDefs.d.ts.map +1 -1
  61. package/out/typer/collectGlobalDefs.js +81 -17
  62. package/out/typer/collectGlobalDefs.js.map +1 -1
  63. package/out/typer/component-def-manager/component-def-manager.d.ts +50 -12
  64. package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
  65. package/out/typer/component-def-manager/component-def-manager.js +129 -27
  66. package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
  67. package/out/typer/component-def-manager/utils.d.ts.map +1 -1
  68. package/out/typer/component-def-manager/utils.js +50 -15
  69. package/out/typer/component-def-manager/utils.js.map +1 -1
  70. package/out/typer/dispatch-all.d.ts +2 -2
  71. package/out/typer/dispatch-all.d.ts.map +1 -1
  72. package/out/typer/dispatch-all.js +6 -10
  73. package/out/typer/dispatch-all.js.map +1 -1
  74. package/out/typer/dispatch-def.d.ts +1 -3
  75. package/out/typer/dispatch-def.d.ts.map +1 -1
  76. package/out/typer/dispatch-def.js +28 -54
  77. package/out/typer/dispatch-def.js.map +1 -1
  78. package/out/typer/dispatch-expr.d.ts +6 -3
  79. package/out/typer/dispatch-expr.d.ts.map +1 -1
  80. package/out/typer/dispatch-expr.js +341 -226
  81. package/out/typer/dispatch-expr.js.map +1 -1
  82. package/out/typer/dispatch-process.d.ts +0 -1
  83. package/out/typer/dispatch-process.d.ts.map +1 -1
  84. package/out/typer/dispatch-process.js +26 -17
  85. package/out/typer/dispatch-process.js.map +1 -1
  86. package/out/typer/dispatch-stmt.d.ts.map +1 -1
  87. package/out/typer/dispatch-stmt.js +50 -29
  88. package/out/typer/dispatch-stmt.js.map +1 -1
  89. package/out/typer/dispatch-view.d.ts +1 -1
  90. package/out/typer/dispatch-view.d.ts.map +1 -1
  91. package/out/typer/dispatch-view.js +265 -158
  92. package/out/typer/dispatch-view.js.map +1 -1
  93. package/out/typer/helper.js +3 -3
  94. package/out/typer/helper.js.map +1 -1
  95. package/out/typer/incremental-update.d.ts +21 -42
  96. package/out/typer/incremental-update.d.ts.map +1 -1
  97. package/out/typer/incremental-update.js +214 -263
  98. package/out/typer/incremental-update.js.map +1 -1
  99. package/out/typer/index.d.ts +5 -5
  100. package/out/typer/index.d.ts.map +1 -1
  101. package/out/typer/index.js +6 -5
  102. package/out/typer/index.js.map +1 -1
  103. package/out/typer/nasl-predicate.d.ts +1 -1
  104. package/out/typer/nasl-predicate.d.ts.map +1 -1
  105. package/out/typer/overload-helper.d.ts +12 -0
  106. package/out/typer/overload-helper.d.ts.map +1 -0
  107. package/out/typer/overload-helper.js +110 -0
  108. package/out/typer/overload-helper.js.map +1 -0
  109. package/out/typer/sem-diag.d.ts +6 -0
  110. package/out/typer/sem-diag.d.ts.map +1 -1
  111. package/out/typer/sem-diag.js +38 -17
  112. package/out/typer/sem-diag.js.map +1 -1
  113. package/out/typer/solver.d.ts +40 -26
  114. package/out/typer/solver.d.ts.map +1 -1
  115. package/out/typer/solver.js +217 -432
  116. package/out/typer/solver.js.map +1 -1
  117. package/out/typer/subster.d.ts +4 -6
  118. package/out/typer/subster.d.ts.map +1 -1
  119. package/out/typer/subster.js +76 -54
  120. package/out/typer/subster.js.map +1 -1
  121. package/out/typer/topo-sort.d.ts.map +1 -1
  122. package/out/typer/topo-sort.js +9 -2
  123. package/out/typer/topo-sort.js.map +1 -1
  124. package/out/typer/type-hint-manager/type-hint-manager.d.ts +5 -2
  125. package/out/typer/type-hint-manager/type-hint-manager.d.ts.map +1 -1
  126. package/out/typer/type-hint-manager/type-hint-manager.js +6 -4
  127. package/out/typer/type-hint-manager/type-hint-manager.js.map +1 -1
  128. package/out/typer/type-manager.d.ts +9 -3
  129. package/out/typer/type-manager.d.ts.map +1 -1
  130. package/out/typer/type-manager.js +64 -22
  131. package/out/typer/type-manager.js.map +1 -1
  132. package/out/typer/type-predicate.d.ts +17 -2
  133. package/out/typer/type-predicate.d.ts.map +1 -1
  134. package/out/typer/type-predicate.js +124 -36
  135. package/out/typer/type-predicate.js.map +1 -1
  136. package/out/typer/typer.d.ts +50 -8
  137. package/out/typer/typer.d.ts.map +1 -1
  138. package/out/typer/typer.js +110 -78
  139. package/out/typer/typer.js.map +1 -1
  140. package/out/typer/unifier.d.ts +0 -1
  141. package/out/typer/unifier.d.ts.map +1 -1
  142. package/out/typer/unifier.js +111 -85
  143. package/out/typer/unifier.js.map +1 -1
  144. package/out/utils/error-boundary.d.ts.map +1 -1
  145. package/out/utils/error-boundary.js +5 -11
  146. package/out/utils/error-boundary.js.map +1 -1
  147. package/out/utils/file-node-cache.d.ts +12 -0
  148. package/out/utils/file-node-cache.d.ts.map +1 -0
  149. package/out/utils/file-node-cache.js +30 -0
  150. package/out/utils/file-node-cache.js.map +1 -0
  151. package/out/utils/nasl-type-manipulation.d.ts +1 -0
  152. package/out/utils/nasl-type-manipulation.d.ts.map +1 -1
  153. package/out/utils/nasl-type-manipulation.js +3 -1
  154. package/out/utils/nasl-type-manipulation.js.map +1 -1
  155. package/out/utils/parseTsClassType.d.ts +4 -3
  156. package/out/utils/parseTsClassType.d.ts.map +1 -1
  157. package/out/utils/parseTsClassType.js +37 -61
  158. package/out/utils/parseTsClassType.js.map +1 -1
  159. package/out/utils/string.d.ts +4 -0
  160. package/out/utils/string.d.ts.map +1 -0
  161. package/out/utils/string.js +29 -0
  162. package/out/utils/string.js.map +1 -0
  163. package/out/utils/type-operator.d.ts +7 -7
  164. package/out/utils/type-operator.d.ts.map +1 -1
  165. package/out/utils/type-operator.js +72 -35
  166. package/out/utils/type-operator.js.map +1 -1
  167. package/package.json +18 -9
  168. package/out/utils/vue-hack.d.ts +0 -25
  169. package/out/utils/vue-hack.d.ts.map +0 -1
  170. package/out/utils/vue-hack.js +0 -33
  171. package/out/utils/vue-hack.js.map +0 -1
  172. package/out/utils/vue.d.ts +0 -2
  173. package/out/utils/vue.d.ts.map +0 -1
  174. package/out/utils/vue.js +0 -10
  175. package/out/utils/vue.js.map +0 -1
package/README.md CHANGED
@@ -1,3 +1,88 @@
1
1
  # Nasl Language Server
2
2
 
3
3
  Nasl 语言服务
4
+
5
+ ## 描述
6
+
7
+ NetEase Application Specific Language (NASL) 语言服务器核心包,提供 NASL 语言的类型检查、语法分析和其他语言服务功能。
8
+
9
+ ## 技术栈
10
+
11
+ ### 核心技术
12
+ - **TypeScript 5.4.4** - 主要开发语言
13
+ - **Node.js 18+** - 运行环境
14
+
15
+ ### 主要依赖
16
+ - **@lcap/nasl-concepts** - NASL 概念定义
17
+ - **@lcap/nasl-types** - NASL 类型系统
18
+ - **@lcap/nasl-utils** - NASL 工具库
19
+ - **decimal.js** - 精确数值计算
20
+ - **json5** - JSON5 格式支持
21
+ - **lodash** - 实用工具库
22
+ - **mnemonist** - 数据结构库
23
+
24
+ ### 开发工具
25
+ - **Vitest 3.2.4** - 现代测试框架
26
+ - **Chai 4.3.7** - 断言库
27
+ - **Mocha** - 传统测试框架(通过 @lcap/nasl-test-toolkit)
28
+
29
+ ## 开发
30
+
31
+ ### 构建
32
+ ```bash
33
+ # 清理输出目录
34
+ npm run clear
35
+
36
+ # 构建项目
37
+ npm run build
38
+
39
+ # 监听模式构建
40
+ npm run watch
41
+ ```
42
+
43
+ ### 测试
44
+
45
+ #### Vitest 测试(推荐)
46
+ ```bash
47
+ # 运行所有 Vitest 测试
48
+ npm run test:vite
49
+
50
+ # 监听模式运行测试
51
+ npm run test:watch
52
+
53
+ # 启动测试 UI 界面
54
+ npm run test:ui
55
+ ```
56
+
57
+ #### Mocha 测试 (遗留)
58
+
59
+ 注意:
60
+ - Mocha 测试框架已经废弃,对于新的单元测试的编写,请使用 Vitest 测试框架。
61
+ - Mocha 测试框架的测试用例,请迁移到 Vitest 测试框架。请参考 [TESTING_MIGRATION.md](./tests/TESTING_MIGRATION.md) 文件,让LLM自动化地完成迁移。
62
+
63
+ ```bash
64
+ # 运行标准 Mocha 测试套件
65
+ npm run test
66
+
67
+ # 运行应用测试
68
+ npm run test:apps
69
+
70
+ # 运行 CI 测试
71
+ npm run test:ci
72
+
73
+ # 更新测试快照
74
+ npm run test:update
75
+
76
+ # 运行性能测试
77
+ npm run test:perf
78
+ ```
79
+
80
+ ### 其他工具
81
+ ```bash
82
+ # 压缩测试数据
83
+ npm run compress-test-data
84
+ ```
85
+
86
+ ## 许可证
87
+
88
+ MIT
package/out/checker.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { SyntaxNode, App, BaseNode } from '@lcap/nasl-concepts';
2
2
  import { TypeAnnotation } from '@lcap/nasl-concepts';
3
- import { type SemEnv } from './typer';
3
+ import { type SemEnv } from './typer/typer';
4
4
  import { Diagnostic as NaslTypeDiagnostic } from '@lcap/nasl-types';
5
5
  export declare enum Severity {
6
6
  WARN = "warning",
@@ -1 +1 @@
1
- {"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../src/checker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAU0F,GAAG,EAMvG,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACgE,cAAc,EAGpF,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAIhE,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEpE,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;AAiQF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe;oCAgiIpB,OAAO;sDAPW,gBAAgB,EAAE;;;;sBAhBjD,UAAU,GAAG,SAAS;;;8BAsCf,UAAU;2BAuBb,UAAU;;kBA9gInB,UAAU,WAAW,MAAM,YAAY,YAAY;EAgiIzE;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;AAED,eAAO,MAAM,6BAA6B,aAAc,UAAU,sCAAoC,MAAM,gBAAgB,CAmC3H,CAAA;AAMD,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,EAU0F,GAAG,EAMvG,QAAQ,EACT,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;AAMpE,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;AAiQF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe;oCAsoIpB,OAAO;sDAPW,gBAAgB,EAAE;;;;sBAhBjD,UAAU,GAAG,SAAS;;;8BA4Df,UAAU;2BAuBb,UAAU;;kBA1oInB,UAAU,WAAW,MAAM,YAAY,YAAY;EA4pIzE;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;AAED,eAAO,MAAM,6BAA6B,aAAc,UAAU,sCAAoC,MAAM,gBAAgB,CAmC3H,CAAA;AAMD,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
package/out/checker.js CHANGED
@@ -4,11 +4,13 @@ exports.transformDiagnosticsToRecords = exports.createErrorDiagnoser = exports.S
4
4
  const decimal_js_1 = require("decimal.js");
5
5
  const nasl_concepts_1 = require("@lcap/nasl-concepts");
6
6
  const service_1 = require("@lcap/nasl-concepts/service");
7
+ const file_node_cache_1 = require("./utils/file-node-cache");
7
8
  const nasl_utils_1 = require("@lcap/nasl-utils");
8
- const typer_1 = require("./typer");
9
+ const sem_diag_1 = require("./typer/sem-diag");
9
10
  const type_predicate_1 = require("./typer/type-predicate");
10
11
  const type_manager_1 = require("./typer/type-manager");
11
12
  const nasl_predicate_1 = require("./typer/nasl-predicate");
13
+ const helper_1 = require("./typer/helper");
12
14
  var Severity;
13
15
  (function (Severity) {
14
16
  Severity["WARN"] = "warning";
@@ -91,7 +93,7 @@ function getExpressionNodeName(concept) {
91
93
  function isDescendant(node, rangeNode) {
92
94
  let currentNode = node;
93
95
  while (currentNode) {
94
- if (currentNode === rangeNode) {
96
+ if (toRaw(currentNode) === toRaw(rangeNode)) {
95
97
  return true;
96
98
  }
97
99
  currentNode = currentNode.parentNode;
@@ -332,11 +334,20 @@ function createErrorDiagnoser(context) {
332
334
  currentNode = currentNode.parentNode;
333
335
  }
334
336
  const finalNode = memberExpression ?? node;
335
- (0, typer_1.createOnPush)(diagnostics, finalNode, diagnostic);
337
+ (0, helper_1.createOnPush)(diagnostics, finalNode, diagnostic);
336
338
  finalNode.tsErrorDetail = diagnostic;
337
339
  }
338
340
  else { }
339
341
  }
342
+ function scopedError(node, message, context) {
343
+ const scope = node?.constructor?.nodeTitle;
344
+ if (scope) {
345
+ error(node, `${scope}:${message}`, context);
346
+ }
347
+ else {
348
+ error(node, message, context);
349
+ }
350
+ }
340
351
  /**
341
352
  * 获取当前错误信息
342
353
  * @param node
@@ -671,7 +682,7 @@ function createErrorDiagnoser(context) {
671
682
  // 允许在当前业务组件中访问
672
683
  businessComponent,
673
684
  ],
674
- errMsg: `“${node.name}”是私有的,只能在“${businessComponent.name}”中访问。`,
685
+ errMsg: `"${node.name}"是私有的,只能在"${businessComponent.name}"中访问。`,
675
686
  } : null;
676
687
  case 'ConfigProperty':
677
688
  return node.isPrivate ? {
@@ -690,7 +701,7 @@ function createErrorDiagnoser(context) {
690
701
  * @returns
691
702
  */
692
703
  function isNonRequiredParam(param) {
693
- return param?.defaultValue?.expression || param?.defaultExpression || param?.optional || param?.spread || (nasl_concepts_1.asserts.isInterfaceParam(param) && !param.required);
704
+ return param?.defaultValue?.expression || param?.defaultExpression || param?.optional || (nasl_concepts_1.asserts.isInterfaceParam(param) && !param.required);
694
705
  }
695
706
  /**
696
707
  * 确定函数签名中所需的最小参数数量
@@ -700,6 +711,9 @@ function createErrorDiagnoser(context) {
700
711
  let minArgsCount = 0;
701
712
  for (let i = 0; i < paramLen; i++) {
702
713
  const param = params[i];
714
+ if (param?.spread) {
715
+ continue;
716
+ }
703
717
  if (!isNonRequiredParam(param)) {
704
718
  minArgsCount++; // 如果参数有默认值,则跳过
705
719
  }
@@ -802,7 +816,7 @@ function createErrorDiagnoser(context) {
802
816
  /**
803
817
  * 检查 调用表达式的参数
804
818
  * @param node
805
- * @param ref
819
+ *( @param r) as anyef
806
820
  */
807
821
  function* checkCallExpressionParameters(node, ref) {
808
822
  // Handle both TypeAnnotation and FunctionDefinition formats
@@ -822,13 +836,17 @@ function createErrorDiagnoser(context) {
822
836
  }
823
837
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(args, function* (arg, index) {
824
838
  const param = params?.[index];
825
- if (!param)
826
- return;
827
- const isParamRequired = !(hasSpreadParam && index > spreadParamIndex) && !isNonRequiredParam(param);
839
+ // param 的定义不存在,则默认是必填的。
840
+ const isParamRequired = param ? !isNonRequiredParam(param) : true;
828
841
  arg.paramRequired = isParamRequired;
842
+ // 即便是 param 的定义不存在,也需要检查 arg。这样可以检查出 arg 是否引用了一些未定义的变量
843
+ const argType = yield* checkNode(arg);
844
+ if (!param) {
845
+ return;
846
+ }
829
847
  const paramType = param.typeAnnotation ??
830
848
  (nasl_concepts_1.asserts.isTypeAnnotation(param) ? param : env.getType(param));
831
- const argType = yield* checkNode(arg);
849
+ // 检查高阶函数参数个数是否匹配
832
850
  if (paramType?.typeKind === 'function' && argType?.typeKind === 'function') {
833
851
  const argTypeArgs = argType?.typeArguments || [];
834
852
  const paramTypeArgs = paramType?.typeArguments || [];
@@ -926,12 +944,11 @@ function createErrorDiagnoser(context) {
926
944
  const type = yield* checkNode(node);
927
945
  if (isUnresolvedType(type)) {
928
946
  const scope = node?.constructor?.nodeTitle;
929
- if (node.concept === 'Identifier') {
930
- error(node, `${scope}:${node.name} 未定义。`);
931
- }
932
- else {
933
- error(node, `${scope}:所选择的内容未定义。`);
934
- }
947
+ // if (node.concept === 'Identifier') {
948
+ // error(node, `${scope}:${node.name} 未定义。`);
949
+ // } else {
950
+ error(node, `${scope}:所选择的内容未定义。`);
951
+ // }
935
952
  return errorType;
936
953
  }
937
954
  return type;
@@ -1094,8 +1111,8 @@ function createErrorDiagnoser(context) {
1094
1111
  const status = getStatusOfSharedApp(node);
1095
1112
  if (status) {
1096
1113
  const msgMap = {
1097
- update: `共享数据 ${node.name} 已在“${node.provider}应用”中更新,请同步更新`,
1098
- delete: `共享数据 ${node.name} 已在“${node.provider}应用”中被删除,请同步删除`,
1114
+ update: `共享数据 ${node.name} 已在"${node.provider}应用"中更新,请同步更新`,
1115
+ delete: `共享数据 ${node.name} 已在"${node.provider}应用"中被删除,请同步删除`,
1099
1116
  };
1100
1117
  error(node, msgMap[status], {
1101
1118
  severity: Severity.WARN,
@@ -1219,13 +1236,14 @@ function createErrorDiagnoser(context) {
1219
1236
  }
1220
1237
  }
1221
1238
  /**
1222
- * 检查 变量
1239
+ * 检查【局部】变量
1223
1240
  * @param node
1224
1241
  */
1225
1242
  function* checkVariable(node) {
1226
1243
  yield* checkNode(node.defaultValue);
1227
1244
  // 前面加了报错,省点时间,报错不用那么精确
1228
1245
  // yield* checkVariableType(node);
1246
+ yield* checkNode(node.typeAnnotation);
1229
1247
  }
1230
1248
  /**
1231
1249
  * 检查 前端全局变量
@@ -1720,6 +1738,7 @@ function createErrorDiagnoser(context) {
1720
1738
  yield* checkNode(node.defaultValue);
1721
1739
  // 前面加了报错,省点时间,报错不用那么精确
1722
1740
  // yield* checkVariableType(node);
1741
+ yield* checkNode(node.typeAnnotation);
1723
1742
  }
1724
1743
  /**
1725
1744
  * 检查 接口
@@ -1866,6 +1885,7 @@ function createErrorDiagnoser(context) {
1866
1885
  ...(node.variables || []),
1867
1886
  ...(node.logics || []),
1868
1887
  ]);
1888
+ checkVariableAndReturnTypeAnnotations(node.variables, [], false);
1869
1889
  const module = node.getAncestor('Module');
1870
1890
  if (!(module?.parentKey === 'dependencies')) {
1871
1891
  if (node.params?.length) {
@@ -1996,6 +2016,21 @@ function createErrorDiagnoser(context) {
1996
2016
  if (node._foldInView) {
1997
2017
  error(node, `组件${node.name}已经极速折叠`);
1998
2018
  }
2019
+ // 已知:选择器会漏报,因为 children 里是两个空 template。暂时先这样吧。
2020
+ let dsFilled = true;
2021
+ let errNode = node;
2022
+ const ds = node.bindAttrs.find(nd => nd.name === 'dataSource');
2023
+ if (ds) {
2024
+ if (ds.type === 'dynamic' && !ds.expression) {
2025
+ dsFilled = false;
2026
+ errNode = ds;
2027
+ }
2028
+ }
2029
+ const hasSubComponents = node.children.filter(c => c.tag !== 'template').length > 0 ||
2030
+ node.children.filter(c => c.tag === 'template').some(cc => cc.children.length > 0);
2031
+ if (!dsFilled && !hasSubComponents) {
2032
+ error(errNode, '数据源不能为空');
2033
+ }
1999
2034
  unbindVariables?.();
2000
2035
  }
2001
2036
  /**
@@ -2256,7 +2291,8 @@ function createErrorDiagnoser(context) {
2256
2291
  yield* checkNode(node.bind);
2257
2292
  if (node.processDefinitions?.length) {
2258
2293
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.processDefinitions, function* (node) {
2259
- yield* checkNode(node);
2294
+ // 现有流程版本 [v1, v2],加个 v3 后,变成了 [proxy(v1), proxy(v2), v3],无法理解
2295
+ yield* checkNode(toRaw(node));
2260
2296
  });
2261
2297
  }
2262
2298
  if (node?.subLogics?.length) {
@@ -2432,7 +2468,7 @@ function createErrorDiagnoser(context) {
2432
2468
  const prop = getPropertyOfType(type, propertyName);
2433
2469
  if (!prop) {
2434
2470
  const scope = item?.constructor?.nodeTitle;
2435
- error(item, `${scope}:找不到 ${type?.typeTitle} 上的 ${propertyName}。`);
2471
+ error(item, `${scope}:找不到 ${(0, type_manager_1.showUserLevelType)(type)} 上的 ${propertyName}。`);
2436
2472
  }
2437
2473
  type = env.getType(prop);
2438
2474
  if (type?.typeKind === 'generic' && type.typeName === 'List') {
@@ -2460,6 +2496,10 @@ function createErrorDiagnoser(context) {
2460
2496
  ...(node.variables || []),
2461
2497
  ...(node.virtualParams || [])
2462
2498
  ]);
2499
+ // 仅检查用户写的逻辑
2500
+ // if (node.nodePath?.startsWith('app.logics')) {
2501
+ checkVariableAndReturnTypeAnnotations(node.variables ?? [], node.returns ?? []);
2502
+ // }
2463
2503
  const module = node.getAncestor('Module');
2464
2504
  if (!(module?.parentKey === 'dependencies')) {
2465
2505
  if (node.params?.length) {
@@ -2640,6 +2680,9 @@ function createErrorDiagnoser(context) {
2640
2680
  ...(node.returns || []),
2641
2681
  ...(node.variables || []),
2642
2682
  ]);
2683
+ // if (nd.nodePath?.startsWith('app.logics')) {
2684
+ checkVariableAndReturnTypeAnnotations(node.variables, node.returns);
2685
+ // }
2643
2686
  const module = node.getAncestor('Module');
2644
2687
  if (!(module?.parentKey === 'dependencies')) {
2645
2688
  if (node.params?.length) {
@@ -2730,22 +2773,27 @@ function createErrorDiagnoser(context) {
2730
2773
  return;
2731
2774
  }
2732
2775
  yield* checkVoidCallUsedAsStatement(node);
2733
- const ref = env.resolvedCallInfo.get(node) ?? env.resolveRef(node);
2734
- // Handle the new FunctionDefinition structure
2735
- if (ref?.params && !(0, type_manager_1.hasUnresolvedTyInCallInfo)(ref)) {
2736
- // It's a FunctionDefinition object
2737
- yield* checkScopeOfUse(node, ref);
2738
- yield* checkCallExpressionParameters(node, ref);
2739
- }
2740
- else if (ref && !(0, type_predicate_1.isUnResolvedTy)(ref)) {
2741
- // 检查使用范围
2742
- yield* checkScopeOfUse(node, ref);
2743
- yield* checkCallExpressionParameters(node, ref);
2744
- }
2745
- else {
2746
- error(node, `找不到${getExpressionNodeName(node.concept)} ${node.calleeName}。`);
2776
+ const ref = env.resolveRef(node); // 前端
2777
+ // TODO: sql 函数的 namespace 带有数据库名 nasl.sqlFunction.mysql nasl.sqlFunction.oracle ...
2778
+ // 暂时不在 qNameDefs 里,用 isBuiltInCall 简单判断了
2779
+ if (!ref && !isBuiltInCall(node)) {
2780
+ const depLibName = getExtensionLibName(node);
2781
+ if (depLibName) {
2782
+ error(node, `找不到依赖库 ${depLibName} 上的 ${getExpressionNodeName(node.concept)} ${node.calleeName}。`);
2783
+ }
2784
+ else {
2785
+ error(node, `找不到${getExpressionNodeName(node.concept)} ${node.calleeName}。`);
2786
+ }
2747
2787
  return errorType;
2748
2788
  }
2789
+ /**
2790
+ * 目前的 callInfo:所有内置函数 + 服务端调用。前端因为有组件库调用,还没统一
2791
+ * 排除未求解出类型变元等引发的报错,这些不应该报 '找不到'
2792
+ */
2793
+ // FIXME: wudengke 帮帮忙,行行好
2794
+ const callInfo = env.resolvedCallInfo.get(node);
2795
+ yield* checkScopeOfUse(node, (callInfo ?? ref));
2796
+ yield* checkCallExpressionParameters(node, (callInfo ?? ref));
2749
2797
  switch (node.concept) {
2750
2798
  case 'CallFunction':
2751
2799
  return yield* checkCallFunction(node);
@@ -2769,6 +2817,9 @@ function createErrorDiagnoser(context) {
2769
2817
  if (node.calleeName === 'Clear' && type?.typeKind === 'union') {
2770
2818
  error(node, `传入类型错误,接收类型:非union类型`);
2771
2819
  }
2820
+ if (node.calleeName === 'ListSort' || node.calleeName === 'ListSortAsync') {
2821
+ checkListSort(node);
2822
+ }
2772
2823
  if (node.typeArguments?.length) {
2773
2824
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.typeArguments, function* (node) {
2774
2825
  yield* checkNode(node);
@@ -2812,6 +2863,23 @@ function createErrorDiagnoser(context) {
2812
2863
  }
2813
2864
  }
2814
2865
  return type;
2866
+ function checkListSort(nd) {
2867
+ for (let i = 1; i < nd.arguments.length; i++) {
2868
+ const expr = nd.arguments[i].expression;
2869
+ let resTy;
2870
+ if (expr?.concept === 'AnonymousFunction') {
2871
+ resTy = env.getType(expr.body);
2872
+ }
2873
+ else if (expr?.concept === 'SubLogic') {
2874
+ resTy = env.getType(expr.returns?.[0]);
2875
+ }
2876
+ const byTy = resTy?.properties?.find((prop) => prop.name === 'by')?.typeAnnotation;
2877
+ if (byTy?.typeKind === 'union') {
2878
+ // 这里使用 node.arguments[i] 则无红框,猜测是 ListSort 的特殊交互导致的问题
2879
+ error(node, (0, sem_diag_1.mkIncompatibleTyErr)(env, byTy, '非 union 的基础类型:如字符串、整数、布尔等'));
2880
+ }
2881
+ }
2882
+ }
2815
2883
  }
2816
2884
  /**
2817
2885
  * 检查 调用逻辑
@@ -3118,18 +3186,29 @@ function createErrorDiagnoser(context) {
3118
3186
  }
3119
3187
  });
3120
3188
  }
3189
+ else if (!isOtherCase(node)) {
3190
+ // pattern 为空时,如果不是其他就报错
3191
+ error(node, '匹配分支:匹配模式不能为空', {
3192
+ titleTip: '匹配模式不能为空',
3193
+ });
3194
+ }
3121
3195
  if (node.body?.length) {
3122
3196
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.body, function* (node) {
3123
3197
  yield* checkNode(node);
3124
3198
  });
3125
3199
  }
3126
- if (match?.isExpression && node.body.length === 0) {
3127
- // 如果不是其他就标红
3128
- if (node?.getIndexOfParent() !== (match?.cases?.length || 0) - 1) {
3129
- error(node, '匹配分支:返回内容不能为空', {
3130
- titleTip: '返回内容不能为空',
3131
- });
3200
+ if (match?.isExpression && node.body.length === 0 && !isOtherCase(node)) {
3201
+ // 如果不是其他就报错
3202
+ error(node, '匹配分支:返回内容不能为空', {
3203
+ titleTip: '返回内容不能为空',
3204
+ });
3205
+ }
3206
+ function isOtherCase(node) {
3207
+ const indexInParent = node.getIndexOfParent();
3208
+ if (indexInParent === -1) {
3209
+ return false;
3132
3210
  }
3211
+ return indexInParent === match.cases.length - 1;
3133
3212
  }
3134
3213
  }
3135
3214
  /**
@@ -3219,21 +3298,13 @@ function createErrorDiagnoser(context) {
3219
3298
  /**
3220
3299
  * 参考类型检查器的 {@link tpIdentifier}方法
3221
3300
  */
3222
- return typer_1.naslLongTy;
3301
+ return type_manager_1.naslLongTy;
3223
3302
  }
3224
3303
  else if (node.name === 'it') {
3225
3304
  return env.getType(node);
3226
3305
  }
3227
3306
  else {
3228
3307
  const { name } = node;
3229
- // 之前有一些脏数据,先兼容
3230
- // if (['true', 'false'].includes(name)) {
3231
- // return new TypeAnnotation({
3232
- // typeKind: 'primitive',
3233
- // typeName: 'Boolean',
3234
- // typeNamespace: 'nasl.core',
3235
- // });
3236
- // }
3237
3308
  if (
3238
3309
  // name 是 A.B.C
3239
3310
  name?.split('.')?.length > 1
@@ -3248,6 +3319,13 @@ function createErrorDiagnoser(context) {
3248
3319
  return errorType;
3249
3320
  }
3250
3321
  }
3322
+ if (node.namespace === 'app.enums' &&
3323
+ node.parentNode?.concept !== 'MemberExpression' &&
3324
+ node.parentNode?.concept !== 'SelectMembers') {
3325
+ // 判断枚举类是否直接被使用
3326
+ scopedError(node, `${node.toNaturalTS()} 枚举类不能直接使用,请取它的枚举项`);
3327
+ return errorType;
3328
+ }
3251
3329
  // 检查使用范围
3252
3330
  yield* checkScopeOfUse(node, ref);
3253
3331
  return env.getType(node);
@@ -3276,7 +3354,7 @@ function createErrorDiagnoser(context) {
3276
3354
  }
3277
3355
  else {
3278
3356
  const scope = node?.constructor?.nodeTitle;
3279
- error(node, `${scope}:找不到 ${type?.typeTitle} 上的 ${nodeProperty?.name}。`);
3357
+ error(node, `${scope}:找不到 ${(0, type_manager_1.showUserLevelType)(type)} 上的 ${nodeProperty?.name}。`);
3280
3358
  return errorType;
3281
3359
  }
3282
3360
  return env.getType(node);
@@ -3428,7 +3506,7 @@ function createErrorDiagnoser(context) {
3428
3506
  }
3429
3507
  else {
3430
3508
  const scope = property?.constructor?.nodeTitle;
3431
- error(property, `${scope}:找不到 ${type?.typeTitle} 上的 ${propertyName}。`);
3509
+ error(property, `${scope}:找不到 ${(0, type_manager_1.showUserLevelType)(type)} 上的 ${propertyName}。`);
3432
3510
  }
3433
3511
  });
3434
3512
  }
@@ -3481,7 +3559,7 @@ function createErrorDiagnoser(context) {
3481
3559
  if (ensureNodeKeyExists(node, 'members')) {
3482
3560
  if (node.members?.length) {
3483
3561
  yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.members, function* (node) {
3484
- yield* checkNode(node);
3562
+ yield* checkNode(toRaw(node));
3485
3563
  });
3486
3564
  }
3487
3565
  }
@@ -3776,6 +3854,18 @@ function createErrorDiagnoser(context) {
3776
3854
  }
3777
3855
  return env.getType(node);
3778
3856
  }
3857
+ function* checkVariadicExpression(node) {
3858
+ if (!node.expressions?.[0]) {
3859
+ error(node, '表达式不能为空!');
3860
+ }
3861
+ if (!node.expressions?.[1]) {
3862
+ error(node, '表达式不能为空!');
3863
+ }
3864
+ yield* (0, nasl_utils_1.wrapForEachToGenerator)(node.expressions, function* (node) {
3865
+ yield* checkNode(node);
3866
+ });
3867
+ return env.getType(node);
3868
+ }
3779
3869
  /**
3780
3870
  * 检查 一元表达式
3781
3871
  * @param node
@@ -3883,7 +3973,7 @@ function createErrorDiagnoser(context) {
3883
3973
  }
3884
3974
  // 元数据
3885
3975
  if (!metadataTypeEnable && node.typeNamespace?.endsWith('.metadataTypes')) {
3886
- error(node, '未启用元数据功能,请在“偏好设置”中启用元数据。');
3976
+ error(node, '未启用元数据功能,请在"偏好设置"中启用元数据。');
3887
3977
  }
3888
3978
  if (node.typeArguments?.length) {
3889
3979
  // 有同名的
@@ -4165,6 +4255,8 @@ function createErrorDiagnoser(context) {
4165
4255
  return yield* checkPaginate(node);
4166
4256
  case 'BinaryExpression':
4167
4257
  return yield* checkBinaryExpression(node);
4258
+ case 'VariadicExpression':
4259
+ return yield* checkVariadicExpression(node);
4168
4260
  case 'UnaryExpression':
4169
4261
  return yield* checkUnaryExpression(node);
4170
4262
  case 'Comment':
@@ -4201,8 +4293,8 @@ function createErrorDiagnoser(context) {
4201
4293
  * @returns 清理函数
4202
4294
  */
4203
4295
  function handleFileNode(node) {
4204
- // TODO: checkNodeIsFileModuleInIde 也慢,后续可以优化
4205
- const isFileModule = fileNodes.length ? (0, service_1.checkNodeIsFileModuleInIde)(node) : true;
4296
+ // TODO: checkNodeIsFileModuleInIdeWithCache 也慢,后续可以优化
4297
+ const isFileModule = fileNodes.length ? (0, file_node_cache_1.checkNodeIsFileModuleInIdeWithCache)(node) : true;
4206
4298
  if (isFileModule) {
4207
4299
  fileNodes.push(node);
4208
4300
  let diagnostics = diagnosticMap.get(node);
@@ -4244,6 +4336,26 @@ function createErrorDiagnoser(context) {
4244
4336
  function setMetadataTypeEnable(enable) {
4245
4337
  metadataTypeEnable = enable;
4246
4338
  }
4339
+ const checkVariableAndReturnTypeAnnotations = (variables, returns, inLogic = true) => {
4340
+ for (const v of variables) {
4341
+ if (v.typeAnnotation)
4342
+ continue;
4343
+ const tyAnn = v.__TypeAnnotation;
4344
+ if (!(0, type_predicate_1.isResolvedUserTy)(tyAnn)) {
4345
+ error(v, `局部变量 ${v.name} 未设置类型,在非草稿区正常使用可自动推断类型`);
4346
+ v.__TypeAnnotation = undefined;
4347
+ }
4348
+ }
4349
+ for (const r of returns) {
4350
+ if (r.typeAnnotation)
4351
+ continue;
4352
+ const tyAnn = r.__TypeAnnotation;
4353
+ if (!(0, type_predicate_1.isResolvedUserTy)(tyAnn)) {
4354
+ error(r, `输出参数 ${r.name} 未设置类型,在非草稿区正常使用可自动推断类型`);
4355
+ r.__TypeAnnotation = undefined;
4356
+ }
4357
+ }
4358
+ };
4247
4359
  /**
4248
4360
  * 诊断App
4249
4361
  * @param app
@@ -4335,4 +4447,8 @@ const transformDiagnosticsToRecords = (fileNode, diagnostics) => {
4335
4447
  exports.transformDiagnosticsToRecords = transformDiagnosticsToRecords;
4336
4448
  // @ts-expect-error
4337
4449
  const toRaw = (nd) => nd.__v_raw ?? nd;
4450
+ // 是否来自系统内置
4451
+ const isBuiltInCall = (nd) => nd.calleeNamespace.startsWith('nasl.');
4452
+ // 是否来自依赖库
4453
+ const getExtensionLibName = (nd) => nd.calleeNamespace.startsWith('extensions.') ? nd.calleeNamespace.split('.')[1] : undefined;
4338
4454
  //# sourceMappingURL=checker.js.map