@lcap/nasl-language-server-core 4.3.0-beta.0 → 4.3.0-beta.3
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 +6 -0
- package/out/checker.d.ts.map +1 -1
- package/out/checker.js +28 -7
- package/out/checker.js.map +1 -1
- package/out/index.d.ts +2 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js +3 -1
- 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 +0 -9
- package/out/reference-manager/build-q-name-def.js.map +1 -1
- package/out/reference-manager/builtin-q-name.d.ts.map +1 -1
- package/out/reference-manager/builtin-q-name.js +1 -5
- package/out/reference-manager/builtin-q-name.js.map +1 -1
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +4 -1
- package/out/reference-manager/reference-manager.js.map +1 -1
- package/out/reference-manager/symbol-type.d.ts +1 -1
- package/out/reference-manager/symbol-type.d.ts.map +1 -1
- package/out/reference-manager/symbol-type.js.map +1 -1
- package/out/typer/collectGlobalDefs.d.ts.map +1 -1
- package/out/typer/collectGlobalDefs.js +3 -1
- package/out/typer/collectGlobalDefs.js.map +1 -1
- package/out/typer/component-def-manager/utils.d.ts.map +1 -1
- package/out/typer/component-def-manager/utils.js +4 -2
- package/out/typer/component-def-manager/utils.js.map +1 -1
- package/out/typer/dispatch-call.d.ts.map +1 -1
- package/out/typer/dispatch-call.js +177 -26
- 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 +6 -2
- package/out/typer/dispatch-def.js.map +1 -1
- package/out/typer/dispatch-expr.d.ts +4 -2
- package/out/typer/dispatch-expr.d.ts.map +1 -1
- package/out/typer/dispatch-expr.js +111 -18
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-stmt.d.ts.map +1 -1
- package/out/typer/dispatch-stmt.js +1 -0
- package/out/typer/dispatch-stmt.js.map +1 -1
- package/out/typer/dispatch-view.js +1 -1
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/get-export-interfaces-files.d.ts +8 -0
- package/out/typer/get-export-interfaces-files.d.ts.map +1 -0
- package/out/typer/get-export-interfaces-files.js +31 -0
- package/out/typer/get-export-interfaces-files.js.map +1 -0
- package/out/typer/get-origin-logic-files.d.ts +1 -1
- package/out/typer/get-origin-logic-files.js +1 -1
- package/out/typer/index.d.ts +2 -1
- package/out/typer/index.d.ts.map +1 -1
- package/out/typer/index.js +3 -1
- package/out/typer/index.js.map +1 -1
- package/out/typer/oql-checker/chain-call-transformer.d.ts +21 -0
- package/out/typer/oql-checker/chain-call-transformer.d.ts.map +1 -0
- package/out/typer/oql-checker/chain-call-transformer.js +150 -0
- package/out/typer/oql-checker/chain-call-transformer.js.map +1 -0
- package/out/typer/oql-checker/ts-parser.d.ts +46 -0
- package/out/typer/oql-checker/ts-parser.d.ts.map +1 -0
- package/out/typer/oql-checker/ts-parser.js +706 -0
- package/out/typer/oql-checker/ts-parser.js.map +1 -0
- package/out/typer/oql-checker/ts-printer.d.ts +3 -0
- package/out/typer/oql-checker/ts-printer.d.ts.map +1 -0
- package/out/typer/oql-checker/ts-printer.js +37 -0
- package/out/typer/oql-checker/ts-printer.js.map +1 -0
- package/out/typer/overload-helper.d.ts +17 -6
- package/out/typer/overload-helper.d.ts.map +1 -1
- package/out/typer/overload-helper.js +393 -76
- package/out/typer/overload-helper.js.map +1 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +70 -2
- package/out/typer/subster.js.map +1 -1
- package/out/typer/type-manager.js +4 -4
- package/out/typer/type-manager.js.map +1 -1
- package/out/typer/type-predicate.d.ts +9 -0
- package/out/typer/type-predicate.d.ts.map +1 -1
- package/out/typer/type-predicate.js +14 -1
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +13 -3
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +21 -5
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +4 -5
- package/out/typer/unifier.js.map +1 -1
- package/out/utils/debug.d.ts +6 -0
- package/out/utils/debug.d.ts.map +1 -0
- package/out/utils/debug.js +62 -0
- package/out/utils/debug.js.map +1 -0
- package/out/utils/file-node-cache.d.ts.map +1 -1
- package/out/utils/file-node-cache.js +4 -1
- package/out/utils/file-node-cache.js.map +1 -1
- package/out/utils/internal-tuple.d.ts +2 -0
- package/out/utils/internal-tuple.d.ts.map +1 -0
- package/out/utils/internal-tuple.js +29 -0
- package/out/utils/internal-tuple.js.map +1 -0
- package/out/utils/parseTsClassType.d.ts +1 -5
- package/out/utils/parseTsClassType.d.ts.map +1 -1
- package/out/utils/parseTsClassType.js +103 -66
- package/out/utils/parseTsClassType.js.map +1 -1
- package/out/utils/type-operator.d.ts +29 -1
- package/out/utils/type-operator.d.ts.map +1 -1
- package/out/utils/type-operator.js +181 -1
- package/out/utils/type-operator.js.map +1 -1
- package/out/utils/type-operators/CheckUniqueKeys.d.ts +15 -0
- package/out/utils/type-operators/CheckUniqueKeys.d.ts.map +1 -0
- package/out/utils/type-operators/CheckUniqueKeys.js +86 -0
- package/out/utils/type-operators/CheckUniqueKeys.js.map +1 -0
- package/package.json +11 -6
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.TypeScriptNASLParser = void 0;
|
|
27
|
+
const nasl_concepts_1 = require("@lcap/nasl-concepts");
|
|
28
|
+
const ts = __importStar(require("typescript"));
|
|
29
|
+
const chain_call_transformer_1 = require("./chain-call-transformer");
|
|
30
|
+
class TypeScriptNASLParser {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.unsupportedTypes = new Set();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 解析TypeScript代码为NASL语法树节点
|
|
36
|
+
* @param code TypeScript代码字符串
|
|
37
|
+
* @returns NASL语法树节点
|
|
38
|
+
*/
|
|
39
|
+
parseToExpression(code) {
|
|
40
|
+
const ast = this.parseAndTransform(code)?.transformed;
|
|
41
|
+
if (!ast) {
|
|
42
|
+
throw new Error('Failed to parse TypeScript code');
|
|
43
|
+
}
|
|
44
|
+
const expr = ast.statements;
|
|
45
|
+
if (!expr) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
parseInLogicContext(code, returnName) {
|
|
51
|
+
const fn = new nasl_concepts_1.Logic();
|
|
52
|
+
const source = (0, chain_call_transformer_1.transformChainCalls)(code).transformed;
|
|
53
|
+
const variables = [];
|
|
54
|
+
const returns = [];
|
|
55
|
+
const body = [];
|
|
56
|
+
const syntaxKinds = []; // 收集所有遇到的SyntaxKind
|
|
57
|
+
// 如果指定了returnName,直接创建Return节点
|
|
58
|
+
if (returnName) {
|
|
59
|
+
const returnNode = nasl_concepts_1.Return.createProtoTypeOnly({ name: returnName });
|
|
60
|
+
returnNode.parentNode = fn;
|
|
61
|
+
returns.push(returnNode);
|
|
62
|
+
}
|
|
63
|
+
const interpret = (node) => {
|
|
64
|
+
// 记录遇到的node的Syntax类型
|
|
65
|
+
const syntaxKind = ts.SyntaxKind[node.kind];
|
|
66
|
+
syntaxKinds.push(syntaxKind); // 添加到数组中
|
|
67
|
+
if (ts.isVariableDeclaration(node)) {
|
|
68
|
+
if (!ts.isIdentifier(node.name) || !node.name.escapedText) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const obj = {
|
|
72
|
+
name: node.name.escapedText,
|
|
73
|
+
};
|
|
74
|
+
if (node.initializer) {
|
|
75
|
+
const expr = interpret(node.initializer);
|
|
76
|
+
if (expr) {
|
|
77
|
+
const defaultValue = nasl_concepts_1.DefaultValue.createProtoTypeOnly({
|
|
78
|
+
expression: expr,
|
|
79
|
+
playground: [],
|
|
80
|
+
});
|
|
81
|
+
defaultValue.parentNode = fn;
|
|
82
|
+
expr.parentNode = defaultValue;
|
|
83
|
+
obj.defaultValue = defaultValue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (obj.name === returnName) {
|
|
87
|
+
// returnName对应的Return节点已经在方法开始时创建,这里只需要创建Assignment
|
|
88
|
+
body.push(new nasl_concepts_1.Assignment({
|
|
89
|
+
left: new nasl_concepts_1.Identifier({ name: returnName }),
|
|
90
|
+
right: obj.defaultValue?.expression,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const v = nasl_concepts_1.Variable.createProtoTypeOnly(obj);
|
|
95
|
+
if (v.defaultValue) {
|
|
96
|
+
v.defaultValue.parentNode = v;
|
|
97
|
+
}
|
|
98
|
+
variables.push(v);
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
else if (ts.isCallExpression(node)) {
|
|
103
|
+
const { namespace, name } = this.parseExpressionNamespace(node.expression);
|
|
104
|
+
const call = new nasl_concepts_1.CallLogic();
|
|
105
|
+
// 设置调用信息
|
|
106
|
+
call.calleeName = name;
|
|
107
|
+
call.calleeNamespace = namespace || '';
|
|
108
|
+
// 如果是临时变量的Identifier上的调用,在解释时hardcode静态分派
|
|
109
|
+
if (call.calleeNamespace?.startsWith('$')) {
|
|
110
|
+
// 支持方法的动态分派需要大面积重构类型推导机制,非常困难,先不支持
|
|
111
|
+
if (name === 'GET' && node.arguments.length > 0) {
|
|
112
|
+
// 特殊处理:当callee名为'GET'且参数为boolean值时,根据boolean值是true还是false静态分派callee,并且清空 arguments
|
|
113
|
+
const firstArg = node.arguments[0];
|
|
114
|
+
if (firstArg.kind === ts.SyntaxKind.TrueKeyword) {
|
|
115
|
+
call.calleeName = 'GET_NO_LIST';
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
call.calleeName = 'GET_LIST';
|
|
119
|
+
}
|
|
120
|
+
call.arguments = [];
|
|
121
|
+
return call;
|
|
122
|
+
}
|
|
123
|
+
else if (name === 'FROM') {
|
|
124
|
+
if (node.arguments.length === 0) {
|
|
125
|
+
call.calleeName = 'FROM_0';
|
|
126
|
+
}
|
|
127
|
+
else if (node.arguments.length === 1) {
|
|
128
|
+
call.calleeName = 'FROM_1';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (name === 'JOIN') {
|
|
132
|
+
if (node.arguments.length === 0) {
|
|
133
|
+
call.calleeName = 'JOIN_0';
|
|
134
|
+
}
|
|
135
|
+
else if (node.arguments.length === 1) {
|
|
136
|
+
call.calleeName = 'JOIN_1';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 处理类型参数
|
|
141
|
+
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
142
|
+
const typeArgs = [];
|
|
143
|
+
node.typeArguments.forEach((typeArg) => {
|
|
144
|
+
// 使用interpretType函数解析类型参数
|
|
145
|
+
const typeAnnotation = this.interpretType(typeArg);
|
|
146
|
+
if (typeAnnotation) {
|
|
147
|
+
typeArgs.push(typeAnnotation);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
call.typeArguments = typeArgs;
|
|
151
|
+
}
|
|
152
|
+
// 处理参数
|
|
153
|
+
const args = [];
|
|
154
|
+
node.arguments.forEach((arg, index) => {
|
|
155
|
+
const expression = interpret(arg);
|
|
156
|
+
const argument = new nasl_concepts_1.Argument({
|
|
157
|
+
keyword: `param${index + 1}`, // 默认参数名
|
|
158
|
+
expression: expression,
|
|
159
|
+
});
|
|
160
|
+
argument.parentNode = call;
|
|
161
|
+
if (expression) {
|
|
162
|
+
expression.parentNode = argument;
|
|
163
|
+
}
|
|
164
|
+
args.push(argument);
|
|
165
|
+
});
|
|
166
|
+
call.arguments = args;
|
|
167
|
+
return call;
|
|
168
|
+
}
|
|
169
|
+
else if (ts.isArrowFunction(node)) {
|
|
170
|
+
// 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');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
func.params = params;
|
|
186
|
+
const body = interpret(node.body);
|
|
187
|
+
if (body) {
|
|
188
|
+
const bodyNode = interpret(node.body);
|
|
189
|
+
func.body = bodyNode;
|
|
190
|
+
if (bodyNode) {
|
|
191
|
+
bodyNode.parentNode = func;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// 报错
|
|
196
|
+
throw new Error('ArrowFunction body must be non empty');
|
|
197
|
+
}
|
|
198
|
+
return func;
|
|
199
|
+
}
|
|
200
|
+
else if (node.kind === ts.SyntaxKind.TrueKeyword) {
|
|
201
|
+
// TrueKeyword - true 字面量
|
|
202
|
+
return new nasl_concepts_1.BooleanLiteral({ value: 'true' });
|
|
203
|
+
}
|
|
204
|
+
else if (node.kind === ts.SyntaxKind.FalseKeyword) {
|
|
205
|
+
// FalseKeyword - false 字面量
|
|
206
|
+
return new nasl_concepts_1.BooleanLiteral({ value: 'false' });
|
|
207
|
+
}
|
|
208
|
+
else if (ts.isNumericLiteral(node)) {
|
|
209
|
+
const literal = node;
|
|
210
|
+
return new nasl_concepts_1.NumericLiteral({ value: literal.text });
|
|
211
|
+
}
|
|
212
|
+
else if (ts.isStringLiteral(node)) {
|
|
213
|
+
// StringLiteral - 字符串字面量
|
|
214
|
+
return new nasl_concepts_1.StringLiteral({ value: node.text });
|
|
215
|
+
}
|
|
216
|
+
else if (ts.isIdentifier(node)) {
|
|
217
|
+
// Identifier - 标识符
|
|
218
|
+
return new nasl_concepts_1.Identifier({ name: node.text });
|
|
219
|
+
}
|
|
220
|
+
else if (ts.isNewExpression(node)) {
|
|
221
|
+
// NewExpression - new 表达式
|
|
222
|
+
const { namespace, name } = this.parseExpressionNamespace(node.expression);
|
|
223
|
+
// 检查是否是 nasl.core 命名空间下的基本类型构造函数
|
|
224
|
+
if (namespace === 'nasl.core' && node.arguments && node.arguments.length === 1) {
|
|
225
|
+
const firstArg = node.arguments[0];
|
|
226
|
+
switch (name) {
|
|
227
|
+
case 'Long':
|
|
228
|
+
case 'Integer':
|
|
229
|
+
case 'Double':
|
|
230
|
+
case 'Decimal':
|
|
231
|
+
// 数值类型构造函数,转换为 NumericLiteral
|
|
232
|
+
if (ts.isNumericLiteral(firstArg)) {
|
|
233
|
+
return new nasl_concepts_1.NumericLiteral({ value: firstArg.text });
|
|
234
|
+
}
|
|
235
|
+
else if (ts.isStringLiteral(firstArg)) {
|
|
236
|
+
// 支持字符串形式的数值
|
|
237
|
+
return new nasl_concepts_1.NumericLiteral({ value: firstArg.text });
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
case 'String':
|
|
241
|
+
// 字符串类型构造函数,转换为 StringLiteral
|
|
242
|
+
if (ts.isStringLiteral(firstArg)) {
|
|
243
|
+
return new nasl_concepts_1.StringLiteral({ value: firstArg.text });
|
|
244
|
+
}
|
|
245
|
+
else if (ts.isNumericLiteral(firstArg)) {
|
|
246
|
+
// 支持数值转字符串
|
|
247
|
+
return new nasl_concepts_1.StringLiteral({ value: firstArg.text });
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
250
|
+
case 'Boolean':
|
|
251
|
+
// 布尔类型构造函数,转换为 BooleanLiteral
|
|
252
|
+
if (firstArg.kind === ts.SyntaxKind.TrueKeyword) {
|
|
253
|
+
return new nasl_concepts_1.BooleanLiteral({ value: 'true' });
|
|
254
|
+
}
|
|
255
|
+
else if (firstArg.kind === ts.SyntaxKind.FalseKeyword) {
|
|
256
|
+
return new nasl_concepts_1.BooleanLiteral({ value: 'false' });
|
|
257
|
+
}
|
|
258
|
+
else if (ts.isStringLiteral(firstArg)) {
|
|
259
|
+
// 支持字符串形式的布尔值
|
|
260
|
+
const value = firstArg.text.toLowerCase();
|
|
261
|
+
if (value === 'true' || value === 'false') {
|
|
262
|
+
return new nasl_concepts_1.BooleanLiteral({ value });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else if (namespace === 'nasl.oql' && name === 'Query') {
|
|
269
|
+
return new nasl_concepts_1.NewComposite({
|
|
270
|
+
typeAnnotation: nasl_concepts_1.TypeAnnotation.createProtoTypeOnly({
|
|
271
|
+
typeKind: 'reference',
|
|
272
|
+
typeName: 'Query',
|
|
273
|
+
typeNamespace: namespace,
|
|
274
|
+
typeArguments: [
|
|
275
|
+
nasl_concepts_1.TypeAnnotation.createProtoTypeOnly({
|
|
276
|
+
typeName: 'InternalTupleType',
|
|
277
|
+
typeNamespace: 'nasl.core',
|
|
278
|
+
typeKind: 'generic',
|
|
279
|
+
typeArguments: [],
|
|
280
|
+
}),
|
|
281
|
+
],
|
|
282
|
+
}),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// 如果不是特殊构造函数,按普通 NewComposite 处理
|
|
286
|
+
return new nasl_concepts_1.NewComposite({
|
|
287
|
+
typeAnnotation: nasl_concepts_1.TypeAnnotation.createReference(name, {
|
|
288
|
+
typeNamespace: namespace,
|
|
289
|
+
}),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else if (ts.isObjectLiteralExpression(node)) {
|
|
293
|
+
// ObjectLiteralExpression - 对象字面量
|
|
294
|
+
const hasSpread = node.properties.some((prop) => ts.isSpreadAssignment(prop));
|
|
295
|
+
const args = [];
|
|
296
|
+
let currentComposite = null;
|
|
297
|
+
function makeEmptyAnonymousStructure(properties) {
|
|
298
|
+
// 为了让NewComposite成为匿名数据结构,需要指定typeAnnotation的typeKind=anonymousStructure;
|
|
299
|
+
// 否则会被tpNewComposite判断为具名新建
|
|
300
|
+
const res = new nasl_concepts_1.NewComposite({
|
|
301
|
+
typeAnnotation: nasl_concepts_1.TypeAnnotation.createProtoTypeOnly({
|
|
302
|
+
typeKind: 'anonymousStructure',
|
|
303
|
+
properties: properties ?? [],
|
|
304
|
+
}),
|
|
305
|
+
});
|
|
306
|
+
return res;
|
|
307
|
+
}
|
|
308
|
+
// 辅助函数:处理属性赋值
|
|
309
|
+
const processPropertyAssignment = (property, index, composite) => {
|
|
310
|
+
let propertyName;
|
|
311
|
+
if (ts.isIdentifier(property.name)) {
|
|
312
|
+
propertyName = property.name.text;
|
|
313
|
+
}
|
|
314
|
+
else if (ts.isStringLiteral(property.name)) {
|
|
315
|
+
propertyName = property.name.text;
|
|
316
|
+
}
|
|
317
|
+
else if (ts.isNumericLiteral(property.name)) {
|
|
318
|
+
propertyName = property.name.text;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
propertyName = `property${index}`;
|
|
322
|
+
}
|
|
323
|
+
const identifier = new nasl_concepts_1.Identifier({ name: propertyName });
|
|
324
|
+
const propertyIndex = composite.properties.length;
|
|
325
|
+
composite.properties.push(identifier);
|
|
326
|
+
const valueExpression = interpret(property.initializer);
|
|
327
|
+
if (valueExpression) {
|
|
328
|
+
const selectMembers = new nasl_concepts_1.SelectMembers();
|
|
329
|
+
selectMembers.expression = valueExpression;
|
|
330
|
+
const rightIndex = composite.rights.length;
|
|
331
|
+
composite.rights.push(selectMembers);
|
|
332
|
+
const assignmentLine = new nasl_concepts_1.AssignmentLine();
|
|
333
|
+
assignmentLine.leftIndex = [0, propertyIndex];
|
|
334
|
+
assignmentLine.rightIndex = [rightIndex];
|
|
335
|
+
composite.assignmentLines.push(assignmentLine);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
// 按顺序处理每个属性
|
|
339
|
+
node.properties.forEach((property, index) => {
|
|
340
|
+
syntaxKinds.push(ts.SyntaxKind[property.kind]);
|
|
341
|
+
if (ts.isSpreadAssignment(property)) {
|
|
342
|
+
// 如果有未完成的 composite,先添加它
|
|
343
|
+
if (currentComposite && currentComposite.properties.length > 0) {
|
|
344
|
+
args.push(new nasl_concepts_1.Argument({ expression: currentComposite }));
|
|
345
|
+
currentComposite = null;
|
|
346
|
+
}
|
|
347
|
+
// 添加展开表达式
|
|
348
|
+
const spreadExpression = interpret(property.expression);
|
|
349
|
+
if (spreadExpression) {
|
|
350
|
+
args.push(new nasl_concepts_1.Argument({ expression: spreadExpression }));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
else if (ts.isPropertyAssignment(property)) {
|
|
354
|
+
// 如果还没有 composite,创建一个
|
|
355
|
+
if (!currentComposite) {
|
|
356
|
+
currentComposite = makeEmptyAnonymousStructure();
|
|
357
|
+
}
|
|
358
|
+
// 使用共享的属性处理逻辑
|
|
359
|
+
processPropertyAssignment(property, index, currentComposite);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
throw new Error(`ObjectLiteralExpression property type not implemented: ${ts.SyntaxKind[property.kind]}`);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
// 根据是否有展开操作决定返回类型
|
|
366
|
+
if (hasSpread) {
|
|
367
|
+
// 如果最后还有未完成的 composite,添加它
|
|
368
|
+
if (currentComposite && currentComposite.properties.length > 0) {
|
|
369
|
+
args.push(new nasl_concepts_1.Argument({ expression: currentComposite }));
|
|
370
|
+
}
|
|
371
|
+
if (args.length === 0) {
|
|
372
|
+
// 不应该接受,随便返回一个空的匿名数据结构即可
|
|
373
|
+
return makeEmptyAnonymousStructure();
|
|
374
|
+
}
|
|
375
|
+
else if (args.length === 1) {
|
|
376
|
+
const call = new nasl_concepts_1.CallLogic();
|
|
377
|
+
call.calleeName = '$InternalMergeUnary';
|
|
378
|
+
call.calleeNamespace = 'nasl.core';
|
|
379
|
+
call.arguments = args;
|
|
380
|
+
return call;
|
|
381
|
+
}
|
|
382
|
+
else if (args.length > 1) {
|
|
383
|
+
// TODO wudengke 如果不支持多元重载,那么将他递归地翻译成二元$InternalMerge调用的嵌套
|
|
384
|
+
}
|
|
385
|
+
// 创建 $InternalMerge 调用
|
|
386
|
+
const call = new nasl_concepts_1.CallLogic();
|
|
387
|
+
call.calleeName = '$InternalMerge';
|
|
388
|
+
call.calleeNamespace = 'nasl.core';
|
|
389
|
+
call.arguments = args;
|
|
390
|
+
return call;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// 没有展开操作,返回单个 composite
|
|
394
|
+
return currentComposite || makeEmptyAnonymousStructure();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else if (ts.isParameter(node)) {
|
|
398
|
+
// Parameter - 参数
|
|
399
|
+
if (ts.isIdentifier(node.name)) {
|
|
400
|
+
return new nasl_concepts_1.Param({ name: node.name.text });
|
|
401
|
+
}
|
|
402
|
+
return new nasl_concepts_1.Param({ name: 'param' });
|
|
403
|
+
}
|
|
404
|
+
else if (ts.isParenthesizedExpression(node)) {
|
|
405
|
+
// ParenthesizedExpression - 括号表达式
|
|
406
|
+
return interpret(node.expression);
|
|
407
|
+
}
|
|
408
|
+
else if (ts.isPropertyAccessExpression(node)) {
|
|
409
|
+
// PropertyAccessExpression - 属性访问表达式
|
|
410
|
+
const memberExpr = new nasl_concepts_1.MemberExpression();
|
|
411
|
+
memberExpr.object = interpret(node.expression);
|
|
412
|
+
memberExpr.property = new nasl_concepts_1.Identifier({ name: node.name.text });
|
|
413
|
+
return memberExpr;
|
|
414
|
+
}
|
|
415
|
+
else if (ts.isSpreadAssignment(node)) {
|
|
416
|
+
// SpreadAssignment - 展开赋值
|
|
417
|
+
throw new Error(`SpreadAssignment not implemented: ${ts.tokenToString(node.kind)}`);
|
|
418
|
+
}
|
|
419
|
+
else if (ts.isVariableStatement(node)) {
|
|
420
|
+
}
|
|
421
|
+
else if (ts.isVariableDeclarationList(node)) {
|
|
422
|
+
// VariableDeclarationList - 变量声明列表
|
|
423
|
+
node.declarations.forEach((decl) => {
|
|
424
|
+
if (ts.isVariableDeclaration(decl)) {
|
|
425
|
+
interpret(decl);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
430
|
+
else if (ts.isArrayLiteralExpression(node)) {
|
|
431
|
+
// 创建 $InternalTuple 调用
|
|
432
|
+
const call = new nasl_concepts_1.CallLogic();
|
|
433
|
+
const kind = ts.tokenToString(node.kind) || ts.SyntaxKind[node.kind];
|
|
434
|
+
const args = node?.elements?.map?.((element, index) => {
|
|
435
|
+
const keyword = `$ArrayParams${index + 1}`;
|
|
436
|
+
const expression = interpret(element);
|
|
437
|
+
const argument = new nasl_concepts_1.Argument({ keyword, expression });
|
|
438
|
+
argument.parentNode = call;
|
|
439
|
+
expression && (expression.parentNode = argument);
|
|
440
|
+
return argument;
|
|
441
|
+
}) || [];
|
|
442
|
+
call.calleeName = `$InternalTuple${args.length}`;
|
|
443
|
+
call.calleeNamespace = 'nasl.core';
|
|
444
|
+
call.arguments = args;
|
|
445
|
+
return call;
|
|
446
|
+
}
|
|
447
|
+
else if (ts.isParenthesizedExpression(node)) {
|
|
448
|
+
return interpret(node.expression);
|
|
449
|
+
}
|
|
450
|
+
else if (ts.isExpressionStatement(node)) {
|
|
451
|
+
return interpret(node.expression);
|
|
452
|
+
}
|
|
453
|
+
else if (ts.isBinaryExpression(node)) {
|
|
454
|
+
const result = new nasl_concepts_1.BinaryExpression();
|
|
455
|
+
result.left = interpret(node.left);
|
|
456
|
+
result.right = interpret(node.right);
|
|
457
|
+
result.operator = node.operatorToken.getText();
|
|
458
|
+
return result;
|
|
459
|
+
}
|
|
460
|
+
else if (ts.isElementAccessExpression(node)) {
|
|
461
|
+
const result = new nasl_concepts_1.CallFunction();
|
|
462
|
+
result.calleeName = 'Get';
|
|
463
|
+
result.calleeNamespace = 'nasl.util';
|
|
464
|
+
result.arguments = [
|
|
465
|
+
interpret(node.expression),
|
|
466
|
+
interpret(node.argumentExpression),
|
|
467
|
+
];
|
|
468
|
+
return result;
|
|
469
|
+
}
|
|
470
|
+
else if (ts.SyntaxKind.NullKeyword === node.kind) {
|
|
471
|
+
const result = new nasl_concepts_1.NullLiteral();
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
else if (ts.isSourceFile(node)) {
|
|
475
|
+
// SourceFile 节点不需要处理
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
// 收集未支持的表达式类型
|
|
479
|
+
const kind = ts.tokenToString(node.kind) || ts.SyntaxKind[node.kind];
|
|
480
|
+
this.unsupportedTypes.add(kind);
|
|
481
|
+
throw new Error(`未支持的表达式类型: ${kind}`);
|
|
482
|
+
}
|
|
483
|
+
ts.visitEachChild(node, visitor, undefined);
|
|
484
|
+
return undefined;
|
|
485
|
+
};
|
|
486
|
+
// 创建visitor函数来遍历AST节点
|
|
487
|
+
const visitor = (node) => {
|
|
488
|
+
interpret(node);
|
|
489
|
+
return node;
|
|
490
|
+
};
|
|
491
|
+
// 遍历source中的所有变量声明,将它收集到variables中
|
|
492
|
+
ts.visitNode(source, visitor);
|
|
493
|
+
fn.variables = variables;
|
|
494
|
+
fn.body = body;
|
|
495
|
+
fn.returns = returns;
|
|
496
|
+
// 打印统计的未支持表达式类型
|
|
497
|
+
this.printUnsupportedTypes();
|
|
498
|
+
// 输出收集到的所有SyntaxKind数组
|
|
499
|
+
// console.log('[TS-Parser] 去重后的SyntaxKind:', [...new Set(syntaxKinds)]);
|
|
500
|
+
// @ts-expect-error
|
|
501
|
+
fn.parentNode = { concept: 'App' };
|
|
502
|
+
return fn;
|
|
503
|
+
}
|
|
504
|
+
parseAndTransform(code) {
|
|
505
|
+
try {
|
|
506
|
+
return (0, chain_call_transformer_1.transformChainCalls)(code);
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
console.error('Failed to parse TypeScript code:', error);
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
parse(code) {
|
|
514
|
+
try {
|
|
515
|
+
const sourceFile = ts.createSourceFile('temp.ts', code, ts.ScriptTarget.Latest, true);
|
|
516
|
+
return sourceFile;
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
console.error('Failed to parse TypeScript code:', error);
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* 打印统计的未支持表达式类型
|
|
525
|
+
*/
|
|
526
|
+
printUnsupportedTypes() {
|
|
527
|
+
if (this.unsupportedTypes.size > 0) {
|
|
528
|
+
console.log('\n=== 未支持的表达式类型统计 ===');
|
|
529
|
+
console.log(`总计: ${this.unsupportedTypes.size} 种类型`);
|
|
530
|
+
const sortedTypes = Array.from(this.unsupportedTypes).sort();
|
|
531
|
+
sortedTypes.forEach((type, index) => {
|
|
532
|
+
console.log(`${index + 1}. ${type}`);
|
|
533
|
+
});
|
|
534
|
+
console.log('================================\n');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* 清空未支持类型统计
|
|
539
|
+
*/
|
|
540
|
+
clearUnsupportedTypes() {
|
|
541
|
+
this.unsupportedTypes.clear();
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* 获取未支持类型列表
|
|
545
|
+
*/
|
|
546
|
+
getUnsupportedTypes() {
|
|
547
|
+
return Array.from(this.unsupportedTypes);
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* 解析表达式,提取 namespace 和 name
|
|
551
|
+
* @param expression TypeScript 表达式节点
|
|
552
|
+
* @returns { namespace?: string, name: string }
|
|
553
|
+
*
|
|
554
|
+
* 示例:
|
|
555
|
+
* - a.b.c -> { namespace: "a.b", name: "c" }
|
|
556
|
+
* - c -> { name: "c" }
|
|
557
|
+
*/
|
|
558
|
+
parseExpressionNamespace(expression) {
|
|
559
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
560
|
+
// 处理 a.b.c 形式
|
|
561
|
+
const parts = [];
|
|
562
|
+
let current = expression;
|
|
563
|
+
// 从右到左收集所有部分
|
|
564
|
+
while (ts.isPropertyAccessExpression(current)) {
|
|
565
|
+
parts.unshift(current.name.text);
|
|
566
|
+
current = current.expression;
|
|
567
|
+
}
|
|
568
|
+
// 最左边应该是一个 Identifier
|
|
569
|
+
if (ts.isIdentifier(current)) {
|
|
570
|
+
parts.unshift(current.text);
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
// 如果不是 Identifier,使用 getText() 作为备选
|
|
574
|
+
parts.unshift(current.getText());
|
|
575
|
+
}
|
|
576
|
+
if (parts.length === 1) {
|
|
577
|
+
// 只有一个部分,没有 namespace
|
|
578
|
+
return { name: parts[0] };
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
// 多个部分,最后一个是 name,其余是 namespace
|
|
582
|
+
const name = parts.pop();
|
|
583
|
+
const namespace = parts.join('.');
|
|
584
|
+
return { namespace, name };
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
else if (ts.isIdentifier(expression)) {
|
|
588
|
+
// 处理单独的标识符 c
|
|
589
|
+
return { name: expression.text };
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
// 其他类型的表达式,使用 getText() 作为 name
|
|
593
|
+
return { name: expression.getText() };
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* 解析TypeScript的TypeNode为NASL的TypeAnnotation
|
|
598
|
+
* @param typeNode TypeScript 类型节点
|
|
599
|
+
* @returns TypeAnnotation 或 undefined
|
|
600
|
+
*/
|
|
601
|
+
interpretType(typeNode) {
|
|
602
|
+
const syntaxKind = ts.SyntaxKind[typeNode.kind];
|
|
603
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
604
|
+
// 处理类型引用节点,如 Array<T> 或 MyType
|
|
605
|
+
const typeName = typeNode.typeName;
|
|
606
|
+
let namespace;
|
|
607
|
+
let name;
|
|
608
|
+
if (ts.isQualifiedName(typeName)) {
|
|
609
|
+
// 处理限定名,如 A.B.C
|
|
610
|
+
const parts = [];
|
|
611
|
+
let current = typeName;
|
|
612
|
+
while (ts.isQualifiedName(current)) {
|
|
613
|
+
parts.unshift(current.right.text);
|
|
614
|
+
current = current.left;
|
|
615
|
+
}
|
|
616
|
+
if (ts.isIdentifier(current)) {
|
|
617
|
+
parts.unshift(current.text);
|
|
618
|
+
}
|
|
619
|
+
if (parts.length === 1) {
|
|
620
|
+
name = parts[0];
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
name = parts.pop();
|
|
624
|
+
namespace = parts.join('.');
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
else if (ts.isIdentifier(typeName)) {
|
|
628
|
+
// 简单标识符
|
|
629
|
+
name = typeName.text;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
name = typeNode.getText();
|
|
633
|
+
}
|
|
634
|
+
const typeAnnotation = nasl_concepts_1.TypeAnnotation.createReference(name, {
|
|
635
|
+
typeNamespace: namespace,
|
|
636
|
+
});
|
|
637
|
+
// 处理泛型参数
|
|
638
|
+
if (typeNode.typeArguments && typeNode.typeArguments.length > 0) {
|
|
639
|
+
const genericArgs = [];
|
|
640
|
+
typeNode.typeArguments.forEach((arg) => {
|
|
641
|
+
const argType = this.interpretType(arg);
|
|
642
|
+
if (argType) {
|
|
643
|
+
genericArgs.push(argType);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
typeAnnotation.typeArguments = genericArgs;
|
|
647
|
+
}
|
|
648
|
+
return typeAnnotation;
|
|
649
|
+
}
|
|
650
|
+
else if (typeNode.kind === ts.SyntaxKind.StringKeyword) {
|
|
651
|
+
// string 类型
|
|
652
|
+
return nasl_concepts_1.TypeAnnotation.createReference('String');
|
|
653
|
+
}
|
|
654
|
+
else if (typeNode.kind === ts.SyntaxKind.NumberKeyword) {
|
|
655
|
+
// number 类型
|
|
656
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Double');
|
|
657
|
+
}
|
|
658
|
+
else if (typeNode.kind === ts.SyntaxKind.BooleanKeyword) {
|
|
659
|
+
// boolean 类型
|
|
660
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Boolean');
|
|
661
|
+
}
|
|
662
|
+
else if (typeNode.kind === ts.SyntaxKind.VoidKeyword) {
|
|
663
|
+
// void 类型
|
|
664
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Void');
|
|
665
|
+
}
|
|
666
|
+
else if (typeNode.kind === ts.SyntaxKind.AnyKeyword) {
|
|
667
|
+
// any 类型
|
|
668
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Any');
|
|
669
|
+
}
|
|
670
|
+
else if (ts.isArrayTypeNode(typeNode)) {
|
|
671
|
+
// 数组类型,如 string[]
|
|
672
|
+
const elementType = this.interpretType(typeNode.elementType);
|
|
673
|
+
if (elementType) {
|
|
674
|
+
return nasl_concepts_1.TypeAnnotation.createReference('List', {
|
|
675
|
+
typeArguments: [elementType],
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
else if (ts.isUnionTypeNode(typeNode)) {
|
|
680
|
+
// 联合类型,如 string | number
|
|
681
|
+
// 暂时取第一个类型作为主要类型
|
|
682
|
+
if (typeNode.types.length > 0) {
|
|
683
|
+
return this.interpretType(typeNode.types[0]);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
else if (ts.isLiteralTypeNode(typeNode)) {
|
|
687
|
+
// 字面量类型,如 "hello" | 42
|
|
688
|
+
if (ts.isStringLiteral(typeNode.literal)) {
|
|
689
|
+
return nasl_concepts_1.TypeAnnotation.createReference('String');
|
|
690
|
+
}
|
|
691
|
+
else if (ts.isNumericLiteral(typeNode.literal)) {
|
|
692
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Double');
|
|
693
|
+
}
|
|
694
|
+
else if (typeNode.literal.kind === ts.SyntaxKind.TrueKeyword ||
|
|
695
|
+
typeNode.literal.kind === ts.SyntaxKind.FalseKeyword) {
|
|
696
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Boolean');
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
// 收集未支持的类型
|
|
700
|
+
this.unsupportedTypes.add(syntaxKind);
|
|
701
|
+
// 默认返回Any类型
|
|
702
|
+
return nasl_concepts_1.TypeAnnotation.createReference('Any');
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
exports.TypeScriptNASLParser = TypeScriptNASLParser;
|
|
706
|
+
//# sourceMappingURL=ts-parser.js.map
|