@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.
- package/out/checker.d.ts +4 -1
- package/out/checker.d.ts.map +1 -1
- package/out/checker.js +996 -96
- package/out/checker.js.map +1 -1
- package/out/index.d.ts +1 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js +5 -3
- package/out/index.js.map +1 -1
- package/out/reference-manager/build-q-name-def.d.ts.map +1 -1
- package/out/reference-manager/build-q-name-def.js +11 -0
- package/out/reference-manager/build-q-name-def.js.map +1 -1
- package/out/reference-manager/builtin-q-name.js +2 -2
- package/out/reference-manager/builtin-q-name.js.map +1 -1
- package/out/reference-manager/collect-q-name.d.ts +1 -1
- package/out/reference-manager/collect-q-name.d.ts.map +1 -1
- package/out/reference-manager/collect-q-name.js +64 -27
- package/out/reference-manager/collect-q-name.js.map +1 -1
- package/out/reference-manager/def-key-helpers.d.ts +38 -0
- package/out/reference-manager/def-key-helpers.d.ts.map +1 -0
- package/out/reference-manager/{get-q-name.js → def-key-helpers.js} +195 -23
- package/out/reference-manager/def-key-helpers.js.map +1 -0
- package/out/reference-manager/helper.js +2 -2
- package/out/reference-manager/helper.js.map +1 -1
- package/out/reference-manager/reference-manager.d.ts +146 -47
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +632 -204
- package/out/reference-manager/reference-manager.js.map +1 -1
- package/out/reference-manager/remove-q-name.d.ts +1 -1
- package/out/reference-manager/remove-q-name.d.ts.map +1 -1
- package/out/reference-manager/remove-q-name.js +14 -14
- package/out/reference-manager/remove-q-name.js.map +1 -1
- package/out/reference-manager/rename-q-name.d.ts +26 -26
- package/out/reference-manager/rename-q-name.d.ts.map +1 -1
- package/out/reference-manager/rename-q-name.js +48 -167
- package/out/reference-manager/rename-q-name.js.map +1 -1
- package/out/reference-manager/symbol-type.d.ts +8 -3
- package/out/reference-manager/symbol-type.d.ts.map +1 -1
- package/out/reference-manager/symbol-type.js +9 -2
- package/out/reference-manager/symbol-type.js.map +1 -1
- package/out/reference-manager/update-nasl-fragment.d.ts +2 -2
- package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
- package/out/reference-manager/update-nasl-fragment.js +33 -28
- package/out/reference-manager/update-nasl-fragment.js.map +1 -1
- package/out/services/bindable-logic-service.js.map +1 -1
- package/out/symbol/traverse/concepts/index.d.ts +1 -1
- package/out/symbol/traverse/concepts/index.d.ts.map +1 -1
- package/out/symbol/traverse/concepts/logic/expression/member-expression.js.map +1 -1
- package/out/typer/collectGlobalDefs.d.ts +8 -0
- package/out/typer/collectGlobalDefs.d.ts.map +1 -1
- package/out/typer/collectGlobalDefs.js +102 -54
- package/out/typer/collectGlobalDefs.js.map +1 -1
- package/out/typer/component-def-manager/component-def-manager.d.ts +16 -0
- package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
- package/out/typer/component-def-manager/component-def-manager.js +63 -2
- package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
- package/out/typer/component-def-manager/utils.d.ts.map +1 -1
- package/out/typer/component-def-manager/utils.js +26 -0
- package/out/typer/component-def-manager/utils.js.map +1 -1
- package/out/typer/dispatch-all.d.ts +3 -1
- package/out/typer/dispatch-all.d.ts.map +1 -1
- package/out/typer/dispatch-all.js +51 -6
- package/out/typer/dispatch-all.js.map +1 -1
- package/out/typer/dispatch-call.d.ts +27 -1
- package/out/typer/dispatch-call.d.ts.map +1 -1
- package/out/typer/dispatch-call.js +151 -107
- package/out/typer/dispatch-call.js.map +1 -1
- package/out/typer/dispatch-def.d.ts.map +1 -1
- package/out/typer/dispatch-def.js +51 -23
- package/out/typer/dispatch-def.js.map +1 -1
- package/out/typer/dispatch-expr.d.ts +2 -1
- package/out/typer/dispatch-expr.d.ts.map +1 -1
- package/out/typer/dispatch-expr.js +240 -199
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-process.d.ts +8 -1
- package/out/typer/dispatch-process.d.ts.map +1 -1
- package/out/typer/dispatch-process.js +37 -4
- package/out/typer/dispatch-process.js.map +1 -1
- package/out/typer/dispatch-stmt.d.ts.map +1 -1
- package/out/typer/dispatch-stmt.js +39 -25
- package/out/typer/dispatch-stmt.js.map +1 -1
- package/out/typer/dispatch-view.d.ts +1 -1
- package/out/typer/dispatch-view.d.ts.map +1 -1
- package/out/typer/dispatch-view.js +87 -48
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/fix-use-before-assign.js.map +1 -1
- package/out/typer/get-oql-files.d.ts.map +1 -1
- package/out/typer/get-oql-files.js +3 -9
- package/out/typer/get-oql-files.js.map +1 -1
- package/out/typer/incremental-update.d.ts +14 -7
- package/out/typer/incremental-update.d.ts.map +1 -1
- package/out/typer/incremental-update.js +396 -43
- package/out/typer/incremental-update.js.map +1 -1
- package/out/typer/oql-checker/chain-call-transformer.d.ts.map +1 -1
- package/out/typer/oql-checker/chain-call-transformer.js +17 -4
- package/out/typer/oql-checker/chain-call-transformer.js.map +1 -1
- package/out/typer/oql-checker/ts-parser.d.ts.map +1 -1
- package/out/typer/oql-checker/ts-parser.js +252 -37
- package/out/typer/oql-checker/ts-parser.js.map +1 -1
- package/out/typer/overload-helper.d.ts.map +1 -1
- package/out/typer/overload-helper.js +190 -23
- package/out/typer/overload-helper.js.map +1 -1
- package/out/typer/solver.d.ts +8 -9
- package/out/typer/solver.d.ts.map +1 -1
- package/out/typer/solver.js +54 -31
- package/out/typer/solver.js.map +1 -1
- package/out/typer/subster.d.ts +1 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +251 -57
- package/out/typer/subster.js.map +1 -1
- package/out/typer/topo-sort.d.ts +38 -0
- package/out/typer/topo-sort.d.ts.map +1 -1
- package/out/typer/topo-sort.js +272 -3
- package/out/typer/topo-sort.js.map +1 -1
- package/out/typer/type-manager.d.ts +1 -0
- package/out/typer/type-manager.d.ts.map +1 -1
- package/out/typer/type-manager.js +14 -11
- package/out/typer/type-manager.js.map +1 -1
- package/out/typer/type-predicate.d.ts +1 -0
- package/out/typer/type-predicate.d.ts.map +1 -1
- package/out/typer/type-predicate.js +83 -14
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +51 -6
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +248 -46
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts +12 -1
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +110 -37
- package/out/typer/unifier.js.map +1 -1
- package/out/utils/debug.js.map +1 -1
- package/out/utils/type-operator.d.ts +15 -0
- package/out/utils/type-operator.d.ts.map +1 -1
- package/out/utils/type-operator.js +65 -3
- package/out/utils/type-operator.js.map +1 -1
- package/package.json +5 -5
- package/out/reference-manager/get-q-name.d.ts +0 -9
- package/out/reference-manager/get-q-name.d.ts.map +0 -1
- package/out/reference-manager/get-q-name.js.map +0 -1
- package/out/reference-manager/view-elem-logic.d.ts +0 -44
- package/out/reference-manager/view-elem-logic.d.ts.map +0 -1
- package/out/reference-manager/view-elem-logic.js +0 -164
- 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
|
-
|
|
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
|
-
|
|
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 } =
|
|
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 =
|
|
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
|
-
|
|
172
|
-
//
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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 } =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
449
|
-
|
|
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
|
-
|
|
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
|
-
|
|
492
|
-
|
|
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
|
-
|
|
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
|
-
|
|
508
|
-
return
|
|
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
|
-
|
|
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);
|