@abaplint/transpiler 2.0.26 → 2.0.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/README.md +2 -2
- package/build/src/expressions/source.js +14 -9
- package/build/src/handle_abap.js +3 -3
- package/build/src/handle_data_element.js +5 -5
- package/build/src/handle_table.js +4 -4
- package/build/src/handle_table_type.js +3 -3
- package/build/src/requires.js +1 -1
- package/build/src/statements/class_implementation.js +2 -1
- package/build/src/statements/do.js +4 -4
- package/build/src/statements/end_method.js +1 -1
- package/build/src/statements/method_implementation.js +7 -6
- package/build/src/statements/return.js +1 -1
- package/build/src/statements/select.d.ts +1 -0
- package/build/src/statements/select.js +27 -5
- package/build/src/structures/class_implementation.js +2 -1
- package/build/src/structures/interface.js +2 -2
- package/build/src/traversal.d.ts +1 -0
- package/build/src/traversal.js +11 -8
- package/build/src/unit_test.d.ts +1 -0
- package/build/src/unit_test.js +79 -75
- package/package.json +42 -42
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# @abaplint/transpiler
|
|
2
|
-
|
|
1
|
+
# @abaplint/transpiler
|
|
2
|
+
|
|
3
3
|
Transpiler
|
|
@@ -12,7 +12,10 @@ class SourceTranspiler {
|
|
|
12
12
|
transpile(node, traversal) {
|
|
13
13
|
let ret = new chunk_1.Chunk();
|
|
14
14
|
const post = new chunk_1.Chunk();
|
|
15
|
-
|
|
15
|
+
const children = node.getChildren();
|
|
16
|
+
for (let i = 0; i < children.length; i++) {
|
|
17
|
+
const c = children[i];
|
|
18
|
+
const last = i === children.length - 1;
|
|
16
19
|
if (c instanceof core_1.Nodes.ExpressionNode) {
|
|
17
20
|
if (c.get() instanceof core_1.Expressions.FieldChain) {
|
|
18
21
|
ret.appendChunk(new _1.FieldChainTranspiler(this.addGet).transpile(c, traversal));
|
|
@@ -35,14 +38,12 @@ class SourceTranspiler {
|
|
|
35
38
|
}
|
|
36
39
|
else if (c.get() instanceof core_1.Expressions.MethodCallChain) {
|
|
37
40
|
ret.appendChunk(traversal.traverse(c));
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ret.append(".get()", c, traversal);
|
|
45
|
-
}
|
|
41
|
+
const code = ret.getCode();
|
|
42
|
+
if (code.includes("await")) {
|
|
43
|
+
ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(")");
|
|
44
|
+
}
|
|
45
|
+
if (this.addGet && last === true) {
|
|
46
|
+
ret.append(".get()", c, traversal);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
else if (c.get() instanceof core_1.Expressions.Source) {
|
|
@@ -57,6 +58,9 @@ class SourceTranspiler {
|
|
|
57
58
|
else if (c.get() instanceof core_1.Expressions.ComponentChain) {
|
|
58
59
|
ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(").get().");
|
|
59
60
|
ret.appendChunk(new _1.ComponentChainTranspiler().transpile(c, traversal));
|
|
61
|
+
if (this.addGet && last === true) {
|
|
62
|
+
ret.append(".get()", c, traversal);
|
|
63
|
+
}
|
|
60
64
|
}
|
|
61
65
|
else if (c.get() instanceof core_1.Expressions.Dereference) {
|
|
62
66
|
ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(").getPointer()");
|
|
@@ -82,6 +86,7 @@ class SourceTranspiler {
|
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
ret.appendChunk(post);
|
|
89
|
+
// console.dir(ret.getCode());
|
|
85
90
|
return ret;
|
|
86
91
|
}
|
|
87
92
|
}
|
package/build/src/handle_abap.js
CHANGED
|
@@ -105,15 +105,15 @@ class HandleABAP {
|
|
|
105
105
|
continue;
|
|
106
106
|
}
|
|
107
107
|
if (name) {
|
|
108
|
-
contents.appendString("const {" + name + "} = await import(\"./" + filename + "\");\n");
|
|
108
|
+
contents.appendString("const {" + traversal_1.Traversal.escapeClassName(name) + "} = await import(\"./" + filename.replace(/#/g, "%23") + "\");\n");
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
contents.appendString("await import(\"./" + filename + "\");\n");
|
|
111
|
+
contents.appendString("await import(\"./" + filename.replace(/#/g, "%23") + "\");\n");
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
contents.appendChunk(output.chunk);
|
|
115
115
|
if (output.exports.length > 0) {
|
|
116
|
-
contents.appendString("\nexport {" + output.exports.join(", ") + "};");
|
|
116
|
+
contents.appendString("\nexport {" + output.exports.map(traversal_1.Traversal.escapeClassName).join(", ") + "};");
|
|
117
117
|
}
|
|
118
118
|
return contents;
|
|
119
119
|
}
|
|
@@ -18,11 +18,11 @@ class HandleDataElement {
|
|
|
18
18
|
fixedValues = doma.getFixedValues();
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
22
|
-
"objectType": "DTEL",
|
|
23
|
-
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
24
|
-
"domain": ${JSON.stringify(obj.getDomainName())},
|
|
25
|
-
"fixedValues": ${JSON.stringify(fixedValues)},
|
|
21
|
+
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
22
|
+
"objectType": "DTEL",
|
|
23
|
+
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
24
|
+
"domain": ${JSON.stringify(obj.getDomainName())},
|
|
25
|
+
"fixedValues": ${JSON.stringify(fixedValues)},
|
|
26
26
|
};`);
|
|
27
27
|
const output = {
|
|
28
28
|
object: {
|
|
@@ -12,10 +12,10 @@ class HandleTable {
|
|
|
12
12
|
return [];
|
|
13
13
|
}
|
|
14
14
|
const type = obj.parseType(reg);
|
|
15
|
-
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
16
|
-
"objectType": "TABL",
|
|
17
|
-
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
18
|
-
"keyFields": ${JSON.stringify(obj.listKeys())},
|
|
15
|
+
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
16
|
+
"objectType": "TABL",
|
|
17
|
+
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
18
|
+
"keyFields": ${JSON.stringify(obj.listKeys())},
|
|
19
19
|
};`);
|
|
20
20
|
const output = {
|
|
21
21
|
object: {
|
|
@@ -11,9 +11,9 @@ class HandleTableType {
|
|
|
11
11
|
return [];
|
|
12
12
|
}
|
|
13
13
|
const type = obj.parseType(reg);
|
|
14
|
-
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
15
|
-
"objectType": "TTYP",
|
|
16
|
-
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
14
|
+
const chunk = new chunk_1.Chunk().appendString(`abap.DDIC["${obj.getName().toUpperCase()}"] = {
|
|
15
|
+
"objectType": "TTYP",
|
|
16
|
+
"type": ${new transpile_types_1.TranspileTypes().toType(type)},
|
|
17
17
|
};`);
|
|
18
18
|
const output = {
|
|
19
19
|
object: {
|
package/build/src/requires.js
CHANGED
|
@@ -28,7 +28,7 @@ class Requires {
|
|
|
28
28
|
if (obj.getType() === "CLAS") {
|
|
29
29
|
// add the superclass
|
|
30
30
|
const clas = obj;
|
|
31
|
-
const sup = (_b = (_a = clas.getDefinition()) === null || _a === void 0 ? void 0 : _a.getSuperClass()) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
31
|
+
const sup = (_b = (_a = clas.getDefinition()) === null || _a === void 0 ? void 0 : _a.getSuperClass()) === null || _b === void 0 ? void 0 : _b.toLowerCase().replace(/\//g, "%23");
|
|
32
32
|
if (sup) {
|
|
33
33
|
add({ filename: sup + ".clas.abap", name: sup });
|
|
34
34
|
}
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ClassImplementationTranspiler = void 0;
|
|
4
4
|
const abaplint = require("@abaplint/core");
|
|
5
|
+
const traversal_1 = require("../traversal");
|
|
5
6
|
const chunk_1 = require("../chunk");
|
|
6
7
|
class ClassImplementationTranspiler {
|
|
7
8
|
transpile(node, traversal) {
|
|
8
9
|
var _a;
|
|
9
10
|
const token = node.findFirstExpression(abaplint.Expressions.ClassName).getFirstToken();
|
|
10
11
|
const def = traversal.getClassDefinition(token);
|
|
11
|
-
let ret = "class " + token.getStr().toLowerCase();
|
|
12
|
+
let ret = "class " + traversal_1.Traversal.escapeClassName(token.getStr().toLowerCase());
|
|
12
13
|
if (token.getStr().toLowerCase() === "cx_root") {
|
|
13
14
|
// special case for exceptions
|
|
14
15
|
ret += " extends Error";
|
|
@@ -12,14 +12,14 @@ class DoTranspiler {
|
|
|
12
12
|
const source = new expressions_1.SourceTranspiler(true).transpile(found, traversal).getCode();
|
|
13
13
|
const idSource = unique_identifier_1.UniqueIdentifier.get();
|
|
14
14
|
const id = unique_identifier_1.UniqueIdentifier.get();
|
|
15
|
-
return new chunk_1.Chunk(`const ${idSource} = ${source};
|
|
16
|
-
for (let ${id} = 0; ${id} < ${idSource}; ${id}++) {
|
|
15
|
+
return new chunk_1.Chunk(`const ${idSource} = ${source};
|
|
16
|
+
for (let ${id} = 0; ${id} < ${idSource}; ${id}++) {
|
|
17
17
|
abap.builtin.sy.get().index.set(${id} + 1);`);
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
20
|
const unique = unique_identifier_1.UniqueIdentifier.get();
|
|
21
|
-
return new chunk_1.Chunk(`let ${unique} = 1;
|
|
22
|
-
while (true) {
|
|
21
|
+
return new chunk_1.Chunk(`let ${unique} = 1;
|
|
22
|
+
while (true) {
|
|
23
23
|
abap.builtin.sy.get().index.set(${unique}++);`);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -15,7 +15,7 @@ class EndMethodTranspiler {
|
|
|
15
15
|
const vars = scope.getData().vars;
|
|
16
16
|
for (const n in vars) {
|
|
17
17
|
const identifier = vars[n];
|
|
18
|
-
if (identifier.getMeta().includes("returning" /* MethodReturning */)) {
|
|
18
|
+
if (identifier.getMeta().includes("returning" /* abaplint.IdentifierMeta.MethodReturning */)) {
|
|
19
19
|
returning += "return " + n.toLowerCase() + ";\n";
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MethodImplementationTranspiler = void 0;
|
|
4
4
|
const abaplint = require("@abaplint/core");
|
|
5
5
|
const transpile_types_1 = require("../transpile_types");
|
|
6
|
+
const traversal_1 = require("../traversal");
|
|
6
7
|
const expressions_1 = require("../expressions");
|
|
7
8
|
const chunk_1 = require("../chunk");
|
|
8
9
|
class MethodImplementationTranspiler {
|
|
@@ -31,14 +32,14 @@ class MethodImplementationTranspiler {
|
|
|
31
32
|
for (const n in vars) {
|
|
32
33
|
const identifier = vars[n];
|
|
33
34
|
const varName = n.toLowerCase();
|
|
34
|
-
if (identifier.getMeta().includes("importing" /* MethodImporting */)
|
|
35
|
-
|| identifier.getMeta().includes("changing" /* MethodChanging */)
|
|
36
|
-
|| identifier.getMeta().includes("exporting" /* MethodExporting */)) {
|
|
35
|
+
if (identifier.getMeta().includes("importing" /* abaplint.IdentifierMeta.MethodImporting */)
|
|
36
|
+
|| identifier.getMeta().includes("changing" /* abaplint.IdentifierMeta.MethodChanging */)
|
|
37
|
+
|| identifier.getMeta().includes("exporting" /* abaplint.IdentifierMeta.MethodExporting */)) {
|
|
37
38
|
if (unique === "") {
|
|
38
39
|
unique = "INPUT";
|
|
39
40
|
}
|
|
40
41
|
after = after + new transpile_types_1.TranspileTypes().declare(identifier) + "\n";
|
|
41
|
-
if (identifier.getMeta().includes("importing" /* MethodImporting */) && identifier.getType().isGeneric() === false) {
|
|
42
|
+
if (identifier.getMeta().includes("importing" /* abaplint.IdentifierMeta.MethodImporting */) && identifier.getType().isGeneric() === false) {
|
|
42
43
|
after += "if (" + unique + " && " + unique + "." + varName + ") {" + varName + ".set(" + unique + "." + varName + ");}\n";
|
|
43
44
|
}
|
|
44
45
|
else {
|
|
@@ -71,7 +72,7 @@ class MethodImplementationTranspiler {
|
|
|
71
72
|
after += "if (" + unique + " === undefined || " + unique + "." + varName + " === undefined) {" + varName + " = " + val + ";}\n";
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
|
-
else if (identifier.getMeta().includes("returning" /* MethodReturning */)) {
|
|
75
|
+
else if (identifier.getMeta().includes("returning" /* abaplint.IdentifierMeta.MethodReturning */)) {
|
|
75
76
|
after = after + new transpile_types_1.TranspileTypes().declare(identifier) + "\n";
|
|
76
77
|
}
|
|
77
78
|
}
|
|
@@ -86,7 +87,7 @@ class MethodImplementationTranspiler {
|
|
|
86
87
|
// in ABAP static methods can be called with instance arrows, "->"
|
|
87
88
|
const className = (_b = (_a = scope.getParent()) === null || _a === void 0 ? void 0 : _a.getIdentifier().sname) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
88
89
|
staticMethod = "async " + methodName + "(" + unique + ") {\n" +
|
|
89
|
-
"return " + className + "." + methodName + "(" + unique + ");\n" +
|
|
90
|
+
"return " + traversal_1.Traversal.escapeClassName(className) + "." + methodName + "(" + unique + ");\n" +
|
|
90
91
|
"}\n" + "static ";
|
|
91
92
|
}
|
|
92
93
|
const str = staticMethod + "async " + methodName + "(" + unique + ") {" + after;
|
|
@@ -9,7 +9,7 @@ class ReturnTranspiler {
|
|
|
9
9
|
const vars = scope === null || scope === void 0 ? void 0 : scope.getData().vars;
|
|
10
10
|
for (const n in vars) {
|
|
11
11
|
const identifier = vars[n];
|
|
12
|
-
if (identifier.getMeta().includes("returning" /* MethodReturning */)) {
|
|
12
|
+
if (identifier.getMeta().includes("returning" /* abaplint.IdentifierMeta.MethodReturning */)) {
|
|
13
13
|
extra = " " + n.toLowerCase();
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -11,18 +11,23 @@ class SelectTranspiler {
|
|
|
11
11
|
let select = "SELECT ";
|
|
12
12
|
select += ((_a = node.findFirstExpression(abaplint.Expressions.SQLFieldList)) === null || _a === void 0 ? void 0 : _a.concatTokens()) + " ";
|
|
13
13
|
select += ((_b = node.findFirstExpression(abaplint.Expressions.SQLFrom)) === null || _b === void 0 ? void 0 : _b.concatTokens()) + " ";
|
|
14
|
-
|
|
14
|
+
let where;
|
|
15
|
+
for (const sqlCond of node.findAllExpressions(abaplint.Expressions.SQLCond)) {
|
|
16
|
+
if (this.isWhereExpression(node, sqlCond)) {
|
|
17
|
+
where = sqlCond;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
15
20
|
if (where) {
|
|
16
21
|
select += "WHERE " + this.concatCond(where, traversal) + " ";
|
|
17
22
|
}
|
|
18
|
-
const orderBy = node.findFirstExpression(abaplint.Expressions.SQLOrderBy);
|
|
19
|
-
if (orderBy) {
|
|
20
|
-
select += orderBy.concatTokens() + " ";
|
|
21
|
-
}
|
|
22
23
|
const upTo = node.findFirstExpression(abaplint.Expressions.SQLUpTo);
|
|
23
24
|
if (upTo) {
|
|
24
25
|
select += upTo.concatTokens() + " ";
|
|
25
26
|
}
|
|
27
|
+
const orderBy = node.findFirstExpression(abaplint.Expressions.SQLOrderBy);
|
|
28
|
+
if (orderBy) {
|
|
29
|
+
select += orderBy.concatTokens() + " ";
|
|
30
|
+
}
|
|
26
31
|
for (const d of node.findAllExpressionsRecursive(abaplint.Expressions.Dynamic)) {
|
|
27
32
|
const chain = d.findFirstExpression(abaplint.Expressions.FieldChain);
|
|
28
33
|
if (chain) {
|
|
@@ -69,6 +74,23 @@ class SelectTranspiler {
|
|
|
69
74
|
}
|
|
70
75
|
return ret.trim();
|
|
71
76
|
}
|
|
77
|
+
isWhereExpression(node, expression) {
|
|
78
|
+
// check if previous token before sqlCond is "WHERE". It could also be "ON" in case of join condition
|
|
79
|
+
let prevToken;
|
|
80
|
+
const sqlCondToken = expression.getFirstToken();
|
|
81
|
+
for (const token of node.getTokens()) {
|
|
82
|
+
if (token.getStart() === sqlCondToken.getStart()) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
prevToken = token;
|
|
86
|
+
}
|
|
87
|
+
if (prevToken && prevToken.getStr() === "WHERE") {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
72
94
|
}
|
|
73
95
|
exports.SelectTranspiler = SelectTranspiler;
|
|
74
96
|
//# sourceMappingURL=select.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ClassImplementationTranspiler = void 0;
|
|
4
4
|
const abaplint = require("@abaplint/core");
|
|
5
|
+
const traversal_1 = require("../traversal");
|
|
5
6
|
const transpile_types_1 = require("../transpile_types");
|
|
6
7
|
const expressions_1 = require("../expressions");
|
|
7
8
|
const chunk_1 = require("../chunk");
|
|
@@ -69,7 +70,7 @@ class ClassImplementationTranspiler {
|
|
|
69
70
|
const clasName = node.getFirstToken().getStr().toLowerCase();
|
|
70
71
|
const staticAttributes = this.findStaticAttributes(cdef, scope);
|
|
71
72
|
for (const attr of staticAttributes) {
|
|
72
|
-
const name = clasName + "." + attr.prefix + attr.identifier.getName().toLowerCase();
|
|
73
|
+
const name = traversal_1.Traversal.escapeClassName(clasName) + "." + attr.prefix + attr.identifier.getName().toLowerCase();
|
|
73
74
|
ret += name + " = " + new transpile_types_1.TranspileTypes().toType(attr.identifier.getType()) + ";\n";
|
|
74
75
|
const val = attr.identifier.getValue();
|
|
75
76
|
if (typeof val === "string") {
|
|
@@ -36,8 +36,8 @@ class InterfaceTranspiler {
|
|
|
36
36
|
let ret = "\n";
|
|
37
37
|
for (const n in vars) {
|
|
38
38
|
const identifier = vars[n];
|
|
39
|
-
if (identifier.getMeta().includes("static" /* Static */) === false
|
|
40
|
-
|| identifier.getMeta().includes("read_only" /* ReadOnly */) === false) {
|
|
39
|
+
if (identifier.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) === false
|
|
40
|
+
|| identifier.getMeta().includes("read_only" /* abaplint.IdentifierMeta.ReadOnly */) === false) {
|
|
41
41
|
continue;
|
|
42
42
|
}
|
|
43
43
|
const interfaceName = node.getFirstToken().getStr().toLowerCase();
|
package/build/src/traversal.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class Traversal {
|
|
|
8
8
|
private readonly reg;
|
|
9
9
|
readonly runtimeTypeError: boolean;
|
|
10
10
|
constructor(spaghetti: abaplint.ISpaghettiScope, file: abaplint.ABAPFile, obj: abaplint.ABAPObject, reg: abaplint.IRegistry, runtimeTypeError?: boolean);
|
|
11
|
+
static escapeClassName(name: string | undefined): string | undefined;
|
|
11
12
|
getCurrentObject(): abaplint.ABAPObject;
|
|
12
13
|
traverse(node: abaplint.INode | undefined): Chunk;
|
|
13
14
|
getFilename(): string;
|
package/build/src/traversal.js
CHANGED
|
@@ -16,6 +16,9 @@ class Traversal {
|
|
|
16
16
|
this.reg = reg;
|
|
17
17
|
this.runtimeTypeError = runtimeTypeError;
|
|
18
18
|
}
|
|
19
|
+
static escapeClassName(name) {
|
|
20
|
+
return name === null || name === void 0 ? void 0 : name.replace(/\//g, "$");
|
|
21
|
+
}
|
|
19
22
|
getCurrentObject() {
|
|
20
23
|
return this.obj;
|
|
21
24
|
}
|
|
@@ -121,17 +124,17 @@ class Traversal {
|
|
|
121
124
|
const found = this.reg.findObjectForFile(file);
|
|
122
125
|
if (found) {
|
|
123
126
|
if (found instanceof abaplint.Objects.Interface) {
|
|
124
|
-
return this.lookupClassOrInterface(found.getName(), t) + "." + found.getName().toLowerCase() + "$" + name;
|
|
127
|
+
return Traversal.escapeClassName(this.lookupClassOrInterface(found.getName(), t)) + "." + found.getName().toLowerCase() + "$" + name;
|
|
125
128
|
}
|
|
126
129
|
else {
|
|
127
|
-
return this.lookupClassOrInterface(found.getName(), t) + "." + name;
|
|
130
|
+
return Traversal.escapeClassName(this.lookupClassOrInterface(found.getName(), t)) + "." + name;
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
const className = this.isStaticClassAttribute(t);
|
|
133
136
|
if (className) {
|
|
134
|
-
name = className + "." + name;
|
|
137
|
+
name = Traversal.escapeClassName(className) + "." + name;
|
|
135
138
|
}
|
|
136
139
|
else if (name === "super") {
|
|
137
140
|
return name;
|
|
@@ -154,7 +157,7 @@ class Traversal {
|
|
|
154
157
|
const found = scope.findScopeForVariable(name);
|
|
155
158
|
const id = scope.findVariable(name);
|
|
156
159
|
if (found && id
|
|
157
|
-
&& id.getMeta().includes("static" /* Static */)
|
|
160
|
+
&& id.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */)
|
|
158
161
|
&& found.stype === abaplint.ScopeType.ClassImplementation) {
|
|
159
162
|
// console.dir(found.sname);
|
|
160
163
|
return found.sname.toLowerCase();
|
|
@@ -261,7 +264,7 @@ class Traversal {
|
|
|
261
264
|
ret += "this.me = new abap.types.ABAPObject();\n";
|
|
262
265
|
ret += "this.me.set(this);\n";
|
|
263
266
|
for (const a of def.getAttributes().getAll()) {
|
|
264
|
-
if (a.getMeta().includes("static" /* Static */) === true) {
|
|
267
|
+
if (a.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) === true) {
|
|
265
268
|
continue;
|
|
266
269
|
}
|
|
267
270
|
const name = a.getName().toLowerCase();
|
|
@@ -305,7 +308,7 @@ class Traversal {
|
|
|
305
308
|
let ret = "";
|
|
306
309
|
const intf = this.findInterfaceDefinition(name, scope);
|
|
307
310
|
for (const a of (intf === null || intf === void 0 ? void 0 : intf.getAttributes().getAll()) || []) {
|
|
308
|
-
if (a.getMeta().includes("static" /* Static */) === true) {
|
|
311
|
+
if (a.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) === true) {
|
|
309
312
|
continue;
|
|
310
313
|
}
|
|
311
314
|
const n = name.toLowerCase() + "$" + a.getName().toLowerCase();
|
|
@@ -345,10 +348,10 @@ class Traversal {
|
|
|
345
348
|
const name = def.getName();
|
|
346
349
|
if (def.isGlobal() === false) {
|
|
347
350
|
const prefix = this.buildPrefix(def);
|
|
348
|
-
return `abap.Classes['${prefix}-${name.toUpperCase()}'] = ${name.toLowerCase()};`;
|
|
351
|
+
return `abap.Classes['${prefix}-${name.toUpperCase()}'] = ${Traversal.escapeClassName(name.toLowerCase())};`;
|
|
349
352
|
}
|
|
350
353
|
else {
|
|
351
|
-
return `abap.Classes['${name.toUpperCase()}'] = ${name.toLowerCase()};`;
|
|
354
|
+
return `abap.Classes['${name.toUpperCase()}'] = ${Traversal.escapeClassName(name.toLowerCase())};`;
|
|
352
355
|
}
|
|
353
356
|
}
|
|
354
357
|
lookupClassOrInterface(name, token, directGlobal = false) {
|
package/build/src/unit_test.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare type TestMethodList = {
|
|
|
7
7
|
}[];
|
|
8
8
|
export declare class UnitTest {
|
|
9
9
|
initializationScript(reg: abaplint.IRegistry, dbSetup: DatabaseSetupResult, extraSetup?: string): string;
|
|
10
|
+
private escapeNamespace;
|
|
10
11
|
unitTestScriptOpen(reg: abaplint.IRegistry, _skip?: TestMethodList, _only?: TestMethodList): string;
|
|
11
12
|
unitTestScript(reg: abaplint.IRegistry, skip?: TestMethodList, _only?: TestMethodList): string;
|
|
12
13
|
private buildImports;
|
package/build/src/unit_test.js
CHANGED
|
@@ -6,11 +6,11 @@ const abaplint = require("@abaplint/core");
|
|
|
6
6
|
class UnitTest {
|
|
7
7
|
// todo, move this method somewhere else, its much more than just unit test relevant
|
|
8
8
|
initializationScript(reg, dbSetup, extraSetup) {
|
|
9
|
-
let ret = `/* eslint-disable import/newline-after-import */
|
|
10
|
-
import runtime from "@abaplint/runtime";
|
|
11
|
-
global.abap = new runtime.ABAP();
|
|
12
|
-
${this.buildImports(reg)}
|
|
13
|
-
|
|
9
|
+
let ret = `/* eslint-disable import/newline-after-import */
|
|
10
|
+
import runtime from "@abaplint/runtime";
|
|
11
|
+
global.abap = new runtime.ABAP();
|
|
12
|
+
${this.buildImports(reg)}
|
|
13
|
+
|
|
14
14
|
export async function initializeABAP() {\n`;
|
|
15
15
|
ret += ` const sqlite = \`${dbSetup.schemas.sqlite}\`;\n`;
|
|
16
16
|
ret += ` const hdb = \`${dbSetup.schemas.hdb}\`;\n`;
|
|
@@ -27,20 +27,24 @@ export async function initializeABAP() {\n`;
|
|
|
27
27
|
ret += `}`;
|
|
28
28
|
return ret;
|
|
29
29
|
}
|
|
30
|
+
escapeNamespace(filename) {
|
|
31
|
+
// ES modules are resolved and cached as URLs. This means that special characters must be percent-encoded, such as # with %23 and ? with %3F.
|
|
32
|
+
return filename.replace(/\//g, "%23");
|
|
33
|
+
}
|
|
30
34
|
unitTestScriptOpen(reg, _skip, _only) {
|
|
31
|
-
let ret = `/* eslint-disable curly */
|
|
32
|
-
import fs from "fs";
|
|
33
|
-
import path from "path";
|
|
34
|
-
import {fileURLToPath} from "url";
|
|
35
|
-
import {initializeABAP} from "./init.mjs";
|
|
36
|
-
|
|
37
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
38
|
-
|
|
39
|
-
async function run() {
|
|
40
|
-
await initializeABAP();
|
|
41
|
-
let lt_input = new abap.types.Table(new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30})}), {"withHeader":false,"type":"STANDARD","isUnique":false,"keyFields":[]});
|
|
42
|
-
let ls_input = new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30})});
|
|
43
|
-
let ls_result = new abap.types.Structure({list: new abap.types.Table(new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30}), expected: new abap.types.String(), actual: new abap.types.String(), status: new abap.types.String(), runtime: new abap.types.Integer(), message: new abap.types.String(), js_location: new abap.types.String()}), {"withHeader":false,"type":"STANDARD","isUnique":false,"keyFields":[]}), json: new abap.types.String()});
|
|
35
|
+
let ret = `/* eslint-disable curly */
|
|
36
|
+
import fs from "fs";
|
|
37
|
+
import path from "path";
|
|
38
|
+
import {fileURLToPath} from "url";
|
|
39
|
+
import {initializeABAP} from "./init.mjs";
|
|
40
|
+
|
|
41
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
|
|
43
|
+
async function run() {
|
|
44
|
+
await initializeABAP();
|
|
45
|
+
let lt_input = new abap.types.Table(new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30})}), {"withHeader":false,"type":"STANDARD","isUnique":false,"keyFields":[]});
|
|
46
|
+
let ls_input = new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30})});
|
|
47
|
+
let ls_result = new abap.types.Structure({list: new abap.types.Table(new abap.types.Structure({class_name: new abap.types.Character({length: 30}), testclass_name: new abap.types.Character({length: 30}), method_name: new abap.types.Character({length: 30}), expected: new abap.types.String(), actual: new abap.types.String(), status: new abap.types.String(), runtime: new abap.types.Integer(), message: new abap.types.String(), js_location: new abap.types.String()}), {"withHeader":false,"type":"STANDARD","isUnique":false,"keyFields":[]}), json: new abap.types.String()});
|
|
44
48
|
`;
|
|
45
49
|
for (const obj of reg.getObjects()) {
|
|
46
50
|
if (reg.isDependency(obj) || !(obj instanceof abaplint.Objects.Class)) {
|
|
@@ -48,7 +52,7 @@ async function run() {
|
|
|
48
52
|
}
|
|
49
53
|
const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
|
|
50
54
|
if (hasTestFile === true) {
|
|
51
|
-
ret += ` await import("./${obj.getName().toLowerCase()}.${obj.getType().toLowerCase()}.testclasses.mjs");\n`;
|
|
55
|
+
ret += ` await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}.testclasses.mjs");\n`;
|
|
52
56
|
}
|
|
53
57
|
for (const file of obj.getABAPFiles()) {
|
|
54
58
|
for (const def of file.getInfo().listClassDefinitions()) {
|
|
@@ -60,44 +64,44 @@ async function run() {
|
|
|
60
64
|
if (m.isForTesting === false) {
|
|
61
65
|
continue;
|
|
62
66
|
}
|
|
63
|
-
ret += ` ls_input.get().class_name.set("${obj.getName()}");
|
|
64
|
-
ls_input.get().testclass_name.set("${def.name.toUpperCase()}");
|
|
65
|
-
ls_input.get().method_name.set("${m.name.toUpperCase()}");
|
|
67
|
+
ret += ` ls_input.get().class_name.set("${obj.getName()}");
|
|
68
|
+
ls_input.get().testclass_name.set("${def.name.toUpperCase()}");
|
|
69
|
+
ls_input.get().method_name.set("${m.name.toUpperCase()}");
|
|
66
70
|
abap.statements.append({source: ls_input, target: lt_input});`;
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
|
-
ret += `
|
|
72
|
-
|
|
73
|
-
ls_result.set(await abap.Classes["KERNEL_UNIT_RUNNER"].run({it_input: lt_input}));
|
|
74
|
-
fs.writeFileSync(__dirname + path.sep + "output.json", ls_result.get().json.get());
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
run().then(() => {
|
|
78
|
-
process.exit(0);
|
|
79
|
-
}).catch((err) => {
|
|
80
|
-
console.log(err);
|
|
81
|
-
process.exit(1);
|
|
75
|
+
ret += `
|
|
76
|
+
|
|
77
|
+
ls_result.set(await abap.Classes["KERNEL_UNIT_RUNNER"].run({it_input: lt_input}));
|
|
78
|
+
fs.writeFileSync(__dirname + path.sep + "output.json", ls_result.get().json.get());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
run().then(() => {
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}).catch((err) => {
|
|
84
|
+
console.log(err);
|
|
85
|
+
process.exit(1);
|
|
82
86
|
});`;
|
|
83
87
|
return ret;
|
|
84
88
|
}
|
|
85
89
|
unitTestScript(reg, skip, _only) {
|
|
86
|
-
let ret = `/* eslint-disable curly */
|
|
87
|
-
import fs from "fs";
|
|
88
|
-
import path from "path";
|
|
89
|
-
import {fileURLToPath} from "url";
|
|
90
|
-
import {initializeABAP} from "./init.mjs";
|
|
91
|
-
import runtime from "@abaplint/runtime";
|
|
92
|
-
|
|
93
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
94
|
-
|
|
95
|
-
async function run() {
|
|
96
|
-
await initializeABAP();
|
|
97
|
-
const unit = new runtime.UnitTestResult();
|
|
98
|
-
let clas;
|
|
99
|
-
let locl;
|
|
100
|
-
let meth;
|
|
90
|
+
let ret = `/* eslint-disable curly */
|
|
91
|
+
import fs from "fs";
|
|
92
|
+
import path from "path";
|
|
93
|
+
import {fileURLToPath} from "url";
|
|
94
|
+
import {initializeABAP} from "./init.mjs";
|
|
95
|
+
import runtime from "@abaplint/runtime";
|
|
96
|
+
|
|
97
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
98
|
+
|
|
99
|
+
async function run() {
|
|
100
|
+
await initializeABAP();
|
|
101
|
+
const unit = new runtime.UnitTestResult();
|
|
102
|
+
let clas;
|
|
103
|
+
let locl;
|
|
104
|
+
let meth;
|
|
101
105
|
try {\n`;
|
|
102
106
|
for (const obj of reg.getObjects()) {
|
|
103
107
|
if (reg.isDependency(obj) || !(obj instanceof abaplint.Objects.Class)) {
|
|
@@ -111,9 +115,9 @@ async function run() {
|
|
|
111
115
|
// todo, fix, there might be global test methods
|
|
112
116
|
continue;
|
|
113
117
|
}
|
|
114
|
-
ret += ` {
|
|
115
|
-
const {${def.name}} = await import("./${obj.getName().toLowerCase()}.${obj.getType().toLowerCase()}.testclasses.mjs");
|
|
116
|
-
locl = clas.addTestClass("${def.name}");
|
|
118
|
+
ret += ` {
|
|
119
|
+
const {${def.name}} = await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}.testclasses.mjs");
|
|
120
|
+
locl = clas.addTestClass("${def.name}");
|
|
117
121
|
if (${def.name}.class_setup) await ${def.name}.class_setup();\n`;
|
|
118
122
|
for (const m of def.methods) {
|
|
119
123
|
if (m.isForTesting === false) {
|
|
@@ -140,24 +144,24 @@ async function run() {
|
|
|
140
144
|
}
|
|
141
145
|
}
|
|
142
146
|
}
|
|
143
|
-
ret += `// -------------------END-------------------
|
|
144
|
-
console.log(abap.console.get());
|
|
145
|
-
fs.writeFileSync(__dirname + path.sep + "output.xml", unit.xUnitXML());
|
|
146
|
-
} catch (e) {
|
|
147
|
-
if (meth) {
|
|
148
|
-
meth.fail();
|
|
149
|
-
}
|
|
150
|
-
console.log(abap.console.get());
|
|
151
|
-
fs.writeFileSync(__dirname + path.sep + "output.xml", unit.xUnitXML());
|
|
152
|
-
throw e;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
run().then(() => {
|
|
157
|
-
process.exit(0);
|
|
158
|
-
}).catch((err) => {
|
|
159
|
-
console.log(err);
|
|
160
|
-
process.exit(1);
|
|
147
|
+
ret += `// -------------------END-------------------
|
|
148
|
+
console.log(abap.console.get());
|
|
149
|
+
fs.writeFileSync(__dirname + path.sep + "output.xml", unit.xUnitXML());
|
|
150
|
+
} catch (e) {
|
|
151
|
+
if (meth) {
|
|
152
|
+
meth.fail();
|
|
153
|
+
}
|
|
154
|
+
console.log(abap.console.get());
|
|
155
|
+
fs.writeFileSync(__dirname + path.sep + "output.xml", unit.xUnitXML());
|
|
156
|
+
throw e;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
run().then(() => {
|
|
161
|
+
process.exit(0);
|
|
162
|
+
}).catch((err) => {
|
|
163
|
+
console.log(err);
|
|
164
|
+
process.exit(1);
|
|
161
165
|
});`;
|
|
162
166
|
return ret;
|
|
163
167
|
}
|
|
@@ -168,26 +172,26 @@ run().then(() => {
|
|
|
168
172
|
const list = [];
|
|
169
173
|
for (const obj of reg.getObjects()) {
|
|
170
174
|
if (obj instanceof abaplint.Objects.Table) {
|
|
171
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.tabl.mjs");`);
|
|
175
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.tabl.mjs");`);
|
|
172
176
|
}
|
|
173
177
|
else if (obj instanceof abaplint.Objects.DataElement) {
|
|
174
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.dtel.mjs");`);
|
|
178
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.dtel.mjs");`);
|
|
175
179
|
}
|
|
176
180
|
else if (obj instanceof abaplint.Objects.TableType) {
|
|
177
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.ttyp.mjs");`);
|
|
181
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.ttyp.mjs");`);
|
|
178
182
|
}
|
|
179
183
|
}
|
|
180
184
|
for (const obj of reg.getObjects()) {
|
|
181
185
|
if (obj instanceof abaplint.Objects.FunctionGroup) {
|
|
182
186
|
for (const m of obj.getModules()) {
|
|
183
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.fugr.${m.getName().toLowerCase()}.mjs");`);
|
|
187
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.fugr.${m.getName().toLowerCase()}.mjs");`);
|
|
184
188
|
}
|
|
185
189
|
}
|
|
186
190
|
else if (obj instanceof abaplint.Objects.Class) {
|
|
187
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.clas.mjs");`);
|
|
191
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.clas.mjs");`);
|
|
188
192
|
}
|
|
189
193
|
else if (obj instanceof abaplint.Objects.Interface) {
|
|
190
|
-
list.push(`await import("./${obj.getName().toLowerCase()}.intf.mjs");`);
|
|
194
|
+
list.push(`await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.intf.mjs");`);
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
197
|
list.sort();
|
package/package.json
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@abaplint/transpiler",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Transpiler",
|
|
5
|
-
"main": "build/src/index.js",
|
|
6
|
-
"typings": "build/src/index.d.ts",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/abaplint/transpiler.git"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"compile": "tsc",
|
|
13
|
-
"publish:major": "npm --no-git-tag-version version major && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
14
|
-
"publish:minor": "npm --no-git-tag-version version minor && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
15
|
-
"publish:patch": "npm --no-git-tag-version version patch && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
16
|
-
"test": "npm run compile && mocha"
|
|
17
|
-
},
|
|
18
|
-
"mocha": {
|
|
19
|
-
"recursive": true,
|
|
20
|
-
"reporter": "progress",
|
|
21
|
-
"spec": "build/test/**/*.js",
|
|
22
|
-
"require": "source-map-support/register"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"ABAP",
|
|
26
|
-
"abaplint"
|
|
27
|
-
],
|
|
28
|
-
"author": "abaplint",
|
|
29
|
-
"license": "MIT",
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"@abaplint/core": "^2.90.
|
|
32
|
-
"source-map": "^0.7.3"
|
|
33
|
-
},
|
|
34
|
-
"devDependencies": {
|
|
35
|
-
"@types/chai": "^4.3.1",
|
|
36
|
-
"@types/mocha": "^9.1.1",
|
|
37
|
-
"chai": "^4.3.6",
|
|
38
|
-
"mocha": "^10.0.0",
|
|
39
|
-
"source-map-support": "^0.5.21",
|
|
40
|
-
"typescript": "^4.
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@abaplint/transpiler",
|
|
3
|
+
"version": "2.0.29",
|
|
4
|
+
"description": "Transpiler",
|
|
5
|
+
"main": "build/src/index.js",
|
|
6
|
+
"typings": "build/src/index.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/abaplint/transpiler.git"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"compile": "tsc",
|
|
13
|
+
"publish:major": "npm --no-git-tag-version version major && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
14
|
+
"publish:minor": "npm --no-git-tag-version version minor && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
15
|
+
"publish:patch": "npm --no-git-tag-version version patch && rm -rf build && npm install && npm run test && npm publish --access public",
|
|
16
|
+
"test": "npm run compile && mocha"
|
|
17
|
+
},
|
|
18
|
+
"mocha": {
|
|
19
|
+
"recursive": true,
|
|
20
|
+
"reporter": "progress",
|
|
21
|
+
"spec": "build/test/**/*.js",
|
|
22
|
+
"require": "source-map-support/register"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ABAP",
|
|
26
|
+
"abaplint"
|
|
27
|
+
],
|
|
28
|
+
"author": "abaplint",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@abaplint/core": "^2.90.9",
|
|
32
|
+
"source-map": "^0.7.3"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/chai": "^4.3.1",
|
|
36
|
+
"@types/mocha": "^9.1.1",
|
|
37
|
+
"chai": "^4.3.6",
|
|
38
|
+
"mocha": "^10.0.0",
|
|
39
|
+
"source-map-support": "^0.5.21",
|
|
40
|
+
"typescript": "^4.7.2"
|
|
41
|
+
}
|
|
42
|
+
}
|