@lcap/nasl-language-server-core 4.4.0-beta.3 → 4.4.0-beta.31

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 (142) hide show
  1. package/out/checker.d.ts +4 -1
  2. package/out/checker.d.ts.map +1 -1
  3. package/out/checker.js +996 -96
  4. package/out/checker.js.map +1 -1
  5. package/out/index.d.ts +1 -1
  6. package/out/index.d.ts.map +1 -1
  7. package/out/index.js +5 -3
  8. package/out/index.js.map +1 -1
  9. package/out/reference-manager/build-q-name-def.d.ts.map +1 -1
  10. package/out/reference-manager/build-q-name-def.js +11 -0
  11. package/out/reference-manager/build-q-name-def.js.map +1 -1
  12. package/out/reference-manager/builtin-q-name.js +2 -2
  13. package/out/reference-manager/builtin-q-name.js.map +1 -1
  14. package/out/reference-manager/collect-q-name.d.ts +1 -1
  15. package/out/reference-manager/collect-q-name.d.ts.map +1 -1
  16. package/out/reference-manager/collect-q-name.js +64 -27
  17. package/out/reference-manager/collect-q-name.js.map +1 -1
  18. package/out/reference-manager/def-key-helpers.d.ts +38 -0
  19. package/out/reference-manager/def-key-helpers.d.ts.map +1 -0
  20. package/out/reference-manager/{get-q-name.js → def-key-helpers.js} +195 -23
  21. package/out/reference-manager/def-key-helpers.js.map +1 -0
  22. package/out/reference-manager/helper.js +2 -2
  23. package/out/reference-manager/helper.js.map +1 -1
  24. package/out/reference-manager/reference-manager.d.ts +146 -47
  25. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  26. package/out/reference-manager/reference-manager.js +632 -204
  27. package/out/reference-manager/reference-manager.js.map +1 -1
  28. package/out/reference-manager/remove-q-name.d.ts +1 -1
  29. package/out/reference-manager/remove-q-name.d.ts.map +1 -1
  30. package/out/reference-manager/remove-q-name.js +14 -14
  31. package/out/reference-manager/remove-q-name.js.map +1 -1
  32. package/out/reference-manager/rename-q-name.d.ts +26 -26
  33. package/out/reference-manager/rename-q-name.d.ts.map +1 -1
  34. package/out/reference-manager/rename-q-name.js +48 -167
  35. package/out/reference-manager/rename-q-name.js.map +1 -1
  36. package/out/reference-manager/symbol-type.d.ts +8 -3
  37. package/out/reference-manager/symbol-type.d.ts.map +1 -1
  38. package/out/reference-manager/symbol-type.js +9 -2
  39. package/out/reference-manager/symbol-type.js.map +1 -1
  40. package/out/reference-manager/update-nasl-fragment.d.ts +2 -2
  41. package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
  42. package/out/reference-manager/update-nasl-fragment.js +33 -28
  43. package/out/reference-manager/update-nasl-fragment.js.map +1 -1
  44. package/out/services/bindable-logic-service.js.map +1 -1
  45. package/out/symbol/traverse/concepts/index.d.ts +1 -1
  46. package/out/symbol/traverse/concepts/index.d.ts.map +1 -1
  47. package/out/symbol/traverse/concepts/logic/expression/member-expression.js.map +1 -1
  48. package/out/typer/collectGlobalDefs.d.ts +8 -0
  49. package/out/typer/collectGlobalDefs.d.ts.map +1 -1
  50. package/out/typer/collectGlobalDefs.js +102 -54
  51. package/out/typer/collectGlobalDefs.js.map +1 -1
  52. package/out/typer/component-def-manager/component-def-manager.d.ts +16 -0
  53. package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
  54. package/out/typer/component-def-manager/component-def-manager.js +63 -2
  55. package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
  56. package/out/typer/component-def-manager/utils.d.ts.map +1 -1
  57. package/out/typer/component-def-manager/utils.js +26 -0
  58. package/out/typer/component-def-manager/utils.js.map +1 -1
  59. package/out/typer/dispatch-all.d.ts +3 -1
  60. package/out/typer/dispatch-all.d.ts.map +1 -1
  61. package/out/typer/dispatch-all.js +51 -6
  62. package/out/typer/dispatch-all.js.map +1 -1
  63. package/out/typer/dispatch-call.d.ts +27 -1
  64. package/out/typer/dispatch-call.d.ts.map +1 -1
  65. package/out/typer/dispatch-call.js +151 -107
  66. package/out/typer/dispatch-call.js.map +1 -1
  67. package/out/typer/dispatch-def.d.ts.map +1 -1
  68. package/out/typer/dispatch-def.js +51 -23
  69. package/out/typer/dispatch-def.js.map +1 -1
  70. package/out/typer/dispatch-expr.d.ts +2 -1
  71. package/out/typer/dispatch-expr.d.ts.map +1 -1
  72. package/out/typer/dispatch-expr.js +240 -199
  73. package/out/typer/dispatch-expr.js.map +1 -1
  74. package/out/typer/dispatch-process.d.ts +8 -1
  75. package/out/typer/dispatch-process.d.ts.map +1 -1
  76. package/out/typer/dispatch-process.js +37 -4
  77. package/out/typer/dispatch-process.js.map +1 -1
  78. package/out/typer/dispatch-stmt.d.ts.map +1 -1
  79. package/out/typer/dispatch-stmt.js +39 -25
  80. package/out/typer/dispatch-stmt.js.map +1 -1
  81. package/out/typer/dispatch-view.d.ts +1 -1
  82. package/out/typer/dispatch-view.d.ts.map +1 -1
  83. package/out/typer/dispatch-view.js +87 -48
  84. package/out/typer/dispatch-view.js.map +1 -1
  85. package/out/typer/fix-use-before-assign.js.map +1 -1
  86. package/out/typer/get-oql-files.d.ts.map +1 -1
  87. package/out/typer/get-oql-files.js +3 -9
  88. package/out/typer/get-oql-files.js.map +1 -1
  89. package/out/typer/incremental-update.d.ts +14 -7
  90. package/out/typer/incremental-update.d.ts.map +1 -1
  91. package/out/typer/incremental-update.js +396 -43
  92. package/out/typer/incremental-update.js.map +1 -1
  93. package/out/typer/oql-checker/chain-call-transformer.d.ts.map +1 -1
  94. package/out/typer/oql-checker/chain-call-transformer.js +17 -4
  95. package/out/typer/oql-checker/chain-call-transformer.js.map +1 -1
  96. package/out/typer/oql-checker/ts-parser.d.ts.map +1 -1
  97. package/out/typer/oql-checker/ts-parser.js +252 -37
  98. package/out/typer/oql-checker/ts-parser.js.map +1 -1
  99. package/out/typer/overload-helper.d.ts.map +1 -1
  100. package/out/typer/overload-helper.js +190 -23
  101. package/out/typer/overload-helper.js.map +1 -1
  102. package/out/typer/solver.d.ts +8 -9
  103. package/out/typer/solver.d.ts.map +1 -1
  104. package/out/typer/solver.js +54 -31
  105. package/out/typer/solver.js.map +1 -1
  106. package/out/typer/subster.d.ts +1 -1
  107. package/out/typer/subster.d.ts.map +1 -1
  108. package/out/typer/subster.js +251 -57
  109. package/out/typer/subster.js.map +1 -1
  110. package/out/typer/topo-sort.d.ts +38 -0
  111. package/out/typer/topo-sort.d.ts.map +1 -1
  112. package/out/typer/topo-sort.js +272 -3
  113. package/out/typer/topo-sort.js.map +1 -1
  114. package/out/typer/type-manager.d.ts +1 -0
  115. package/out/typer/type-manager.d.ts.map +1 -1
  116. package/out/typer/type-manager.js +14 -11
  117. package/out/typer/type-manager.js.map +1 -1
  118. package/out/typer/type-predicate.d.ts +1 -0
  119. package/out/typer/type-predicate.d.ts.map +1 -1
  120. package/out/typer/type-predicate.js +83 -14
  121. package/out/typer/type-predicate.js.map +1 -1
  122. package/out/typer/typer.d.ts +51 -6
  123. package/out/typer/typer.d.ts.map +1 -1
  124. package/out/typer/typer.js +248 -46
  125. package/out/typer/typer.js.map +1 -1
  126. package/out/typer/unifier.d.ts +12 -1
  127. package/out/typer/unifier.d.ts.map +1 -1
  128. package/out/typer/unifier.js +110 -37
  129. package/out/typer/unifier.js.map +1 -1
  130. package/out/utils/debug.js.map +1 -1
  131. package/out/utils/type-operator.d.ts +15 -0
  132. package/out/utils/type-operator.d.ts.map +1 -1
  133. package/out/utils/type-operator.js +65 -3
  134. package/out/utils/type-operator.js.map +1 -1
  135. package/package.json +5 -5
  136. package/out/reference-manager/get-q-name.d.ts +0 -9
  137. package/out/reference-manager/get-q-name.d.ts.map +0 -1
  138. package/out/reference-manager/get-q-name.js.map +0 -1
  139. package/out/reference-manager/view-elem-logic.d.ts +0 -44
  140. package/out/reference-manager/view-elem-logic.d.ts.map +0 -1
  141. package/out/reference-manager/view-elem-logic.js +0 -164
  142. package/out/reference-manager/view-elem-logic.js.map +0 -1
@@ -54,13 +54,16 @@ class TypeScriptNASLParser {
54
54
  const returns = [];
55
55
  const body = [];
56
56
  const syntaxKinds = []; // 收集所有遇到的SyntaxKind
57
+ const self = this;
58
+ let anonSubLogicCounter = 0;
57
59
  // 如果指定了returnName,直接创建Return节点
58
60
  if (returnName) {
59
61
  const returnNode = nasl_concepts_1.Return.createProtoTypeOnly({ name: returnName });
60
62
  returnNode.parentNode = fn;
61
63
  returns.push(returnNode);
62
64
  }
63
- const interpret = (node) => {
65
+ // 内部实现函数:包含所有解析逻辑
66
+ function interpretImpl(node) {
64
67
  // 记录遇到的node的Syntax类型
65
68
  const syntaxKind = ts.SyntaxKind[node.kind];
66
69
  syntaxKinds.push(syntaxKind); // 添加到数组中
@@ -85,13 +88,20 @@ class TypeScriptNASLParser {
85
88
  }
86
89
  if (obj.name === returnName) {
87
90
  // returnName对应的Return节点已经在方法开始时创建,这里只需要创建Assignment
88
- body.push(new nasl_concepts_1.Assignment({
91
+ const assignment = new nasl_concepts_1.Assignment({
89
92
  left: nasl_concepts_1.Identifier.createProtoTypeOnly({ name: returnName }),
90
93
  right: obj.defaultValue?.expression,
91
- }));
94
+ });
95
+ assignment.parentNode = fn;
96
+ if (assignment.left)
97
+ assignment.left.parentNode = assignment;
98
+ if (assignment.right)
99
+ assignment.right.parentNode = assignment;
100
+ body.push(assignment);
92
101
  }
93
102
  else {
94
103
  const v = nasl_concepts_1.Variable.createProtoTypeOnly(obj);
104
+ v.parentNode = fn;
95
105
  if (v.defaultValue) {
96
106
  v.defaultValue.parentNode = v;
97
107
  }
@@ -100,7 +110,7 @@ class TypeScriptNASLParser {
100
110
  return;
101
111
  }
102
112
  else if (ts.isCallExpression(node)) {
103
- const { namespace, name } = this.parseExpressionNamespace(node.expression);
113
+ const { namespace, name } = self.parseExpressionNamespace(node.expression);
104
114
  const call = new nasl_concepts_1.CallLogic();
105
115
  // 设置调用信息
106
116
  call.calleeName = name;
@@ -118,6 +128,7 @@ class TypeScriptNASLParser {
118
128
  call.calleeName = 'GET_LIST';
119
129
  }
120
130
  call.arguments = [];
131
+ // Note: parentNode will be set when this call is used as an expression
121
132
  return call;
122
133
  }
123
134
  else if (name === 'FROM') {
@@ -142,7 +153,7 @@ class TypeScriptNASLParser {
142
153
  const typeArgs = [];
143
154
  node.typeArguments.forEach((typeArg) => {
144
155
  // 使用interpretType函数解析类型参数
145
- const typeAnnotation = this.interpretType(typeArg);
156
+ const typeAnnotation = self.interpretType(typeArg);
146
157
  if (typeAnnotation) {
147
158
  typeArgs.push(typeAnnotation);
148
159
  }
@@ -168,55 +179,148 @@ class TypeScriptNASLParser {
168
179
  }
169
180
  else if (ts.isArrowFunction(node)) {
170
181
  // ArrowFunction - 箭头函数
171
- const func = new nasl_concepts_1.AnonymousFunction();
172
- // 处理参数
173
- const params = [];
174
- node.parameters.forEach((param) => {
175
- if (ts.isParameter(param) && ts.isIdentifier(param.name)) {
176
- const p = new nasl_concepts_1.Param({ name: param.name.text });
177
- p.typeAnnotation = undefined;
178
- p.parentNode = func;
179
- params.push(p);
180
- }
181
- else {
182
- throw new Error('ArrowFunction parameter must be identifier');
182
+ //
183
+ // 重要:chain-call-transformer 为了拆 nested chain call,可能把表达式体箭头函数重写成 block:
184
+ // () => { const $temp$1 = ...; return ...; }
185
+ // 这时若仍用 AnonymousFunction(只支持单个 body 表达式)会丢失局部变量作用域,从而产生自由变量错误。
186
+ // 因此:block 体的箭头函数解析成 SubLogic(支持 params/variables/body/returns)。
187
+ // 先解析形参
188
+ const parseParams = (parent) => {
189
+ const params = [];
190
+ node.parameters.forEach((param) => {
191
+ if (ts.isParameter(param) && ts.isIdentifier(param.name)) {
192
+ const p = new nasl_concepts_1.Param({ name: param.name.text });
193
+ p.typeAnnotation = undefined;
194
+ p.parentNode = parent;
195
+ params.push(p);
196
+ }
197
+ else {
198
+ throw new Error('ArrowFunction parameter must be identifier');
199
+ }
200
+ });
201
+ return params;
202
+ };
203
+ if (ts.isBlock(node.body)) {
204
+ const sub = new nasl_concepts_1.SubLogic();
205
+ sub.name = `$anon$${++anonSubLogicCounter}`;
206
+ sub.params = parseParams(sub);
207
+ const localVars = [];
208
+ const localBody = [];
209
+ const retName = `$return$${anonSubLogicCounter}`;
210
+ const ret = nasl_concepts_1.Return.createProtoTypeOnly({ name: retName });
211
+ ret.parentNode = sub;
212
+ sub.returns = [ret];
213
+ const addLocalVariableDecl = (decl) => {
214
+ if (!ts.isIdentifier(decl.name) || !decl.name.escapedText) {
215
+ return;
216
+ }
217
+ const v = nasl_concepts_1.Variable.createProtoTypeOnly({
218
+ name: decl.name.escapedText,
219
+ });
220
+ v.parentNode = sub;
221
+ if (decl.initializer) {
222
+ const initExpr = interpret(decl.initializer);
223
+ if (initExpr) {
224
+ const defaultValue = nasl_concepts_1.DefaultValue.createProtoTypeOnly({
225
+ expression: initExpr,
226
+ playground: [],
227
+ });
228
+ defaultValue.parentNode = v;
229
+ initExpr.parentNode = defaultValue;
230
+ v.defaultValue = defaultValue;
231
+ }
232
+ }
233
+ if (v.defaultValue) {
234
+ v.defaultValue.parentNode = v;
235
+ }
236
+ localVars.push(v);
237
+ };
238
+ for (const st of node.body.statements) {
239
+ // 支持:const x = ...;
240
+ if (ts.isVariableStatement(st)) {
241
+ st.declarationList.declarations.forEach(addLocalVariableDecl);
242
+ continue;
243
+ }
244
+ // 支持:return <expr>;
245
+ if (ts.isReturnStatement(st)) {
246
+ const retExpr = st.expression ? interpret(st.expression) : undefined;
247
+ const assignment = new nasl_concepts_1.Assignment({
248
+ left: nasl_concepts_1.Identifier.createProtoTypeOnly({ name: retName }),
249
+ right: retExpr,
250
+ });
251
+ assignment.parentNode = sub;
252
+ if (assignment.left)
253
+ assignment.left.parentNode = assignment;
254
+ if (assignment.right)
255
+ assignment.right.parentNode = assignment;
256
+ localBody.push(assignment);
257
+ continue;
258
+ }
259
+ // 兼容:表达式语句(不常见,但尽量不丢)
260
+ if (ts.isExpressionStatement(st)) {
261
+ const expr = interpret(st.expression);
262
+ if (expr) {
263
+ expr.parentNode = sub;
264
+ localBody.push(expr);
265
+ }
266
+ continue;
267
+ }
268
+ // 兼容空语句
269
+ if (ts.isEmptyStatement(st)) {
270
+ continue;
271
+ }
272
+ // 其他 statement 暂不支持(当前 transformer 只会生成上面几类)
273
+ const kind = ts.tokenToString(st.kind) || ts.SyntaxKind[st.kind];
274
+ throw new Error(`ArrowFunction block statement not implemented: ${kind}`);
183
275
  }
184
- });
185
- func.params = params;
276
+ sub.variables = localVars;
277
+ sub.body = localBody;
278
+ sub.playground = [];
279
+ // Note: parentNode will be set when this sub is used as an expression
280
+ return sub;
281
+ }
282
+ // 表达式体箭头函数:保持原行为(AnonymousFunction)
283
+ const func = new nasl_concepts_1.AnonymousFunction();
284
+ func.params = parseParams(func);
186
285
  const bodyNode = interpret(node.body);
187
286
  if (bodyNode) {
188
287
  func.body = bodyNode;
189
288
  bodyNode.parentNode = func;
190
289
  }
191
290
  else {
192
- // 报错
193
291
  throw new Error('ArrowFunction body must be non empty');
194
292
  }
293
+ // Note: parentNode will be set when this func is used as an expression
195
294
  return func;
196
295
  }
197
296
  else if (node.kind === ts.SyntaxKind.TrueKeyword) {
198
297
  // TrueKeyword - true 字面量
298
+ // Note: parentNode will be set when this literal is used as an expression
199
299
  return new nasl_concepts_1.BooleanLiteral({ value: 'true' });
200
300
  }
201
301
  else if (node.kind === ts.SyntaxKind.FalseKeyword) {
202
302
  // FalseKeyword - false 字面量
303
+ // Note: parentNode will be set when this literal is used as an expression
203
304
  return new nasl_concepts_1.BooleanLiteral({ value: 'false' });
204
305
  }
205
306
  else if (ts.isNumericLiteral(node)) {
206
307
  const literal = node;
308
+ // Note: parentNode will be set when this literal is used as an expression
207
309
  return new nasl_concepts_1.NumericLiteral({ value: literal.text });
208
310
  }
209
311
  else if (ts.isStringLiteral(node)) {
210
312
  // StringLiteral - 字符串字面量
313
+ // Note: parentNode will be set when this literal is used as an expression
211
314
  return new nasl_concepts_1.StringLiteral({ value: node.text });
212
315
  }
213
316
  else if (ts.isIdentifier(node)) {
214
317
  // Identifier - 标识符
318
+ // Note: parentNode will be set when this identifier is used as an expression
215
319
  return nasl_concepts_1.Identifier.createProtoTypeOnly({ name: node.text });
216
320
  }
217
321
  else if (ts.isNewExpression(node)) {
218
322
  // NewExpression - new 表达式
219
- const { namespace, name } = this.parseExpressionNamespace(node.expression);
323
+ const { namespace, name } = self.parseExpressionNamespace(node.expression);
220
324
  // 检查是否是 nasl.core 命名空间下的基本类型构造函数
221
325
  if (namespace === 'nasl.core' && node.arguments && node.arguments.length === 1) {
222
326
  const firstArg = node.arguments[0];
@@ -225,10 +329,12 @@ class TypeScriptNASLParser {
225
329
  case 'Integer':
226
330
  // 数值类型构造函数,转换为 NumericLiteral
227
331
  if (ts.isNumericLiteral(firstArg)) {
332
+ // Note: parentNode will be set when this literal is used as an expression
228
333
  return new nasl_concepts_1.NumericLiteral({ value: firstArg.text });
229
334
  }
230
335
  else if (ts.isStringLiteral(firstArg)) {
231
336
  // 支持字符串形式的数值
337
+ // Note: parentNode will be set when this literal is used as an expression
232
338
  return new nasl_concepts_1.NumericLiteral({ value: firstArg.text });
233
339
  }
234
340
  break;
@@ -240,36 +346,43 @@ class TypeScriptNASLParser {
240
346
  const originalText = firstArg.getText();
241
347
  // 如果是整数形式(如 "0"),转换为小数形式(如 "0.0")以确保类型推断为 Decimal
242
348
  const value = originalText.includes('.') ? originalText : `${originalText}.0`;
349
+ // Note: parentNode will be set when this literal is used as an expression
243
350
  return new nasl_concepts_1.NumericLiteral({ value });
244
351
  }
245
352
  else if (ts.isStringLiteral(firstArg)) {
246
353
  // 支持字符串形式的数值
247
354
  const value = firstArg.text.includes('.') ? firstArg.text : `${firstArg.text}.0`;
355
+ // Note: parentNode will be set when this literal is used as an expression
248
356
  return new nasl_concepts_1.NumericLiteral({ value });
249
357
  }
250
358
  break;
251
359
  case 'String':
252
360
  // 字符串类型构造函数,转换为 StringLiteral
253
361
  if (ts.isStringLiteral(firstArg)) {
362
+ // Note: parentNode will be set when this literal is used as an expression
254
363
  return new nasl_concepts_1.StringLiteral({ value: firstArg.text });
255
364
  }
256
365
  else if (ts.isNumericLiteral(firstArg)) {
257
366
  // 支持数值转字符串
367
+ // Note: parentNode will be set when this literal is used as an expression
258
368
  return new nasl_concepts_1.StringLiteral({ value: firstArg.text });
259
369
  }
260
370
  break;
261
371
  case 'Boolean':
262
372
  // 布尔类型构造函数,转换为 BooleanLiteral
263
373
  if (firstArg.kind === ts.SyntaxKind.TrueKeyword) {
374
+ // Note: parentNode will be set when this literal is used as an expression
264
375
  return new nasl_concepts_1.BooleanLiteral({ value: 'true' });
265
376
  }
266
377
  else if (firstArg.kind === ts.SyntaxKind.FalseKeyword) {
378
+ // Note: parentNode will be set when this literal is used as an expression
267
379
  return new nasl_concepts_1.BooleanLiteral({ value: 'false' });
268
380
  }
269
381
  else if (ts.isStringLiteral(firstArg)) {
270
382
  // 支持字符串形式的布尔值
271
383
  const value = firstArg.text.toLowerCase();
272
384
  if (value === 'true' || value === 'false') {
385
+ // Note: parentNode will be set when this literal is used as an expression
273
386
  return new nasl_concepts_1.BooleanLiteral({ value });
274
387
  }
275
388
  }
@@ -277,6 +390,7 @@ class TypeScriptNASLParser {
277
390
  }
278
391
  }
279
392
  else if (namespace === 'nasl.oql' && name === 'Query') {
393
+ // Note: parentNode will be set when this composite is used as an expression
280
394
  return new nasl_concepts_1.NewComposite({
281
395
  typeAnnotation: nasl_concepts_1.TypeAnnotation.createProtoTypeOnly({
282
396
  typeKind: 'reference',
@@ -294,6 +408,7 @@ class TypeScriptNASLParser {
294
408
  });
295
409
  }
296
410
  // 如果不是特殊构造函数,按普通 NewComposite 处理
411
+ // Note: parentNode will be set when this composite is used as an expression
297
412
  return new nasl_concepts_1.NewComposite({
298
413
  typeAnnotation: nasl_concepts_1.TypeAnnotation.createReference(name, {
299
414
  typeNamespace: namespace,
@@ -332,17 +447,23 @@ class TypeScriptNASLParser {
332
447
  propertyName = `property${index}`;
333
448
  }
334
449
  const identifier = nasl_concepts_1.Identifier.createProtoTypeOnly({ name: propertyName });
450
+ identifier.parentNode = composite;
335
451
  const propertyIndex = composite.properties.length;
336
452
  composite.properties.push(identifier);
337
453
  const valueExpression = interpret(property.initializer);
338
454
  if (valueExpression) {
339
455
  const selectMembers = new nasl_concepts_1.SelectMembers();
340
456
  selectMembers.expression = valueExpression;
457
+ selectMembers.parentNode = composite;
458
+ if (valueExpression) {
459
+ valueExpression.parentNode = selectMembers;
460
+ }
341
461
  const rightIndex = composite.rights.length;
342
462
  composite.rights.push(selectMembers);
343
463
  const assignmentLine = new nasl_concepts_1.AssignmentLine();
344
464
  assignmentLine.leftIndex = [0, propertyIndex];
345
465
  assignmentLine.rightIndex = [rightIndex];
466
+ assignmentLine.parentNode = composite;
346
467
  composite.assignmentLines.push(assignmentLine);
347
468
  }
348
469
  };
@@ -352,13 +473,19 @@ class TypeScriptNASLParser {
352
473
  if (ts.isSpreadAssignment(property)) {
353
474
  // 如果有未完成的 composite,先添加它
354
475
  if (currentComposite && currentComposite.properties.length > 0) {
355
- args.push(nasl_concepts_1.Argument.createProtoTypeOnly({ expression: currentComposite }));
476
+ const arg = nasl_concepts_1.Argument.createProtoTypeOnly({ expression: currentComposite });
477
+ currentComposite.parentNode = arg;
478
+ args.push(arg);
356
479
  currentComposite = null;
357
480
  }
358
481
  // 添加展开表达式
359
482
  const spreadExpression = interpret(property.expression);
360
483
  if (spreadExpression) {
361
- args.push(nasl_concepts_1.Argument.createProtoTypeOnly({ expression: spreadExpression }));
484
+ const arg = nasl_concepts_1.Argument.createProtoTypeOnly({ expression: spreadExpression });
485
+ if (spreadExpression) {
486
+ spreadExpression.parentNode = arg;
487
+ }
488
+ args.push(arg);
362
489
  }
363
490
  }
364
491
  else if (ts.isPropertyAssignment(property)) {
@@ -376,8 +503,12 @@ class TypeScriptNASLParser {
376
503
  // 根据是否有展开操作决定返回类型
377
504
  if (hasSpread) {
378
505
  // 如果最后还有未完成的 composite,添加它
506
+ // TypeScript 的控制流分析可能无法正确推断 currentComposite 的类型,使用类型断言
379
507
  if (currentComposite && currentComposite.properties.length > 0) {
380
- args.push(nasl_concepts_1.Argument.createProtoTypeOnly({ expression: currentComposite }));
508
+ const composite = currentComposite;
509
+ const arg = nasl_concepts_1.Argument.createProtoTypeOnly({ expression: composite });
510
+ composite.parentNode = arg;
511
+ args.push(arg);
381
512
  }
382
513
  // 递归辅助函数:将多个参数转换为嵌套的二元 $InternalMerge 调用
383
514
  const buildNestedMerge = (args) => {
@@ -419,6 +550,7 @@ class TypeScriptNASLParser {
419
550
  expression: firstMerge,
420
551
  });
421
552
  firstMerge.parentNode = firstMergeArg;
553
+ // Note: firstMergeArg.parentNode will be set by the parent CallLogic
422
554
  const newArgs = [firstMergeArg, ...remainingArgs];
423
555
  return buildNestedMerge(newArgs);
424
556
  }
@@ -428,6 +560,7 @@ class TypeScriptNASLParser {
428
560
  }
429
561
  else {
430
562
  // 没有展开操作,返回单个 composite
563
+ // Note: parentNode will be set when this composite is used as an expression
431
564
  return currentComposite || makeEmptyAnonymousStructure();
432
565
  }
433
566
  }
@@ -444,9 +577,59 @@ class TypeScriptNASLParser {
444
577
  }
445
578
  else if (ts.isPropertyAccessExpression(node)) {
446
579
  // PropertyAccessExpression - 属性访问表达式
580
+ const full = self.parseExpressionNamespace(node);
581
+ // 特判:把 `app.enums.<EnumName>` 解析为带 namespace 的 Identifier
582
+ // 这样 `app.enums.IntEnum['0']` 的左值就不会依赖运行时变量 `app`
583
+ if (full.namespace === 'app.enums') {
584
+ // Note: parentNode will be set when this identifier is used as an expression
585
+ return nasl_concepts_1.Identifier.createProtoTypeOnly({ namespace: 'app.enums', name: full.name });
586
+ }
447
587
  const memberExpr = new nasl_concepts_1.MemberExpression();
448
- memberExpr.object = interpret(node.expression);
449
- memberExpr.property = nasl_concepts_1.Identifier.createProtoTypeOnly({ name: node.name.text });
588
+ // 特判:把 `app.backend.variables.<var>` 解析为带 namespace 的 Identifier
589
+ // 例如:app.backend.variables.currentUser
590
+ if (full.namespace === 'app.backend.variables') {
591
+ // Note: parentNode will be set when this identifier is used as an expression
592
+ return nasl_concepts_1.Identifier.createProtoTypeOnly({ namespace: 'app.backend.variables', name: full.name });
593
+ }
594
+ // 特判:把 `app.enums.<EnumName>.<EnumItem>` 压缩为 Enum 标识符 + 成员访问
595
+ // 避免 `app` 在当前逻辑上下文里被当成普通变量,从而导致类型未知的成员访问错误
596
+ if (full.namespace?.startsWith('app.enums.')) {
597
+ const nsParts = full.namespace.split('.');
598
+ if (nsParts.length === 3) {
599
+ const enumName = nsParts[2];
600
+ const objId = nasl_concepts_1.Identifier.createProtoTypeOnly({ namespace: 'app.enums', name: enumName });
601
+ const propId = nasl_concepts_1.Identifier.createProtoTypeOnly({ name: full.name });
602
+ objId.parentNode = memberExpr;
603
+ propId.parentNode = memberExpr;
604
+ memberExpr.object = objId;
605
+ memberExpr.property = propId;
606
+ // Note: parentNode will be set when this memberExpr is used as an expression
607
+ return memberExpr;
608
+ }
609
+ }
610
+ // 特判:把 `app.backend.variables.<var>.<prop>` 压缩为 backend variable 标识符 + 成员访问
611
+ // 例如:app.backend.variables.currentUser.userId
612
+ if (full.namespace?.startsWith('app.backend.variables.')) {
613
+ const nsParts = full.namespace.split('.');
614
+ if (nsParts.length === 4) {
615
+ const varName = nsParts[3];
616
+ const objId = nasl_concepts_1.Identifier.createProtoTypeOnly({ namespace: 'app.backend.variables', name: varName });
617
+ const propId = nasl_concepts_1.Identifier.createProtoTypeOnly({ name: full.name });
618
+ objId.parentNode = memberExpr;
619
+ propId.parentNode = memberExpr;
620
+ memberExpr.object = objId;
621
+ memberExpr.property = propId;
622
+ // Note: parentNode will be set when this memberExpr is used as an expression
623
+ return memberExpr;
624
+ }
625
+ }
626
+ const obj = interpret(node.expression);
627
+ const prop = nasl_concepts_1.Identifier.createProtoTypeOnly({ name: node.name.text });
628
+ obj.parentNode = memberExpr;
629
+ prop.parentNode = memberExpr;
630
+ memberExpr.object = obj;
631
+ memberExpr.property = prop;
632
+ // Note: parentNode will be set when this memberExpr is used as an expression
450
633
  return memberExpr;
451
634
  }
452
635
  else if (ts.isSpreadAssignment(node)) {
@@ -472,12 +655,15 @@ class TypeScriptNASLParser {
472
655
  const expression = interpret(element);
473
656
  const argument = nasl_concepts_1.Argument.createProtoTypeOnly({ keyword, expression });
474
657
  argument.parentNode = call;
475
- expression && (expression.parentNode = argument);
658
+ if (expression) {
659
+ expression.parentNode = argument;
660
+ }
476
661
  return argument;
477
662
  }) || [];
478
663
  call.calleeName = `$InternalTuple${args.length}`;
479
664
  call.calleeNamespace = 'nasl.core';
480
665
  call.arguments = args;
666
+ // Note: parentNode will be set when this call is used as an expression
481
667
  return call;
482
668
  }
483
669
  else if (ts.isParenthesizedExpression(node)) {
@@ -488,37 +674,66 @@ class TypeScriptNASLParser {
488
674
  }
489
675
  else if (ts.isBinaryExpression(node)) {
490
676
  const result = new nasl_concepts_1.BinaryExpression();
491
- result.left = interpret(node.left);
492
- result.right = interpret(node.right);
677
+ const left = interpret(node.left);
678
+ const right = interpret(node.right);
679
+ if (left)
680
+ left.parentNode = result;
681
+ if (right)
682
+ right.parentNode = result;
683
+ result.left = left;
684
+ result.right = right;
493
685
  result.operator = node.operatorToken.getText();
686
+ // Note: parentNode will be set when this expression is used as an expression
494
687
  return result;
495
688
  }
496
689
  else if (ts.isElementAccessExpression(node)) {
497
690
  const result = new nasl_concepts_1.CallFunction();
691
+ const expr = interpret(node.expression);
692
+ const argExpr = interpret(node.argumentExpression);
693
+ const arg1 = nasl_concepts_1.Argument.createProtoTypeOnly({ expression: expr });
694
+ const arg2 = nasl_concepts_1.Argument.createProtoTypeOnly({ expression: argExpr });
695
+ if (expr)
696
+ expr.parentNode = arg1;
697
+ if (argExpr)
698
+ argExpr.parentNode = arg2;
699
+ arg1.parentNode = result;
700
+ arg2.parentNode = result;
498
701
  result.calleeName = 'Get';
499
702
  result.calleeNamespace = 'nasl.util';
500
- result.arguments = [
501
- interpret(node.expression),
502
- interpret(node.argumentExpression),
503
- ];
703
+ result.arguments = [arg1, arg2];
704
+ // Note: parentNode will be set when this call is used as an expression
504
705
  return result;
505
706
  }
506
707
  else if (ts.SyntaxKind.NullKeyword === node.kind) {
507
- const result = new nasl_concepts_1.NullLiteral();
508
- return result;
708
+ // Note: parentNode will be set when this literal is used as an expression
709
+ return new nasl_concepts_1.NullLiteral();
509
710
  }
510
711
  else if (ts.isSourceFile(node)) {
511
712
  // SourceFile 节点不需要处理
512
713
  }
714
+ else if (ts.isEmptyStatement(node)) {
715
+ // EmptyStatement 不需要处理,直接跳过
716
+ return undefined;
717
+ }
513
718
  else {
514
719
  // 收集未支持的表达式类型
515
720
  const kind = ts.tokenToString(node.kind) || ts.SyntaxKind[node.kind];
516
- this.unsupportedTypes.add(kind);
721
+ self.unsupportedTypes.add(kind);
517
722
  throw new Error(`未支持的表达式类型: ${kind}`);
518
723
  }
519
724
  ts.visitEachChild(node, visitor, undefined);
520
725
  return undefined;
521
- };
726
+ }
727
+ ;
728
+ /**
729
+ * 解析TypeScript节点为NASL节点
730
+ * @param node TypeScript节点
731
+ * @returns NASL节点
732
+ */
733
+ function interpret(node) {
734
+ return interpretImpl(node);
735
+ }
736
+ ;
522
737
  // 创建visitor函数来遍历AST节点
523
738
  const visitor = (node) => {
524
739
  interpret(node);