@abaplint/transpiler 2.10.28 → 2.10.29
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/build/src/expressions/method_call.js +5 -0
- package/build/src/feature_flags.d.ts +3 -0
- package/build/src/feature_flags.js +7 -0
- package/build/src/statements/class_implementation.js +1 -0
- package/build/src/statements/method_implementation.js +9 -2
- package/build/src/structures/class_definition.js +1 -0
- package/build/src/traversal.d.ts +2 -0
- package/build/src/traversal.js +35 -8
- package/build/src/unit_test.js +4 -54
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ const core_1 = require("@abaplint/core");
|
|
|
5
5
|
const traversal_1 = require("../traversal");
|
|
6
6
|
const method_call_param_1 = require("./method_call_param");
|
|
7
7
|
const chunk_1 = require("../chunk");
|
|
8
|
+
const feature_flags_1 = require("../feature_flags");
|
|
8
9
|
class MethodCallTranspiler {
|
|
9
10
|
transpile(node, traversal) {
|
|
10
11
|
const nameToken = node.findDirectExpression(core_1.Expressions.MethodName)?.getFirstToken();
|
|
@@ -22,6 +23,10 @@ class MethodCallTranspiler {
|
|
|
22
23
|
if (m?.name && traversal.isBuiltinMethod(nameToken) === false) {
|
|
23
24
|
name = m.name.toLowerCase() + "(";
|
|
24
25
|
}
|
|
26
|
+
if (feature_flags_1.FEATURE_FLAGS.private === true
|
|
27
|
+
&& m?.def.getVisibility() === core_1.Visibility.Private) {
|
|
28
|
+
name = "#" + name;
|
|
29
|
+
}
|
|
25
30
|
const step = node.findDirectExpression(core_1.Expressions.MethodCallParam);
|
|
26
31
|
if (step === undefined) {
|
|
27
32
|
throw new Error("MethodCallTranspiler, unexpected node");
|
|
@@ -23,6 +23,7 @@ static INTERNAL_TYPE = 'CLAS';
|
|
|
23
23
|
static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';
|
|
24
24
|
static IMPLEMENTED_INTERFACES = [${this.findImplementedByClass(traversal, def, scope).map(e => `"` + e.toUpperCase() + `"`).join(",")}];
|
|
25
25
|
static ATTRIBUTES = {${traversal.buildAttributes(def, scope).join(",\n")}};
|
|
26
|
+
static FRIENDS_ACCESS_STATIC = {}; // todo
|
|
26
27
|
static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};`, node, traversal);
|
|
27
28
|
}
|
|
28
29
|
findImplementedInterface(traversal, def, scope) {
|
|
@@ -8,6 +8,7 @@ const traversal_1 = require("../traversal");
|
|
|
8
8
|
const expressions_1 = require("../expressions");
|
|
9
9
|
const chunk_1 = require("../chunk");
|
|
10
10
|
const unique_identifier_1 = require("../unique_identifier");
|
|
11
|
+
const feature_flags_1 = require("../feature_flags");
|
|
11
12
|
class MethodImplementationTranspiler {
|
|
12
13
|
transpile(node, traversal) {
|
|
13
14
|
const token = node.findFirstExpression(abaplint.Expressions.MethodName).getFirstToken();
|
|
@@ -116,15 +117,21 @@ class MethodImplementationTranspiler {
|
|
|
116
117
|
methodName = a.getComponent().replace("~", "$").toLowerCase();
|
|
117
118
|
}
|
|
118
119
|
}
|
|
120
|
+
// https://github.com/tc39/proposal-class-fields
|
|
121
|
+
let isPrivate = "";
|
|
122
|
+
if (feature_flags_1.FEATURE_FLAGS.private === true
|
|
123
|
+
&& method?.getVisibility() === abaplint.Visibility.Private) {
|
|
124
|
+
isPrivate = "#";
|
|
125
|
+
}
|
|
119
126
|
if (method && method.isStatic()) {
|
|
120
127
|
// in ABAP static methods can be called with instance arrows, "->"
|
|
121
128
|
const className = scope.getParent()?.getIdentifier().sname?.toLowerCase();
|
|
122
|
-
staticMethod = "async " + traversal_1.Traversal.escapeNamespace(methodName) + "(" + unique + ") {\n" +
|
|
129
|
+
staticMethod = "async " + isPrivate + traversal_1.Traversal.escapeNamespace(methodName) + "(" + unique + ") {\n" +
|
|
123
130
|
"return " + traversal_1.Traversal.escapeNamespace(className) + "." + traversal_1.Traversal.escapeNamespace(methodName) + "(" + unique + ");\n" +
|
|
124
131
|
"}\n" + "static ";
|
|
125
132
|
}
|
|
126
133
|
unique_identifier_1.UniqueIdentifier.resetIndexBackup();
|
|
127
|
-
const str = staticMethod + "async " + traversal_1.Traversal.escapeNamespace(methodName) + "(" + unique + ") {" + after;
|
|
134
|
+
const str = staticMethod + "async " + isPrivate + traversal_1.Traversal.escapeNamespace(methodName) + "(" + unique + ") {" + after;
|
|
128
135
|
return new chunk_1.Chunk().append(str, node, traversal);
|
|
129
136
|
}
|
|
130
137
|
/////////////////////////////
|
|
@@ -25,6 +25,7 @@ class ${className?.toLowerCase()} {
|
|
|
25
25
|
static IMPLEMENTED_INTERFACES = [];
|
|
26
26
|
static INTERNAL_NAME = 'ABSTRACT_CLASS_INTERNAL_NAME';
|
|
27
27
|
static ATTRIBUTES = {};
|
|
28
|
+
static FRIENDS_ACCESS_STATIC = {};
|
|
28
29
|
async constructor_() {
|
|
29
30
|
this.me = new abap.types.ABAPObject();
|
|
30
31
|
this.me.set(this);
|
package/build/src/traversal.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export declare class Traversal {
|
|
|
39
39
|
isTypePool(token: abaplint.Token): string | undefined;
|
|
40
40
|
isInterfaceAttribute(token: abaplint.Token): string | undefined;
|
|
41
41
|
private findReadOrWriteReference;
|
|
42
|
+
private buildThisAttributes;
|
|
43
|
+
private buildFriendsAccess;
|
|
42
44
|
buildConstructorContents(scope: abaplint.ISpaghettiScopeNode | undefined, def: abaplint.IClassDefinition): string;
|
|
43
45
|
findInterfaceDefinition(name: string, scope: abaplint.ISpaghettiScopeNode | undefined): abaplint.IInterfaceDefinition | undefined;
|
|
44
46
|
findTable(name: string): abaplint.Objects.Table | undefined;
|
package/build/src/traversal.js
CHANGED
|
@@ -9,6 +9,7 @@ const transpile_types_1 = require("./transpile_types");
|
|
|
9
9
|
const chunk_1 = require("./chunk");
|
|
10
10
|
const expressions_1 = require("./expressions");
|
|
11
11
|
const keywords_1 = require("./keywords");
|
|
12
|
+
const feature_flags_1 = require("./feature_flags");
|
|
12
13
|
class Traversal {
|
|
13
14
|
constructor(spaghetti, file, obj, reg, options) {
|
|
14
15
|
this.scopeCache = undefined;
|
|
@@ -376,15 +377,8 @@ class Traversal {
|
|
|
376
377
|
}
|
|
377
378
|
return undefined;
|
|
378
379
|
}
|
|
379
|
-
|
|
380
|
+
buildThisAttributes(def, cName) {
|
|
380
381
|
let ret = "";
|
|
381
|
-
if (def.getSuperClass() !== undefined || def.getName().toUpperCase() === "CX_ROOT") {
|
|
382
|
-
ret += "super();\n";
|
|
383
|
-
}
|
|
384
|
-
const cName = Traversal.escapeNamespace(def.getName().toLowerCase());
|
|
385
|
-
ret += `this.me = new abap.types.ABAPObject();
|
|
386
|
-
this.me.set(this);
|
|
387
|
-
this.INTERNAL_ID = abap.internalIdCounter++;\n`;
|
|
388
382
|
for (const a of def.getAttributes()?.getAll() || []) {
|
|
389
383
|
const escaped = Traversal.escapeNamespace(a.getName().toLowerCase());
|
|
390
384
|
if (a.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) === true) {
|
|
@@ -395,6 +389,39 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
|
|
|
395
389
|
ret += name + " = " + new transpile_types_1.TranspileTypes().toType(a.getType()) + ";\n";
|
|
396
390
|
ret += this.setValues(a, name);
|
|
397
391
|
}
|
|
392
|
+
return ret;
|
|
393
|
+
}
|
|
394
|
+
buildFriendsAccess(def, hasSuperClass) {
|
|
395
|
+
let ret = "this.FRIENDS_ACCESS_INSTANCE = {\n";
|
|
396
|
+
if (hasSuperClass === true) {
|
|
397
|
+
ret += `"SUPER": sup.FRIENDS_ACCESS_INSTANCE,\n`;
|
|
398
|
+
}
|
|
399
|
+
for (const a of def.getMethodDefinitions()?.getAll() || []) {
|
|
400
|
+
const name = a.getName().toLowerCase();
|
|
401
|
+
if (name === "constructor" || a.isStatic() === true) {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
let privateHash = "";
|
|
405
|
+
if (feature_flags_1.FEATURE_FLAGS.private === true && a.getVisibility() === abaplint.Visibility.Private) {
|
|
406
|
+
privateHash = "#";
|
|
407
|
+
}
|
|
408
|
+
const methodName = privateHash + Traversal.escapeNamespace(name.replace("~", "$"));
|
|
409
|
+
ret += `"${name.replace("~", "$")}": this.${methodName}.bind(this),\n`;
|
|
410
|
+
}
|
|
411
|
+
ret += "};\n";
|
|
412
|
+
return ret;
|
|
413
|
+
}
|
|
414
|
+
buildConstructorContents(scope, def) {
|
|
415
|
+
let ret = "";
|
|
416
|
+
if (def.getSuperClass() !== undefined || def.getName().toUpperCase() === "CX_ROOT") {
|
|
417
|
+
ret += "const sup = super();\n";
|
|
418
|
+
}
|
|
419
|
+
const cName = Traversal.escapeNamespace(def.getName().toLowerCase());
|
|
420
|
+
ret += `this.me = new abap.types.ABAPObject();
|
|
421
|
+
this.me.set(this);
|
|
422
|
+
this.INTERNAL_ID = abap.internalIdCounter++;\n`;
|
|
423
|
+
ret += this.buildFriendsAccess(def, def.getSuperClass() !== undefined);
|
|
424
|
+
ret += this.buildThisAttributes(def, cName);
|
|
398
425
|
// attributes from directly implemented interfaces(not interfaces implemented in super classes)
|
|
399
426
|
for (const i of def.getImplementing()) {
|
|
400
427
|
ret += this.dataFromInterfaces(i.name, scope, cName);
|
package/build/src/unit_test.js
CHANGED
|
@@ -225,10 +225,13 @@ async function run() {
|
|
|
225
225
|
continue;
|
|
226
226
|
}
|
|
227
227
|
ret += ` {\n const test = await (new ${lc}()).constructor_();\n`;
|
|
228
|
+
// todo, some refactoring here,
|
|
228
229
|
ret += ` if (test.setup) await test.setup();\n`;
|
|
230
|
+
ret += ` if (test.FRIENDS_ACCESS_INSTANCE.setup) await test.FRIENDS_ACCESS_INSTANCE.setup();\n`;
|
|
231
|
+
ret += ` if (test.FRIENDS_ACCESS_INSTANCE.SUPER && test.FRIENDS_ACCESS_INSTANCE.SUPER.setup) await test.FRIENDS_ACCESS_INSTANCE.SUPER.setup();\n`;
|
|
229
232
|
ret += ` console.log("${st.obj.getName()}: running ${lc}->${m}");\n`;
|
|
230
233
|
ret += ` meth = locl.addMethod("${m}");\n`;
|
|
231
|
-
ret += ` await test.${m}();\n`;
|
|
234
|
+
ret += ` await test.FRIENDS_ACCESS_INSTANCE.${m}();\n`;
|
|
232
235
|
ret += ` meth.pass();\n`;
|
|
233
236
|
ret += ` if (test.teardown) await test.teardown();\n`;
|
|
234
237
|
ret += ` }\n`;
|
|
@@ -236,59 +239,6 @@ async function run() {
|
|
|
236
239
|
ret += ` if (${lc}.class_teardown) await ${lc}.class_teardown();\n`;
|
|
237
240
|
ret += ` }\n`;
|
|
238
241
|
}
|
|
239
|
-
/*
|
|
240
|
-
for (const obj of reg.getObjects()) {
|
|
241
|
-
if (reg.isDependency(obj) || !(obj instanceof abaplint.Objects.Class)) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
ret += `// --------------------------------------------\n`;
|
|
245
|
-
ret += ` clas = unit.addObject("${obj.getName()}");\n`;
|
|
246
|
-
for (const file of obj.getABAPFiles()) {
|
|
247
|
-
for (const def of file.getInfo().listClassDefinitions()) {
|
|
248
|
-
if (def.isForTesting === false
|
|
249
|
-
|| def.isGlobal === true
|
|
250
|
-
|| def.methods.length === 0
|
|
251
|
-
|| def.isAbstract === true) {
|
|
252
|
-
// todo, fix, there might be global test methods
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
|
|
256
|
-
if (hasTestFile === false) {
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
ret += ` {
|
|
260
|
-
const {${def.name}} = await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}.testclasses.mjs");
|
|
261
|
-
locl = clas.addTestClass("${def.name}");
|
|
262
|
-
if (${def.name}.class_setup) await ${def.name}.class_setup();\n`;
|
|
263
|
-
|
|
264
|
-
for (const m of def.methods) {
|
|
265
|
-
if (m.isForTesting === false) {
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
const skipThis = (skip || []).some(a => a.object === obj.getName() && a.class === def.name && a.method === m.name);
|
|
269
|
-
if (skipThis) {
|
|
270
|
-
ret += ` console.log('${obj.getName()}: running ${def.name}->${m.name}, skipped');\n`;
|
|
271
|
-
ret += ` meth = locl.addMethod("${m.name}");\n`;
|
|
272
|
-
ret += ` meth.skip();\n`;
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
ret += ` {\n const test = await (new ${def.name}()).constructor_();\n`;
|
|
277
|
-
ret += ` if (test.setup) await test.setup();\n`;
|
|
278
|
-
ret += ` console.log("${obj.getName()}: running ${def.name}->${m.name}");\n`;
|
|
279
|
-
ret += ` meth = locl.addMethod("${m.name}");\n`;
|
|
280
|
-
ret += ` await test.${m.name}();\n`;
|
|
281
|
-
ret += ` meth.pass();\n`;
|
|
282
|
-
ret += ` if (test.teardown) await test.teardown();\n`;
|
|
283
|
-
ret += ` }\n`;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
ret += ` if (${def.name}.class_teardown) await ${def.name}.class_teardown();\n`;
|
|
287
|
-
ret += ` }\n`;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
*/
|
|
292
242
|
ret += `// -------------------END-------------------
|
|
293
243
|
fs.writeFileSync(__dirname + path.sep + "_output.xml", unit.xUnitXML());
|
|
294
244
|
} catch (e) {
|