@abaplint/transpiler 2.10.38 → 2.10.39

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.
@@ -20,6 +20,7 @@ const handle_smim_1 = require("./handlers/handle_smim");
20
20
  const handle_msag_1 = require("./handlers/handle_msag");
21
21
  const handle_oa2p_1 = require("./handlers/handle_oa2p");
22
22
  const handle_fugr_1 = require("./handlers/handle_fugr");
23
+ const initialization_1 = require("./initialization");
23
24
  class Transpiler {
24
25
  constructor(options) {
25
26
  this.options = options;
@@ -44,8 +45,8 @@ class Transpiler {
44
45
  objects: [],
45
46
  unitTestScript: new unit_test_1.UnitTest().unitTestScript(reg, this.options?.skip),
46
47
  unitTestScriptOpen: new unit_test_1.UnitTest().unitTestScriptOpen(reg, this.options?.skip),
47
- initializationScript: new unit_test_1.UnitTest().initializationScript(reg, dbSetup, this.options?.extraSetup),
48
- initializationScript2: new unit_test_1.UnitTest().initializationScript(reg, dbSetup, this.options?.extraSetup, true),
48
+ initializationScript: new initialization_1.Initialization().script(reg, dbSetup, this.options?.extraSetup),
49
+ initializationScript2: new initialization_1.Initialization().script(reg, dbSetup, this.options?.extraSetup, true),
49
50
  databaseSetup: dbSetup,
50
51
  reg: reg,
51
52
  };
@@ -0,0 +1,8 @@
1
+ import { DatabaseSetupResult } from "./db/database_setup_result";
2
+ import * as abaplint from "@abaplint/core";
3
+ export declare function escapeNamespaceFilename(filename: string): string;
4
+ export declare class Initialization {
5
+ script(reg: abaplint.IRegistry, dbSetup: DatabaseSetupResult, extraSetup?: string, useImport?: boolean): string;
6
+ private buildImports;
7
+ private hasClassConstructor;
8
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Initialization = void 0;
4
+ exports.escapeNamespaceFilename = escapeNamespaceFilename;
5
+ const abaplint = require("@abaplint/core");
6
+ function escapeNamespaceFilename(filename) {
7
+ // ES modules are resolved and cached as URLs. This means that special characters must be
8
+ // percent-encoded, such as # with %23 and ? with %3F.
9
+ return filename.replace(/\//g, "%23");
10
+ }
11
+ class Initialization {
12
+ script(reg, dbSetup, extraSetup, useImport) {
13
+ let ret = "";
14
+ if (useImport === true) {
15
+ ret = `/* eslint-disable import/newline-after-import */
16
+ import "./_top.mjs";\n`;
17
+ }
18
+ else {
19
+ ret = `/* eslint-disable import/newline-after-import */
20
+ import runtime from "@abaplint/runtime";
21
+ globalThis.abap = new runtime.ABAP();\n`;
22
+ }
23
+ ret += `${this.buildImports(reg, useImport)}
24
+
25
+ export async function initializeABAP() {\n`;
26
+ ret += ` const sqlite = [];\n`;
27
+ for (const i of dbSetup.schemas.sqlite) {
28
+ ret += ` sqlite.push(\`${i}\`);\n`;
29
+ }
30
+ ret += ` const hdb = \`${dbSetup.schemas.hdb}\`;\n`;
31
+ ret += ` const pg = [];\n`;
32
+ for (const i of dbSetup.schemas.pg) {
33
+ ret += ` pg.push(\`${i}\`);\n`;
34
+ }
35
+ ret += ` const snowflake = [];\n`;
36
+ for (const i of dbSetup.schemas.snowflake) {
37
+ ret += ` snowflake.push(\`${i}\`);\n`;
38
+ }
39
+ ret += ` const schemas = {sqlite, hdb, pg, snowflake};\n`;
40
+ ret += `\n`;
41
+ ret += ` const insert = [];\n`;
42
+ for (const i of dbSetup.insert) {
43
+ ret += ` insert.push(\`${i}\`);\n`;
44
+ }
45
+ ret += `\n`;
46
+ if (extraSetup === undefined || extraSetup === "") {
47
+ ret += `// no setup logic specified in config\n`;
48
+ }
49
+ else {
50
+ ret += ` const {setup} = await import("${extraSetup}");\n` +
51
+ ` await setup(globalThis.abap, schemas, insert);\n`;
52
+ }
53
+ ret += `}`;
54
+ return ret;
55
+ }
56
+ buildImports(reg, useImport) {
57
+ // note: ES modules are hoised, so use the dynamic import(), due to setting of globalThis.abap
58
+ // some sorting required: eg. a class constructor using constant from interface
59
+ const list = [];
60
+ const late = [];
61
+ const imp = (filename) => {
62
+ if (useImport === true) {
63
+ return `import "./${filename}.mjs";`;
64
+ }
65
+ else {
66
+ return `await import("./${filename}.mjs");`;
67
+ }
68
+ };
69
+ for (const obj of reg.getObjects()) {
70
+ if (obj instanceof abaplint.Objects.Table
71
+ || obj instanceof abaplint.Objects.DataElement
72
+ || obj instanceof abaplint.Objects.LockObject
73
+ || obj instanceof abaplint.Objects.MessageClass
74
+ || obj instanceof abaplint.Objects.MIMEObject
75
+ || obj instanceof abaplint.Objects.Oauth2Profile
76
+ || obj instanceof abaplint.Objects.WebMIME
77
+ || obj instanceof abaplint.Objects.TypePool
78
+ || obj instanceof abaplint.Objects.TableType) {
79
+ list.push(imp(`${escapeNamespaceFilename(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
80
+ }
81
+ }
82
+ for (const obj of reg.getObjects()) {
83
+ if (obj instanceof abaplint.Objects.FunctionGroup) {
84
+ list.push(imp(`${escapeNamespaceFilename(obj.getName().toLowerCase())}.fugr`));
85
+ }
86
+ else if (obj instanceof abaplint.Objects.Class) {
87
+ if (obj.getName().toUpperCase() !== "CL_ABAP_CHAR_UTILITIES"
88
+ && this.hasClassConstructor(reg, obj)) {
89
+ // this will not solve all problems with class constors 100%, but probably good enough
90
+ late.push(imp(`${escapeNamespaceFilename(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
91
+ }
92
+ else {
93
+ list.push(imp(`${escapeNamespaceFilename(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
94
+ }
95
+ }
96
+ else if (obj instanceof abaplint.Objects.Interface) {
97
+ list.push(imp(`${escapeNamespaceFilename(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
98
+ }
99
+ }
100
+ return [...list.sort(), ...late].join("\n");
101
+ }
102
+ // class constructors might make early use of eg. constants from interfaces
103
+ // sub classes will import() super classes and trigger a class constructor of the super
104
+ hasClassConstructor(reg, clas) {
105
+ if (clas.getDefinition()?.getMethodDefinitions().getByName("CLASS_CONSTRUCTOR") !== undefined) {
106
+ return true;
107
+ }
108
+ const sup = clas.getDefinition()?.getSuperClass();
109
+ if (sup !== undefined) {
110
+ const superClass = reg.getObject("CLAS", sup);
111
+ if (superClass) {
112
+ return this.hasClassConstructor(reg, superClass);
113
+ }
114
+ }
115
+ return false;
116
+ }
117
+ }
118
+ exports.Initialization = Initialization;
119
+ //# sourceMappingURL=initialization.js.map
@@ -1,16 +1,11 @@
1
1
  import * as abaplint from "@abaplint/core";
2
- import { DatabaseSetupResult } from "./db/database_setup_result";
3
2
  export type TestMethodList = {
4
3
  object: string;
5
4
  class: string;
6
5
  method: string;
7
6
  }[];
8
7
  export declare class UnitTest {
9
- initializationScript(reg: abaplint.IRegistry, dbSetup: DatabaseSetupResult, extraSetup?: string, useImport?: boolean): string;
10
- private escapeNamespace;
11
8
  unitTestScriptOpen(reg: abaplint.IRegistry, _skip?: TestMethodList): string;
12
9
  private getSortedTests;
13
10
  unitTestScript(reg: abaplint.IRegistry, skip?: TestMethodList): string;
14
- private buildImports;
15
- private hasClassConstructor;
16
11
  }
@@ -3,56 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UnitTest = void 0;
4
4
  /* eslint-disable max-len */
5
5
  const abaplint = require("@abaplint/core");
6
+ const initialization_1 = require("./initialization");
6
7
  class UnitTest {
7
- // todo, move this method somewhere else, its much more than just unit test relevant
8
- initializationScript(reg, dbSetup, extraSetup, useImport) {
9
- let ret = "";
10
- if (useImport === true) {
11
- ret = `/* eslint-disable import/newline-after-import */
12
- import "./_top.mjs";\n`;
13
- }
14
- else {
15
- ret = `/* eslint-disable import/newline-after-import */
16
- import runtime from "@abaplint/runtime";
17
- globalThis.abap = new runtime.ABAP();\n`;
18
- }
19
- ret += `${this.buildImports(reg, useImport)}
20
-
21
- export async function initializeABAP() {\n`;
22
- ret += ` const sqlite = [];\n`;
23
- for (const i of dbSetup.schemas.sqlite) {
24
- ret += ` sqlite.push(\`${i}\`);\n`;
25
- }
26
- ret += ` const hdb = \`${dbSetup.schemas.hdb}\`;\n`;
27
- ret += ` const pg = [];\n`;
28
- for (const i of dbSetup.schemas.pg) {
29
- ret += ` pg.push(\`${i}\`);\n`;
30
- }
31
- ret += ` const snowflake = [];\n`;
32
- for (const i of dbSetup.schemas.snowflake) {
33
- ret += ` snowflake.push(\`${i}\`);\n`;
34
- }
35
- ret += ` const schemas = {sqlite, hdb, pg, snowflake};\n`;
36
- ret += `\n`;
37
- ret += ` const insert = [];\n`;
38
- for (const i of dbSetup.insert) {
39
- ret += ` insert.push(\`${i}\`);\n`;
40
- }
41
- ret += `\n`;
42
- if (extraSetup === undefined || extraSetup === "") {
43
- ret += `// no setup logic specified in config\n`;
44
- }
45
- else {
46
- ret += ` const {setup} = await import("${extraSetup}");\n` +
47
- ` await setup(globalThis.abap, schemas, insert);\n`;
48
- }
49
- ret += `}`;
50
- return ret;
51
- }
52
- escapeNamespace(filename) {
53
- // ES modules are resolved and cached as URLs. This means that special characters must be percent-encoded, such as # with %23 and ? with %3F.
54
- return filename.replace(/\//g, "%23");
55
- }
56
8
  unitTestScriptOpen(reg, _skip) {
57
9
  let ret = `/* eslint-disable curly */
58
10
  import fs from "fs";
@@ -74,7 +26,7 @@ async function run() {
74
26
  }
75
27
  const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
76
28
  if (hasTestFile === true) {
77
- ret += ` await import("./${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}.testclasses.mjs");\n`;
29
+ ret += ` await import("./${(0, initialization_1.escapeNamespaceFilename)(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}.testclasses.mjs");\n`;
78
30
  }
79
31
  for (const file of obj.getABAPFiles()) {
80
32
  for (const def of file.getInfo().listClassDefinitions()) {
@@ -193,35 +145,20 @@ run().then(() => {
193
145
  }
194
146
  unitTestScript(reg, skip) {
195
147
  let ret = `/* eslint-disable curly */
196
- import fs from "fs";
197
- import path from "path";
198
- import {fileURLToPath} from "url";
199
148
  import {initializeABAP} from "./init.mjs";
200
- import runtime from "@abaplint/runtime";
201
-
202
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
203
149
 
204
150
  async function run() {
205
- await initializeABAP();
206
- const unit = new runtime.UnitTestResult();
207
- let clas;
208
- let locl;
209
- let meth;
210
- try {\n`;
151
+ await initializeABAP();\n`;
211
152
  for (const st of this.getSortedTests(reg)) {
212
153
  ret += `// --------------------------------------------\n`;
213
- ret += ` clas = unit.addObject("${st.obj.getName()}");\n`;
214
154
  const lc = st.localClass.toLowerCase();
215
155
  ret += ` {
216
- const {${lc}} = await import("./${this.escapeNamespace(st.obj.getName().toLowerCase())}.${st.obj.getType().toLowerCase()}.testclasses.mjs");
217
- locl = clas.addTestClass("${lc}");
156
+ const {${lc}} = await import("./${(0, initialization_1.escapeNamespaceFilename)(st.obj.getName().toLowerCase())}.${st.obj.getType().toLowerCase()}.testclasses.mjs");
218
157
  if (${lc}.class_setup) await ${lc}.class_setup();\n`;
219
158
  for (const m of st.methods) {
220
159
  const skipThis = (skip || []).some(a => a.object === st.obj.getName() && a.class === lc && a.method === m);
221
160
  if (skipThis) {
222
- ret += ` console.log('${st.obj.getName()}: running ${lc}->${m}, skipped');\n`;
223
- ret += ` meth = locl.addMethod("${m}");\n`;
224
- ret += ` meth.skip();\n`;
161
+ ret += ` console.log('${st.obj.getName()}: running ${lc}->${m}, skipped');\n`;
225
162
  continue;
226
163
  }
227
164
  const callSpecial = (name) => {
@@ -234,24 +171,14 @@ async function run() {
234
171
  ret += ` {\n const test = await (new ${lc}()).constructor_();\n`;
235
172
  ret += callSpecial("setup");
236
173
  ret += ` console.log("${st.obj.getName()}: running ${lc}->${m}");\n`;
237
- ret += ` meth = locl.addMethod("${m}");\n`;
238
174
  ret += ` await test.FRIENDS_ACCESS_INSTANCE.${m}();\n`;
239
- ret += ` meth.pass();\n`;
240
175
  ret += callSpecial("teardown");
241
176
  ret += ` }\n`;
242
177
  }
243
- ret += ` if (${lc}.class_teardown) await ${lc}.class_teardown();\n`;
178
+ ret += ` if (${lc}.class_teardown) await ${lc}.class_teardown();\n`;
244
179
  ret += ` }\n`;
245
180
  }
246
181
  ret += `// -------------------END-------------------
247
- fs.writeFileSync(__dirname + path.sep + "_output.xml", unit.xUnitXML());
248
- } catch (e) {
249
- if (meth) {
250
- meth.fail();
251
- }
252
- fs.writeFileSync(__dirname + path.sep + "_output.xml", unit.xUnitXML());
253
- throw e;
254
- }
255
182
  }
256
183
 
257
184
  run().then(() => {
@@ -262,67 +189,6 @@ run().then(() => {
262
189
  });`;
263
190
  return ret;
264
191
  }
265
- buildImports(reg, useImport) {
266
- // note: ES modules are hoised, so use the dynamic import(), due to setting of globalThis.abap
267
- // some sorting required: eg. a class constructor using constant from interface
268
- const list = [];
269
- const late = [];
270
- const imp = (filename) => {
271
- if (useImport === true) {
272
- return `import "./${filename}.mjs";`;
273
- }
274
- else {
275
- return `await import("./${filename}.mjs");`;
276
- }
277
- };
278
- for (const obj of reg.getObjects()) {
279
- if (obj instanceof abaplint.Objects.Table
280
- || obj instanceof abaplint.Objects.DataElement
281
- || obj instanceof abaplint.Objects.LockObject
282
- || obj instanceof abaplint.Objects.MessageClass
283
- || obj instanceof abaplint.Objects.MIMEObject
284
- || obj instanceof abaplint.Objects.Oauth2Profile
285
- || obj instanceof abaplint.Objects.WebMIME
286
- || obj instanceof abaplint.Objects.TypePool
287
- || obj instanceof abaplint.Objects.TableType) {
288
- list.push(imp(`${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
289
- }
290
- }
291
- for (const obj of reg.getObjects()) {
292
- if (obj instanceof abaplint.Objects.FunctionGroup) {
293
- list.push(imp(`${this.escapeNamespace(obj.getName().toLowerCase())}.fugr`));
294
- }
295
- else if (obj instanceof abaplint.Objects.Class) {
296
- if (obj.getName().toUpperCase() !== "CL_ABAP_CHAR_UTILITIES"
297
- && this.hasClassConstructor(reg, obj)) {
298
- // this will not solve all problems with class constors 100%, but probably good enough
299
- late.push(imp(`${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
300
- }
301
- else {
302
- list.push(imp(`${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
303
- }
304
- }
305
- else if (obj instanceof abaplint.Objects.Interface) {
306
- list.push(imp(`${this.escapeNamespace(obj.getName().toLowerCase())}.${obj.getType().toLowerCase()}`));
307
- }
308
- }
309
- return [...list.sort(), ...late].join("\n");
310
- }
311
- // class constructors might make early use of eg. constants from interfaces
312
- // sub classes will import() super classes and trigger a class constructor of the super
313
- hasClassConstructor(reg, clas) {
314
- if (clas.getDefinition()?.getMethodDefinitions().getByName("CLASS_CONSTRUCTOR") !== undefined) {
315
- return true;
316
- }
317
- const sup = clas.getDefinition()?.getSuperClass();
318
- if (sup !== undefined) {
319
- const superClass = reg.getObject("CLAS", sup);
320
- if (superClass) {
321
- return this.hasClassConstructor(reg, superClass);
322
- }
323
- }
324
- return false;
325
- }
326
192
  }
327
193
  exports.UnitTest = UnitTest;
328
194
  //# sourceMappingURL=unit_test.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/transpiler",
3
- "version": "2.10.38",
3
+ "version": "2.10.39",
4
4
  "description": "Transpiler",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",