@abaplint/transpiler-cli 2.13.100 → 2.14.0
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 +62 -1
- package/build/bundle.js +914 -235
- package/build/types.d.ts +4 -0
- package/package.json +3 -3
- package/schema.json +1 -4
- package/tsconfig.tsbuildinfo +1 -0
package/build/bundle.js
CHANGED
|
@@ -240,6 +240,7 @@ class FileOperations {
|
|
|
240
240
|
return limit(async () => {
|
|
241
241
|
// read as latin1, written as latin1: anything else re-encodes the
|
|
242
242
|
// bytes on the way out and undoes the careful read
|
|
243
|
+
await fsPromises.mkdir(path.dirname(file.path), { recursive: true });
|
|
243
244
|
await fsPromises.writeFile(file.path, file.contents, this.isBinaryFilename(file.path) ? { encoding: "latin1" } : undefined);
|
|
244
245
|
});
|
|
245
246
|
});
|
|
@@ -315,16 +316,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
315
316
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
316
317
|
const fs = __importStar(__webpack_require__(/*! fs */ "fs"));
|
|
317
318
|
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
318
|
-
const childProcess = __importStar(__webpack_require__(/*! child_process */ "child_process"));
|
|
319
|
-
const os = __importStar(__webpack_require__(/*! os */ "os"));
|
|
320
|
-
const module_1 = __webpack_require__(/*! module */ "module");
|
|
321
319
|
const progress_1 = __importDefault(__webpack_require__(/*! progress */ "./node_modules/progress/index.js"));
|
|
322
320
|
const Transpiler = __importStar(__webpack_require__(/*! @abaplint/transpiler */ "./node_modules/@abaplint/transpiler/build/src/index.js"));
|
|
323
|
-
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
324
321
|
const config_1 = __webpack_require__(/*! ./config */ "./build/config.js");
|
|
325
322
|
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
326
|
-
const
|
|
327
|
-
const
|
|
323
|
+
const libraries_1 = __webpack_require__(/*! ./libraries */ "./build/libraries.js");
|
|
324
|
+
const write_objects_1 = __webpack_require__(/*! ./write_objects */ "./build/write_objects.js");
|
|
328
325
|
class Progress {
|
|
329
326
|
bar;
|
|
330
327
|
set(total, _text) {
|
|
@@ -335,142 +332,30 @@ class Progress {
|
|
|
335
332
|
this.bar.render();
|
|
336
333
|
}
|
|
337
334
|
}
|
|
338
|
-
async function loadLib(config) {
|
|
339
|
-
const files = [];
|
|
340
|
-
for (const lib of config.libs || []) {
|
|
341
|
-
let dir = "";
|
|
342
|
-
let cleanupFolder = false;
|
|
343
|
-
const folder = (0, lib_folder_1.resolveLibFolder)(lib.folder, process.cwd());
|
|
344
|
-
if (folder !== undefined && fs.existsSync(folder)) {
|
|
345
|
-
console.log("From folder: " + folder);
|
|
346
|
-
dir = folder;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
if (lib.url === undefined || lib.url === "") {
|
|
350
|
-
if (folder === undefined) {
|
|
351
|
-
throw new Error("Library must define a non-empty url or an existing folder");
|
|
352
|
-
}
|
|
353
|
-
throw new Error("Library folder not found: " + folder);
|
|
354
|
-
}
|
|
355
|
-
console.log("Clone: " + lib.url);
|
|
356
|
-
dir = fs.mkdtempSync(path.join(os.tmpdir(), "abap_transpile-"));
|
|
357
|
-
const args = (0, git_clone_1.buildGitCloneArguments)(lib.url);
|
|
358
|
-
childProcess.execFileSync("git", args, { cwd: dir, stdio: "inherit" });
|
|
359
|
-
cleanupFolder = true;
|
|
360
|
-
}
|
|
361
|
-
let patterns = ["/src/**"];
|
|
362
|
-
if (lib.files !== undefined && typeof lib.files === "string" && lib.files !== "") {
|
|
363
|
-
patterns = [lib.files];
|
|
364
|
-
}
|
|
365
|
-
else if (Array.isArray(lib.files)) {
|
|
366
|
-
patterns = lib.files;
|
|
367
|
-
}
|
|
368
|
-
const excludeFilters = (lib.exclude_filter ?? []).map(pattern => new RegExp(pattern, "i"));
|
|
369
|
-
const filesToRead = [];
|
|
370
|
-
for (const pattern of patterns) {
|
|
371
|
-
for (const filename of file_operations_1.FileOperations.globSync(dir + pattern)) {
|
|
372
|
-
if (filename.endsWith(".clas.testclasses.abap")) {
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
else if (excludeFilters.length > 0 && excludeFilters.some(a => a.test(filename)) === true) {
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
filesToRead.push(filename);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
files.push(...await file_operations_1.FileOperations.readAllFiles(filesToRead, ""));
|
|
382
|
-
console.log("\t" + filesToRead.length + " files added from lib");
|
|
383
|
-
if (cleanupFolder === true) {
|
|
384
|
-
file_operations_1.FileOperations.deleteFolderRecursive(dir);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return files;
|
|
388
|
-
}
|
|
389
|
-
async function writeObjects(outputFiles, config, outputFolder, files) {
|
|
390
|
-
const writeSourceMaps = config.write_source_map || false;
|
|
391
|
-
const filesToWrite = [];
|
|
392
|
-
for (const output of outputFiles) {
|
|
393
|
-
const type = output.object.type.toUpperCase();
|
|
394
|
-
let contents = output.chunk.getCode();
|
|
395
|
-
// PROG output gets a runtime bootstrap line prepended, which shifts every
|
|
396
|
-
// generated line down by one - the source map must account for this offset
|
|
397
|
-
let generatedLineOffset = 0;
|
|
398
|
-
if (type === "PROG") {
|
|
399
|
-
// hmm, will this work for INCLUDEs ?
|
|
400
|
-
contents = `if (!globalThis.abap) await import("./_init.mjs");\n` + contents;
|
|
401
|
-
generatedLineOffset = 1;
|
|
402
|
-
}
|
|
403
|
-
if (writeSourceMaps === true
|
|
404
|
-
&& (type === "PROG" || type === "FUGR" || type === "CLAS")) {
|
|
405
|
-
const name = output.filename + ".map";
|
|
406
|
-
// SourceMappingUrl needs to be percent-encoded, ref https://github.com/microsoft/TypeScript/issues/40951
|
|
407
|
-
contents = contents + `\n//# sourceMappingURL=` + name.replace(/%/g, "%25").replace(/#/g, "%23");
|
|
408
|
-
// map the bare abap filename each mapping carries to its path on disk;
|
|
409
|
-
// source map "sources" are URLs, so always forward slashes, also on Windows
|
|
410
|
-
const sourcePaths = {};
|
|
411
|
-
for (const f of files) {
|
|
412
|
-
if (f.relative === undefined) {
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
const rel = f.relative.split(path.sep).join("/");
|
|
416
|
-
sourcePaths[f.filename] = rel === "" ? f.filename : `${rel}/${f.filename}`;
|
|
417
|
-
}
|
|
418
|
-
const map = output.chunk.getMap(output.filename, { generatedLineOffset, sourcePaths });
|
|
419
|
-
filesToWrite.push({ path: outputFolder + path.sep + name, contents: map });
|
|
420
|
-
}
|
|
421
|
-
filesToWrite.push({ path: outputFolder + path.sep + output.filename, contents });
|
|
422
|
-
}
|
|
423
|
-
await file_operations_1.FileOperations.writeFiles(filesToWrite);
|
|
424
|
-
}
|
|
425
|
-
const PLUGIN_MODULE = "@abaplint/transpiler-extras";
|
|
426
|
-
function loadPlugin() {
|
|
427
|
-
// createRequire so the plugin resolves from the project consuming the CLI, also after webpacking
|
|
428
|
-
const projectRequire = (0, module_1.createRequire)(path.join(process.cwd(), "package.json"));
|
|
429
|
-
try {
|
|
430
|
-
projectRequire.resolve(PLUGIN_MODULE);
|
|
431
|
-
}
|
|
432
|
-
catch {
|
|
433
|
-
// plugin package not installed
|
|
434
|
-
return undefined;
|
|
435
|
-
}
|
|
436
|
-
const plugin = projectRequire(PLUGIN_MODULE).plugin;
|
|
437
|
-
if (plugin === undefined) {
|
|
438
|
-
throw new Error(PLUGIN_MODULE + " does not export a plugin");
|
|
439
|
-
}
|
|
440
|
-
console.log("Plugin loaded: " + PLUGIN_MODULE + ", object types: " + plugin.objectTypes().join(", "));
|
|
441
|
-
console.log("Note this requires license for commercial use");
|
|
442
|
-
return plugin;
|
|
443
|
-
}
|
|
444
335
|
async function build(config, files) {
|
|
445
|
-
const
|
|
336
|
+
const libraries = await (0, libraries_1.loadLibraries)(config);
|
|
446
337
|
const options = { ...config.options };
|
|
447
338
|
if (config.write_source_map !== true) {
|
|
448
339
|
// Do not pay to allocate and copy mappings that the CLI will not write.
|
|
449
340
|
options.ignoreSourceMap = true;
|
|
450
341
|
}
|
|
451
|
-
const t = new Transpiler.Transpiler(options
|
|
452
|
-
const reg =
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
for (const l of libFiles) {
|
|
457
|
-
reg.addDependency(new abaplint.MemoryFile(l.filename, l.contents));
|
|
458
|
-
}
|
|
459
|
-
const output = await t.run(reg, new Progress());
|
|
460
|
-
return output;
|
|
342
|
+
const t = new Transpiler.Transpiler(options);
|
|
343
|
+
const { reg, folders, sources } = (0, libraries_1.libraryRegistry)(files, libraries);
|
|
344
|
+
const output = await t.run(reg, new Progress(), folders);
|
|
345
|
+
return { output, sources };
|
|
461
346
|
}
|
|
462
347
|
async function run() {
|
|
463
348
|
console.log("Transpiler CLI");
|
|
464
349
|
const config = config_1.TranspilerConfig.find(process.argv[2]);
|
|
465
350
|
const files = await file_operations_1.FileOperations.loadFiles(config);
|
|
466
351
|
console.log("\nBuilding");
|
|
467
|
-
const output = await build(config, files);
|
|
352
|
+
const { output, sources } = await build(config, files);
|
|
468
353
|
console.log("\nOutput");
|
|
469
354
|
const outputFolder = config.output_folder;
|
|
470
355
|
if (!fs.existsSync(outputFolder)) {
|
|
471
|
-
fs.mkdirSync(outputFolder);
|
|
356
|
+
fs.mkdirSync(outputFolder, { recursive: true });
|
|
472
357
|
}
|
|
473
|
-
await writeObjects(output.objects, config,
|
|
358
|
+
await (0, write_objects_1.writeObjects)(output.objects, config, sources);
|
|
474
359
|
console.log(output.objects.length + " objects written to disk");
|
|
475
360
|
if (config.write_unit_tests === true) {
|
|
476
361
|
// breaking change? rename this output file,
|
|
@@ -553,6 +438,267 @@ function resolveLibFolder(folder, cwd) {
|
|
|
553
438
|
|
|
554
439
|
/***/ },
|
|
555
440
|
|
|
441
|
+
/***/ "./build/libraries.js"
|
|
442
|
+
/*!****************************!*\
|
|
443
|
+
!*** ./build/libraries.js ***!
|
|
444
|
+
\****************************/
|
|
445
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
446
|
+
|
|
447
|
+
"use strict";
|
|
448
|
+
|
|
449
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
450
|
+
if (k2 === undefined) k2 = k;
|
|
451
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
452
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
453
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
454
|
+
}
|
|
455
|
+
Object.defineProperty(o, k2, desc);
|
|
456
|
+
}) : (function(o, m, k, k2) {
|
|
457
|
+
if (k2 === undefined) k2 = k;
|
|
458
|
+
o[k2] = m[k];
|
|
459
|
+
}));
|
|
460
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
461
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
462
|
+
}) : function(o, v) {
|
|
463
|
+
o["default"] = v;
|
|
464
|
+
});
|
|
465
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
466
|
+
var ownKeys = function(o) {
|
|
467
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
468
|
+
var ar = [];
|
|
469
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
470
|
+
return ar;
|
|
471
|
+
};
|
|
472
|
+
return ownKeys(o);
|
|
473
|
+
};
|
|
474
|
+
return function (mod) {
|
|
475
|
+
if (mod && mod.__esModule) return mod;
|
|
476
|
+
var result = {};
|
|
477
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
478
|
+
__setModuleDefault(result, mod);
|
|
479
|
+
return result;
|
|
480
|
+
};
|
|
481
|
+
})();
|
|
482
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
483
|
+
exports.libraryNames = libraryNames;
|
|
484
|
+
exports.loadLibraries = loadLibraries;
|
|
485
|
+
exports.libraryRegistry = libraryRegistry;
|
|
486
|
+
const fs = __importStar(__webpack_require__(/*! fs */ "fs"));
|
|
487
|
+
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
488
|
+
const childProcess = __importStar(__webpack_require__(/*! child_process */ "child_process"));
|
|
489
|
+
const os = __importStar(__webpack_require__(/*! os */ "os"));
|
|
490
|
+
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
491
|
+
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
492
|
+
const git_clone_1 = __webpack_require__(/*! ./git_clone */ "./build/git_clone.js");
|
|
493
|
+
const lib_folder_1 = __webpack_require__(/*! ./lib_folder */ "./build/lib_folder.js");
|
|
494
|
+
function libraryNames(libs) {
|
|
495
|
+
const used = new Set(["project"]);
|
|
496
|
+
return libs.map(lib => {
|
|
497
|
+
const source = (lib.url || lib.folder || "").replace(/\\/g, "/").replace(/\/+$/, "");
|
|
498
|
+
const name = lib.name ?? source.substring(Math.max(source.lastIndexOf("/"), source.lastIndexOf(":")) + 1)
|
|
499
|
+
.replace(/\.git$/i, "");
|
|
500
|
+
if (typeof name !== "string" || name.length === 0 || name === "." || name === ".."
|
|
501
|
+
|| /[<>:"/\\|?*\u0000-\u001f]/.test(name) || /[. ]$/.test(name)
|
|
502
|
+
|| /^(con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³])(\.|$)/i.test(name)) {
|
|
503
|
+
throw new Error("Invalid library name: " + JSON.stringify(name) + ". Set libs[].name to a valid folder name.");
|
|
504
|
+
}
|
|
505
|
+
if (used.has(name.toLowerCase())) {
|
|
506
|
+
throw new Error("Duplicate or reserved library name: " + name + ". Set a different libs[].name.");
|
|
507
|
+
}
|
|
508
|
+
used.add(name.toLowerCase());
|
|
509
|
+
return name;
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
async function loadLibraries(config) {
|
|
513
|
+
const libs = config.libs || [];
|
|
514
|
+
const names = libraryNames(libs);
|
|
515
|
+
const result = [];
|
|
516
|
+
for (const [index, lib] of libs.entries()) {
|
|
517
|
+
let dir;
|
|
518
|
+
let cleanupFolder = false;
|
|
519
|
+
const folder = (0, lib_folder_1.resolveLibFolder)(lib.folder, process.cwd());
|
|
520
|
+
if (folder !== undefined && fs.existsSync(folder)) {
|
|
521
|
+
console.log("From folder: " + folder);
|
|
522
|
+
dir = folder;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
if (!lib.url) {
|
|
526
|
+
throw new Error(folder === undefined
|
|
527
|
+
? "Library must define a non-empty url or an existing folder"
|
|
528
|
+
: "Library folder not found: " + folder);
|
|
529
|
+
}
|
|
530
|
+
console.log("Clone: " + lib.url);
|
|
531
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), "abap_transpile-"));
|
|
532
|
+
cleanupFolder = true;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
if (cleanupFolder) {
|
|
536
|
+
childProcess.execFileSync("git", (0, git_clone_1.buildGitCloneArguments)(lib.url), { cwd: dir, stdio: "inherit" });
|
|
537
|
+
}
|
|
538
|
+
const patterns = typeof lib.files === "string" && lib.files !== "" ? [lib.files]
|
|
539
|
+
: Array.isArray(lib.files) ? lib.files : ["/src/**"];
|
|
540
|
+
const excludeFilters = (lib.exclude_filter ?? []).map(pattern => new RegExp(pattern, "i"));
|
|
541
|
+
const filesToRead = new Set();
|
|
542
|
+
for (const pattern of patterns) {
|
|
543
|
+
for (const filename of file_operations_1.FileOperations.globSync(dir + pattern)) {
|
|
544
|
+
if (filename.endsWith(".clas.testclasses.abap") || excludeFilters.some(filter => filter.test(filename))) {
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
filesToRead.add(filename);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const files = await file_operations_1.FileOperations.readAllFiles([...filesToRead], config.output_folder);
|
|
551
|
+
result.push({ name: names[index], files });
|
|
552
|
+
console.log("\t" + files.length + " files added from lib");
|
|
553
|
+
}
|
|
554
|
+
finally {
|
|
555
|
+
if (cleanupFolder) {
|
|
556
|
+
file_operations_1.FileOperations.deleteFolderRecursive(dir);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
function libraryRegistry(files, libraries) {
|
|
563
|
+
const reg = new abaplint.Registry();
|
|
564
|
+
const folders = new Map();
|
|
565
|
+
const objects = new Map();
|
|
566
|
+
const sources = new Map();
|
|
567
|
+
// Libraries first: addFile() then replaces a dependency object with the project's object.
|
|
568
|
+
for (const lib of libraries) {
|
|
569
|
+
for (const file of lib.files) {
|
|
570
|
+
const memory = new abaplint.MemoryFile(file.filename, file.contents);
|
|
571
|
+
const type = memory.getObjectType()?.toUpperCase();
|
|
572
|
+
if (type === undefined || file.filename.split(".").length <= 2) {
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const key = type + ":" + memory.getObjectName().toUpperCase();
|
|
576
|
+
const owner = objects.get(key);
|
|
577
|
+
// abapGit repeats package.devc.xml across repositories; the registry keeps the last copy.
|
|
578
|
+
if (key !== "DEVC:PACKAGE" && owner !== undefined && owner !== lib.name) {
|
|
579
|
+
throw new Error("Ambiguous dependency object " + key + " in " + owner + " and " + lib.name);
|
|
580
|
+
}
|
|
581
|
+
objects.set(key, lib.name);
|
|
582
|
+
reg.addDependency(memory);
|
|
583
|
+
folders.set(file.filename.toLowerCase(), lib.name);
|
|
584
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
for (const file of files) {
|
|
588
|
+
reg.addFile(new abaplint.MemoryFile(file.filename, file.contents));
|
|
589
|
+
folders.set(file.filename.toLowerCase(), "project");
|
|
590
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
591
|
+
}
|
|
592
|
+
return { reg, folders, sources: [...sources.values()] };
|
|
593
|
+
}
|
|
594
|
+
//# sourceMappingURL=libraries.js.map
|
|
595
|
+
|
|
596
|
+
/***/ },
|
|
597
|
+
|
|
598
|
+
/***/ "./build/write_objects.js"
|
|
599
|
+
/*!********************************!*\
|
|
600
|
+
!*** ./build/write_objects.js ***!
|
|
601
|
+
\********************************/
|
|
602
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
603
|
+
|
|
604
|
+
"use strict";
|
|
605
|
+
|
|
606
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
607
|
+
if (k2 === undefined) k2 = k;
|
|
608
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
609
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
610
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
611
|
+
}
|
|
612
|
+
Object.defineProperty(o, k2, desc);
|
|
613
|
+
}) : (function(o, m, k, k2) {
|
|
614
|
+
if (k2 === undefined) k2 = k;
|
|
615
|
+
o[k2] = m[k];
|
|
616
|
+
}));
|
|
617
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
618
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
619
|
+
}) : function(o, v) {
|
|
620
|
+
o["default"] = v;
|
|
621
|
+
});
|
|
622
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
623
|
+
var ownKeys = function(o) {
|
|
624
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
625
|
+
var ar = [];
|
|
626
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
627
|
+
return ar;
|
|
628
|
+
};
|
|
629
|
+
return ownKeys(o);
|
|
630
|
+
};
|
|
631
|
+
return function (mod) {
|
|
632
|
+
if (mod && mod.__esModule) return mod;
|
|
633
|
+
var result = {};
|
|
634
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
635
|
+
__setModuleDefault(result, mod);
|
|
636
|
+
return result;
|
|
637
|
+
};
|
|
638
|
+
})();
|
|
639
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
640
|
+
exports.writeObjects = writeObjects;
|
|
641
|
+
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
642
|
+
const url_1 = __webpack_require__(/*! url */ "url");
|
|
643
|
+
const transpiler_1 = __webpack_require__(/*! @abaplint/transpiler */ "./node_modules/@abaplint/transpiler/build/src/index.js");
|
|
644
|
+
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
645
|
+
async function writeObjects(outputFiles, config, files) {
|
|
646
|
+
const root = path.resolve(config.output_folder);
|
|
647
|
+
const filesToWrite = [];
|
|
648
|
+
const destinations = new Set();
|
|
649
|
+
const sources = new Map(files.map(file => [file.filename.toLowerCase(), file]));
|
|
650
|
+
const add = (filename, contents) => {
|
|
651
|
+
const target = path.resolve(root, filename);
|
|
652
|
+
const relative = path.relative(root, target);
|
|
653
|
+
if (relative === "" || relative.startsWith(".." + path.sep) || relative === ".." || path.isAbsolute(relative)) {
|
|
654
|
+
throw new Error("Output file escapes output_folder: " + filename);
|
|
655
|
+
}
|
|
656
|
+
const key = target.toLowerCase();
|
|
657
|
+
if (destinations.has(key)) {
|
|
658
|
+
throw new Error("Conflicting output file: " + filename);
|
|
659
|
+
}
|
|
660
|
+
destinations.add(key);
|
|
661
|
+
filesToWrite.push({ path: target, contents });
|
|
662
|
+
};
|
|
663
|
+
for (const output of outputFiles) {
|
|
664
|
+
const type = output.object.type.toUpperCase();
|
|
665
|
+
let contents = output.chunk.getCode();
|
|
666
|
+
let generatedLineOffset = 0;
|
|
667
|
+
if (type === "PROG") {
|
|
668
|
+
contents = 'if (!globalThis.abap) await import("' + (0, transpiler_1.importPath)(output.filename, "_init.mjs") + '");\n' + contents;
|
|
669
|
+
generatedLineOffset = 1;
|
|
670
|
+
}
|
|
671
|
+
if (config.write_source_map === true && (type === "PROG" || type === "FUGR" || type === "CLAS")) {
|
|
672
|
+
const name = output.filename + ".map";
|
|
673
|
+
contents += "\n//# sourceMappingURL=" + encodeURIComponent(path.basename(name));
|
|
674
|
+
const sourcePaths = {};
|
|
675
|
+
const sourceContents = {};
|
|
676
|
+
const mapDirectory = path.dirname(path.join(root, name));
|
|
677
|
+
for (const filename of new Set(output.chunk.mappings.map(mapping => mapping.source))) {
|
|
678
|
+
const file = sources.get(filename.toLowerCase());
|
|
679
|
+
if (file === undefined) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
if (file.relative !== undefined) {
|
|
683
|
+
const source = path.resolve(root, file.relative, file.filename);
|
|
684
|
+
const relative = path.relative(mapDirectory, source);
|
|
685
|
+
// Sources on another Windows drive cannot be expressed as relative paths.
|
|
686
|
+
sourcePaths[filename] = path.isAbsolute(relative) ? (0, url_1.pathToFileURL)(source).href
|
|
687
|
+
: relative.split(path.sep).map(segment => encodeURIComponent(segment)).join("/");
|
|
688
|
+
}
|
|
689
|
+
// Include sources for local and cloned libraries; clones are removed before emission.
|
|
690
|
+
sourceContents[filename] = file.contents;
|
|
691
|
+
}
|
|
692
|
+
add(name, output.chunk.getMap(path.basename(output.filename), { generatedLineOffset, sourcePaths, sourceContents }));
|
|
693
|
+
}
|
|
694
|
+
add(output.filename, contents);
|
|
695
|
+
}
|
|
696
|
+
await file_operations_1.FileOperations.writeFiles(filesToWrite);
|
|
697
|
+
}
|
|
698
|
+
//# sourceMappingURL=write_objects.js.map
|
|
699
|
+
|
|
700
|
+
/***/ },
|
|
701
|
+
|
|
556
702
|
/***/ "./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js"
|
|
557
703
|
/*!*********************************************************************!*\
|
|
558
704
|
!*** ./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js ***!
|
|
@@ -10941,7 +11087,7 @@ class StringTemplateFormatting extends combi_1.Expression {
|
|
|
10941
11087
|
const alpha = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("ALPHA =", alphaOptions), { also: combi_1.AlsoIn.OpenABAP });
|
|
10942
11088
|
const xsd = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("XSD =", zeroXSDOptions));
|
|
10943
11089
|
const country = (0, combi_1.seq)("COUNTRY =", _1.Source);
|
|
10944
|
-
const formatting = (0, combi_1.altPrio)((0, combi_1.seq)("TIME =", dateTimeOptions), (0, combi_1.seq)("DATE =", dateTimeOptions), (0, combi_1.seq)("CASE =", caseOptions), (0, combi_1.seq)("
|
|
11090
|
+
const formatting = (0, combi_1.altPrio)((0, combi_1.seq)("TIME =", dateTimeOptions), (0, combi_1.seq)("DATE =", dateTimeOptions), (0, combi_1.seq)("CASE =", caseOptions), (0, combi_1.seq)("ZERO =", zeroXSDOptions), xsd, (0, combi_1.seq)("STYLE =", styleOptions), (0, combi_1.seq)("CURRENCY =", _1.Source), (0, combi_1.per)(sign, number, decimals, width, pad, alpha, align, country, (0, combi_1.seq)("EXPONENT =", _1.Source)), (0, combi_1.per)(timezone, timestamp));
|
|
10945
11091
|
return formatting;
|
|
10946
11092
|
}
|
|
10947
11093
|
}
|
|
@@ -30673,12 +30819,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
30673
30819
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
30674
30820
|
exports.Compare = void 0;
|
|
30675
30821
|
const Expressions = __importStar(__webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js"));
|
|
30822
|
+
const nodes_1 = __webpack_require__(/*! ../../nodes */ "./node_modules/@abaplint/core/build/src/abap/nodes/index.js");
|
|
30676
30823
|
const source_1 = __webpack_require__(/*! ./source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
|
|
30677
30824
|
const method_call_chain_1 = __webpack_require__(/*! ./method_call_chain */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/method_call_chain.js");
|
|
30678
30825
|
const source_field_symbol_1 = __webpack_require__(/*! ./source_field_symbol */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source_field_symbol.js");
|
|
30679
30826
|
const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
|
|
30680
30827
|
const basic_1 = __webpack_require__(/*! ../../types/basic */ "./node_modules/@abaplint/core/build/src/abap/types/basic/index.js");
|
|
30681
30828
|
const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
|
|
30829
|
+
const _builtin_1 = __webpack_require__(/*! ../_builtin */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_builtin.js");
|
|
30830
|
+
const _object_oriented_1 = __webpack_require__(/*! ../_object_oriented */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_object_oriented.js");
|
|
30682
30831
|
class Compare {
|
|
30683
30832
|
static runSyntax(node, input) {
|
|
30684
30833
|
var _a;
|
|
@@ -30693,6 +30842,11 @@ class Compare {
|
|
|
30693
30842
|
for (const t of node.findDirectExpressions(Expressions.MethodCallChain)) {
|
|
30694
30843
|
method_call_chain_1.MethodCallChain.runSyntax(t, input);
|
|
30695
30844
|
}
|
|
30845
|
+
const initialMessage = this.checkInitialOperand(node, input);
|
|
30846
|
+
if (initialMessage !== undefined) {
|
|
30847
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), initialMessage));
|
|
30848
|
+
return;
|
|
30849
|
+
}
|
|
30696
30850
|
const typeUtils = new _type_utils_1.TypeUtils(input.scope);
|
|
30697
30851
|
const compareOperator = (_a = node.findDirectExpression(Expressions.CompareOperator)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
|
|
30698
30852
|
if (compareOperator === "CS"
|
|
@@ -30716,6 +30870,46 @@ class Compare {
|
|
|
30716
30870
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
30717
30871
|
}
|
|
30718
30872
|
}
|
|
30873
|
+
// a built-in function with a character-like result cannot be the operand of IS [NOT] INITIAL,
|
|
30874
|
+
// "Unexpected operator IS" on a system, while one with a numeric result, lines( ), can
|
|
30875
|
+
static checkInitialOperand(node, input) {
|
|
30876
|
+
var _a, _b, _c, _d;
|
|
30877
|
+
if (input.scope.getOpenABAP()) {
|
|
30878
|
+
return undefined;
|
|
30879
|
+
}
|
|
30880
|
+
const tokens = node.getChildren().filter(c => c instanceof nodes_1.TokenNode).map(c => c.getFirstToken().getStr().toUpperCase());
|
|
30881
|
+
if (tokens.includes("IS") === false || tokens[tokens.length - 1] !== "INITIAL") {
|
|
30882
|
+
return undefined;
|
|
30883
|
+
}
|
|
30884
|
+
const chain = (_a = node.findDirectExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.getChildren();
|
|
30885
|
+
// xsdbool( ) and boolc( ) are their own form in the Source grammar, a condition in parentheses
|
|
30886
|
+
const first = (_b = chain === null || chain === void 0 ? void 0 : chain[0]) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr().toUpperCase();
|
|
30887
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) === 4 && chain[0] instanceof nodes_1.TokenNode && (first === "XSDBOOL" || first === "BOOLC")) {
|
|
30888
|
+
return `Built-in function "${chain[0].getFirstToken().getStr()}" cannot be the operand of IS INITIAL`;
|
|
30889
|
+
}
|
|
30890
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) !== 1 || !(chain[0] instanceof nodes_1.ExpressionNode) || !(chain[0].get() instanceof Expressions.MethodCallChain)) {
|
|
30891
|
+
return undefined;
|
|
30892
|
+
}
|
|
30893
|
+
const calls = chain[0].getChildren();
|
|
30894
|
+
if (calls.length !== 1 || !(calls[0] instanceof nodes_1.ExpressionNode) || !(calls[0].get() instanceof Expressions.MethodCall)) {
|
|
30895
|
+
return undefined;
|
|
30896
|
+
}
|
|
30897
|
+
const name = (_c = calls[0].findDirectExpression(Expressions.MethodName)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
30898
|
+
const builtin = _builtin_1.BuiltIn.searchBuiltin(name);
|
|
30899
|
+
if (name === undefined || builtin === undefined) {
|
|
30900
|
+
return undefined;
|
|
30901
|
+
}
|
|
30902
|
+
// a method of the same name hides the built-in function
|
|
30903
|
+
const enclosing = input.scope.findClassDefinition(input.scope.getEnclosingClassName());
|
|
30904
|
+
if (enclosing !== undefined && new _object_oriented_1.ObjectOriented(input.scope).searchMethodName(enclosing, name).method !== undefined) {
|
|
30905
|
+
return undefined;
|
|
30906
|
+
}
|
|
30907
|
+
const returning = (_d = builtin.getParameters().getReturning()) === null || _d === void 0 ? void 0 : _d.getType();
|
|
30908
|
+
if (returning instanceof basic_1.StringType || returning instanceof basic_1.CharacterType) {
|
|
30909
|
+
return `Built-in function "${name}" cannot be the operand of IS INITIAL`;
|
|
30910
|
+
}
|
|
30911
|
+
return undefined;
|
|
30912
|
+
}
|
|
30719
30913
|
}
|
|
30720
30914
|
exports.Compare = Compare;
|
|
30721
30915
|
//# sourceMappingURL=compare.js.map
|
|
@@ -71077,7 +71271,7 @@ class Registry {
|
|
|
71077
71271
|
}
|
|
71078
71272
|
static abaplintVersion() {
|
|
71079
71273
|
// magic, see build script "version.js"
|
|
71080
|
-
return "2.120.
|
|
71274
|
+
return "2.120.71";
|
|
71081
71275
|
}
|
|
71082
71276
|
getDDICReferences() {
|
|
71083
71277
|
return this.ddicReferences;
|
|
@@ -73766,7 +73960,7 @@ exports.CDSCheckSyntaxConf = CDSCheckSyntaxConf;
|
|
|
73766
73960
|
const KNOWN_QUAN_DATA_ELEMENTS = ["MENGE_D"];
|
|
73767
73961
|
const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
|
|
73768
73962
|
// Reserved names, cannot be used as element names, see DDIC table TRESE
|
|
73769
|
-
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
|
|
73963
|
+
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION", "ZONE", "HANDLER", "SECTION"];
|
|
73770
73964
|
const MAX_LABEL_LENGTH = 40;
|
|
73771
73965
|
// Annotations which are not supported in CDS view entities
|
|
73772
73966
|
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure", "Semantics.currencyCode"];
|
|
@@ -95476,7 +95670,8 @@ class RedundantConversion {
|
|
|
95476
95670
|
key: "redundant_conversion",
|
|
95477
95671
|
title: "Redundant Conversion",
|
|
95478
95672
|
shortDescription: `Find redundant CONV expressions`,
|
|
95479
|
-
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type
|
|
95673
|
+
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type,
|
|
95674
|
+
including the result of a built-in function with a fixed result type, like to_upper( ) or strlen( ).`,
|
|
95480
95675
|
tags: [_irule_1.RuleTag.Quickfix],
|
|
95481
95676
|
badExample: `DATA text TYPE string.
|
|
95482
95677
|
text = CONV string( text ).`,
|
|
@@ -95513,7 +95708,8 @@ text = text.`,
|
|
|
95513
95708
|
if (structure === undefined) {
|
|
95514
95709
|
continue;
|
|
95515
95710
|
}
|
|
95516
|
-
|
|
95711
|
+
// recursive, a CONV can be the argument of a built-in function, which is itself a Source
|
|
95712
|
+
for (const source of structure.findAllExpressionsRecursive(Expressions.Source)) {
|
|
95517
95713
|
if (source.getFirstToken().getStr().toUpperCase() !== "CONV") {
|
|
95518
95714
|
continue;
|
|
95519
95715
|
}
|
|
@@ -95572,6 +95768,15 @@ text = text.`,
|
|
|
95572
95768
|
}
|
|
95573
95769
|
sourceType(source, scope) {
|
|
95574
95770
|
let context;
|
|
95771
|
+
// boolc( <condition> ) is not a MethodCallChain, xsdbool( ) has the same shape but is not reported
|
|
95772
|
+
const first = source.getFirstToken();
|
|
95773
|
+
if (first.getStr().toUpperCase() === "BOOLC"
|
|
95774
|
+
&& source.findDirectExpression(Expressions.Cond) !== undefined
|
|
95775
|
+
&& source.getChildren().length === 4
|
|
95776
|
+
&& scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95777
|
+
&& reference.position.getStart().equals(first.getStart()))) {
|
|
95778
|
+
return basic_1.StringType.get();
|
|
95779
|
+
}
|
|
95575
95780
|
for (const child of source.getChildren()) {
|
|
95576
95781
|
if (!(child instanceof nodes_1.ExpressionNode)) {
|
|
95577
95782
|
continue;
|
|
@@ -95582,6 +95787,15 @@ text = text.`,
|
|
|
95582
95787
|
return undefined;
|
|
95583
95788
|
}
|
|
95584
95789
|
}
|
|
95790
|
+
else if (child.get() instanceof Expressions.MethodCallChain) {
|
|
95791
|
+
if (source.getChildren().length !== 1) {
|
|
95792
|
+
return undefined;
|
|
95793
|
+
}
|
|
95794
|
+
context = this.builtinResultType(child, scope);
|
|
95795
|
+
if (context === undefined) {
|
|
95796
|
+
return undefined;
|
|
95797
|
+
}
|
|
95798
|
+
}
|
|
95585
95799
|
else if (child.get() instanceof Expressions.Constant) {
|
|
95586
95800
|
context = this.infer(context, constant_1.Constant.runSyntax(child));
|
|
95587
95801
|
}
|
|
@@ -95602,6 +95816,32 @@ text = text.`,
|
|
|
95602
95816
|
}
|
|
95603
95817
|
return context;
|
|
95604
95818
|
}
|
|
95819
|
+
/** The result type of a call to a built-in function whose result type does not depend on its arguments,
|
|
95820
|
+
* undefined for anything else, e.g. abs( ) or xsdbool( ), or a method of the same name */
|
|
95821
|
+
builtinResultType(chain, scope) {
|
|
95822
|
+
var _a;
|
|
95823
|
+
const children = chain.getChildren();
|
|
95824
|
+
if (children.length !== 1 || !(children[0].get() instanceof Expressions.MethodCall)) {
|
|
95825
|
+
return undefined;
|
|
95826
|
+
}
|
|
95827
|
+
const name = (_a = children[0].findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
95828
|
+
if (name === undefined) {
|
|
95829
|
+
return undefined;
|
|
95830
|
+
}
|
|
95831
|
+
const isBuiltin = scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95832
|
+
&& reference.position.getStart().equals(name.getStart()));
|
|
95833
|
+
if (isBuiltin === false) {
|
|
95834
|
+
return undefined;
|
|
95835
|
+
}
|
|
95836
|
+
const upper = name.getStr().toUpperCase();
|
|
95837
|
+
if (RedundantConversion.stringResult.has(upper)) {
|
|
95838
|
+
return basic_1.StringType.get();
|
|
95839
|
+
}
|
|
95840
|
+
else if (RedundantConversion.integerResult.has(upper)) {
|
|
95841
|
+
return basic_1.IntegerType.get();
|
|
95842
|
+
}
|
|
95843
|
+
return undefined;
|
|
95844
|
+
}
|
|
95605
95845
|
fieldChainType(fieldChain, scope) {
|
|
95606
95846
|
var _a;
|
|
95607
95847
|
const operand = (_a = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.DataReadReference
|
|
@@ -95666,6 +95906,17 @@ text = text.`,
|
|
|
95666
95906
|
}
|
|
95667
95907
|
}
|
|
95668
95908
|
exports.RedundantConversion = RedundantConversion;
|
|
95909
|
+
// built-in functions that always return a string, whatever their arguments
|
|
95910
|
+
RedundantConversion.stringResult = new Set([
|
|
95911
|
+
"BOOLC", "CONCAT_LINES_OF", "CONDENSE", "ESCAPE", "FROM_MIXED", "INSERT", "REPEAT", "REPLACE",
|
|
95912
|
+
"REVERSE", "SEGMENT", "SHIFT_LEFT", "SHIFT_RIGHT", "SUBSTRING", "SUBSTRING_AFTER", "SUBSTRING_BEFORE",
|
|
95913
|
+
"SUBSTRING_FROM", "SUBSTRING_TO", "TO_LOWER", "TO_MIXED", "TO_UPPER", "TRANSLATE"
|
|
95914
|
+
]);
|
|
95915
|
+
// built-in functions that always return an i
|
|
95916
|
+
RedundantConversion.integerResult = new Set([
|
|
95917
|
+
"CHARLEN", "COUNT", "COUNT_ANY_NOT_OF", "COUNT_ANY_OF", "DBMAXLEN", "DISTANCE", "FIND", "FIND_ANY_NOT_OF",
|
|
95918
|
+
"FIND_ANY_OF", "FIND_END", "LINES", "NUMOFCHAR", "STRLEN", "XSTRLEN"
|
|
95919
|
+
]);
|
|
95669
95920
|
//# sourceMappingURL=redundant_conversion.js.map
|
|
95670
95921
|
|
|
95671
95922
|
/***/ },
|
|
@@ -102871,7 +103122,7 @@ class XMLConsistency {
|
|
|
102871
103122
|
}
|
|
102872
103123
|
runTable(obj, file) {
|
|
102873
103124
|
var _a, _b, _c, _d;
|
|
102874
|
-
var _e;
|
|
103125
|
+
var _e, _f;
|
|
102875
103126
|
const issues = [];
|
|
102876
103127
|
for (const field of (_e = obj.getFields()) !== null && _e !== void 0 ? _e : []) {
|
|
102877
103128
|
if (field.DATATYPE === "QUAN" && (!((_a = field.REFTABLE) === null || _a === void 0 ? void 0 : _a.trim()) || !((_b = field.REFFIELD) === null || _b === void 0 ? void 0 : _b.trim()))) {
|
|
@@ -102880,6 +103131,14 @@ class XMLConsistency {
|
|
|
102880
103131
|
}
|
|
102881
103132
|
}
|
|
102882
103133
|
if (obj.getTableCategory() === Objects.TableCategory.Transparent) {
|
|
103134
|
+
// Confirmed reserved database field names, see issue #4331, DAY and HOUR reported by activation.
|
|
103135
|
+
// TRESE also contains names such as TEXT and LENGTH which are allowed here.
|
|
103136
|
+
const reservedFieldNames = ["ZONE", "HANDLER", "SECTION", "PARAMETER", "DAY", "HOUR"];
|
|
103137
|
+
for (const field of (_f = obj.getFields()) !== null && _f !== void 0 ? _f : []) {
|
|
103138
|
+
if (reservedFieldNames.includes(field.FIELDNAME.toUpperCase())) {
|
|
103139
|
+
issues.push(issue_1.Issue.atRow(file, 1, `Table field name "${field.FIELDNAME}" is reserved`, this.getMetadata().key, this.conf.severity));
|
|
103140
|
+
}
|
|
103141
|
+
}
|
|
102883
103142
|
if (!((_c = obj.getDeliveryClass()) === null || _c === void 0 ? void 0 : _c.trim())) {
|
|
102884
103143
|
const message = `Transparent table must have delivery class(CONTFLAG in DD02V) set`;
|
|
102885
103144
|
issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.transparentTableSeverity));
|
|
@@ -104490,6 +104749,12 @@ class Chunk {
|
|
|
104490
104749
|
original: m.original,
|
|
104491
104750
|
generated: { line: m.generated.line + offset, column: m.generated.column },
|
|
104492
104751
|
}));
|
|
104752
|
+
for (const source of new Set(this.mappings.map(m => m.source))) {
|
|
104753
|
+
const contents = options?.sourceContents?.[source];
|
|
104754
|
+
if (contents !== undefined) {
|
|
104755
|
+
sourceMapGenerator.setSourceContent(sourcePaths[source] ?? source, contents);
|
|
104756
|
+
}
|
|
104757
|
+
}
|
|
104493
104758
|
const json = sourceMapGenerator.toJSON();
|
|
104494
104759
|
json.file = generatedFilename;
|
|
104495
104760
|
json.sourceRoot = "";
|
|
@@ -104501,6 +104766,231 @@ exports.Chunk = Chunk;
|
|
|
104501
104766
|
|
|
104502
104767
|
/***/ },
|
|
104503
104768
|
|
|
104769
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js"
|
|
104770
|
+
/*!*****************************************************************************!*\
|
|
104771
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js ***!
|
|
104772
|
+
\*****************************************************************************/
|
|
104773
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
104774
|
+
|
|
104775
|
+
"use strict";
|
|
104776
|
+
|
|
104777
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
104778
|
+
if (k2 === undefined) k2 = k;
|
|
104779
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
104780
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
104781
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
104782
|
+
}
|
|
104783
|
+
Object.defineProperty(o, k2, desc);
|
|
104784
|
+
}) : (function(o, m, k, k2) {
|
|
104785
|
+
if (k2 === undefined) k2 = k;
|
|
104786
|
+
o[k2] = m[k];
|
|
104787
|
+
}));
|
|
104788
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
104789
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
104790
|
+
}) : function(o, v) {
|
|
104791
|
+
o["default"] = v;
|
|
104792
|
+
});
|
|
104793
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
104794
|
+
var ownKeys = function(o) {
|
|
104795
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
104796
|
+
var ar = [];
|
|
104797
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
104798
|
+
return ar;
|
|
104799
|
+
};
|
|
104800
|
+
return ownKeys(o);
|
|
104801
|
+
};
|
|
104802
|
+
return function (mod) {
|
|
104803
|
+
if (mod && mod.__esModule) return mod;
|
|
104804
|
+
var result = {};
|
|
104805
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
104806
|
+
__setModuleDefault(result, mod);
|
|
104807
|
+
return result;
|
|
104808
|
+
};
|
|
104809
|
+
})();
|
|
104810
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
104811
|
+
exports.CDSDatabaseView = void 0;
|
|
104812
|
+
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
104813
|
+
const cds = abaplint.ExpressionsCDS;
|
|
104814
|
+
/** SQL for the supported relational subset of CDS. Never discard unknown syntax. */
|
|
104815
|
+
class CDSDatabaseView {
|
|
104816
|
+
reg;
|
|
104817
|
+
viewName = "";
|
|
104818
|
+
sources = [];
|
|
104819
|
+
constructor(reg) {
|
|
104820
|
+
this.reg = reg;
|
|
104821
|
+
}
|
|
104822
|
+
build(obj) {
|
|
104823
|
+
this.viewName = obj.getName();
|
|
104824
|
+
const tree = new abaplint.CDSParser().parse(obj.findSourceFile());
|
|
104825
|
+
if (tree === undefined) {
|
|
104826
|
+
return this.unsupported("could not parse CDS definition");
|
|
104827
|
+
}
|
|
104828
|
+
else if (!(tree.get() instanceof cds.CDSDefineView)) {
|
|
104829
|
+
return undefined; // Abstract/custom entities have no database view.
|
|
104830
|
+
}
|
|
104831
|
+
const name = tree.findDirectExpression(cds.CDSName);
|
|
104832
|
+
const select = tree.findDirectExpression(cds.CDSSelect);
|
|
104833
|
+
if (name === undefined || select === undefined) {
|
|
104834
|
+
return this.unsupported("expected a SELECT view");
|
|
104835
|
+
}
|
|
104836
|
+
this.viewName = this.name(name);
|
|
104837
|
+
for (const child of tree.getChildren()) {
|
|
104838
|
+
if (child === name || child === select || child.get() instanceof cds.CDSAnnotation) {
|
|
104839
|
+
continue;
|
|
104840
|
+
}
|
|
104841
|
+
this.keyword(child, ["DEFINE", "ROOT", "VIEW", "ENTITY", "AS", ";"]);
|
|
104842
|
+
}
|
|
104843
|
+
const source = select.findDirectExpression(cds.CDSSource);
|
|
104844
|
+
if (source === undefined) {
|
|
104845
|
+
return this.unsupported("missing source");
|
|
104846
|
+
}
|
|
104847
|
+
const from = [this.source(source)];
|
|
104848
|
+
for (const join of select.findDirectExpressions(cds.CDSJoin)) {
|
|
104849
|
+
from.push(this.join(join));
|
|
104850
|
+
}
|
|
104851
|
+
const elements = select.findDirectExpressions(cds.CDSElement);
|
|
104852
|
+
if (elements.length === 0) {
|
|
104853
|
+
return this.unsupported("expected explicit projected fields");
|
|
104854
|
+
}
|
|
104855
|
+
const columns = elements.map(e => this.element(e)).join(", ");
|
|
104856
|
+
let where = "";
|
|
104857
|
+
for (const child of select.getChildren()) {
|
|
104858
|
+
if (child === source || child.get() instanceof cds.CDSJoin || child.get() instanceof cds.CDSElement) {
|
|
104859
|
+
continue;
|
|
104860
|
+
}
|
|
104861
|
+
else if (child.get() instanceof cds.CDSWhere) {
|
|
104862
|
+
where = " " + this.expression(child);
|
|
104863
|
+
}
|
|
104864
|
+
else {
|
|
104865
|
+
this.keyword(child, ["SELECT", "DISTINCT", "FROM", "{", "}", ","]);
|
|
104866
|
+
}
|
|
104867
|
+
}
|
|
104868
|
+
const distinct = select.findDirectTokenByText("DISTINCT") ? "DISTINCT " : "";
|
|
104869
|
+
return `CREATE VIEW ${this.quote(this.viewName)} AS SELECT ${distinct}${columns} FROM ${from.join(" ")}${where};`;
|
|
104870
|
+
}
|
|
104871
|
+
source(node) {
|
|
104872
|
+
const nameNode = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104873
|
+
if (nameNode === undefined) {
|
|
104874
|
+
return this.unsupported("expected a table source");
|
|
104875
|
+
}
|
|
104876
|
+
const name = this.name(nameNode);
|
|
104877
|
+
if (this.reg.getObject("TABL", name)?.getType() !== "TABL") {
|
|
104878
|
+
return this.unsupported(`source ${name} does not resolve to a TABL`);
|
|
104879
|
+
}
|
|
104880
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104881
|
+
const alias = as?.findDirectExpression(cds.CDSName) || node.findDirectExpression(cds.CDSName);
|
|
104882
|
+
for (const child of node.getChildren()) {
|
|
104883
|
+
if (child !== nameNode && child !== as && child !== alias) {
|
|
104884
|
+
return this.unsupported("source parameters, filters or nested joins");
|
|
104885
|
+
}
|
|
104886
|
+
}
|
|
104887
|
+
this.sources.push(alias ? this.name(alias) : name);
|
|
104888
|
+
return this.quote(name) + (alias ? " AS " + this.quote(this.name(alias)) : "");
|
|
104889
|
+
}
|
|
104890
|
+
join(node) {
|
|
104891
|
+
const sources = node.findDirectExpressions(cds.CDSSource);
|
|
104892
|
+
const conditions = node.findDirectExpressions(cds.CDSCondition);
|
|
104893
|
+
const words = node.getDirectTokens().map(t => t.getStr().toUpperCase()).join(" ");
|
|
104894
|
+
const match = /^(?:(INNER|LEFT OUTER|RIGHT OUTER|CROSS) )?JOIN(?: ON)?$/.exec(words);
|
|
104895
|
+
if (sources.length !== 1 || match === null) {
|
|
104896
|
+
return this.unsupported("join shape: " + node.concatTokens());
|
|
104897
|
+
}
|
|
104898
|
+
const kind = match[1] || "INNER";
|
|
104899
|
+
if (conditions.length !== (kind === "CROSS" ? 0 : 1)) {
|
|
104900
|
+
return this.unsupported("join requires an ON condition (except CROSS JOIN)");
|
|
104901
|
+
}
|
|
104902
|
+
const source = this.source(sources[0]);
|
|
104903
|
+
return kind + " JOIN " + source + (conditions.length ? " ON " + this.expression(conditions[0]) : "");
|
|
104904
|
+
}
|
|
104905
|
+
element(node) {
|
|
104906
|
+
const field = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104907
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104908
|
+
for (const child of node.getChildren()) {
|
|
104909
|
+
if (child === field || child === as || child.get() instanceof cds.CDSAnnotation) {
|
|
104910
|
+
continue;
|
|
104911
|
+
}
|
|
104912
|
+
this.keyword(child, ["KEY"]);
|
|
104913
|
+
}
|
|
104914
|
+
if (field === undefined) {
|
|
104915
|
+
return this.unsupported("expected a projected source field");
|
|
104916
|
+
}
|
|
104917
|
+
const parts = this.fieldParts(field);
|
|
104918
|
+
const alias = as?.findDirectExpression(cds.CDSName);
|
|
104919
|
+
return this.field(field) + " AS " + this.quote(alias ? this.name(alias) : parts[parts.length - 1]);
|
|
104920
|
+
}
|
|
104921
|
+
expression(node) {
|
|
104922
|
+
if (node instanceof abaplint.Nodes.TokenNode) {
|
|
104923
|
+
return this.keyword(node, ["WHERE", "AND", "OR", "NOT", "IS", "NULL", "LIKE", "ESCAPE", "BETWEEN",
|
|
104924
|
+
"=", "!", "<", ">", "(", ")"]);
|
|
104925
|
+
}
|
|
104926
|
+
else if (node.get() instanceof cds.CDSPrefixedName) {
|
|
104927
|
+
if (node.getTokens().map(t => t.getStr()).join("").toLowerCase() === "$session.system_language") {
|
|
104928
|
+
return "'E'";
|
|
104929
|
+
}
|
|
104930
|
+
return this.field(node);
|
|
104931
|
+
}
|
|
104932
|
+
else if (node.get() instanceof cds.CDSString || node.get() instanceof cds.CDSInteger) {
|
|
104933
|
+
return node.getTokens().map(t => t.getStr()).join("");
|
|
104934
|
+
}
|
|
104935
|
+
else if (node.get() instanceof cds.CDSCondition || node.get() instanceof cds.CDSWhere) {
|
|
104936
|
+
const parts = [];
|
|
104937
|
+
for (const child of node.getChildren()) {
|
|
104938
|
+
const part = this.expression(child);
|
|
104939
|
+
if (["<", ">", "!"].includes(parts[parts.length - 1]) && ["=", ">"].includes(part)) {
|
|
104940
|
+
parts[parts.length - 1] += part;
|
|
104941
|
+
}
|
|
104942
|
+
else {
|
|
104943
|
+
parts.push(part);
|
|
104944
|
+
}
|
|
104945
|
+
}
|
|
104946
|
+
return parts.join(" ");
|
|
104947
|
+
}
|
|
104948
|
+
return this.unsupported(node.concatTokens());
|
|
104949
|
+
}
|
|
104950
|
+
field(node) {
|
|
104951
|
+
const parts = this.fieldParts(node);
|
|
104952
|
+
if (parts.length === 1 && this.sources.length === 1) {
|
|
104953
|
+
parts.unshift(this.sources[0]);
|
|
104954
|
+
}
|
|
104955
|
+
else if (parts.length === 2 && !this.sources.includes(parts[0])) {
|
|
104956
|
+
return this.unsupported("unknown source qualifier " + parts[0]);
|
|
104957
|
+
}
|
|
104958
|
+
return parts.map(p => this.quote(p)).join(".");
|
|
104959
|
+
}
|
|
104960
|
+
fieldParts(node) {
|
|
104961
|
+
const text = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104962
|
+
const parts = text.split(".");
|
|
104963
|
+
if (parts.length > 2 || parts.some(p => !/^(\/\w+\/)?\w+$/.test(p))) {
|
|
104964
|
+
return this.unsupported("field path " + text);
|
|
104965
|
+
}
|
|
104966
|
+
return parts;
|
|
104967
|
+
}
|
|
104968
|
+
name(node) {
|
|
104969
|
+
const name = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104970
|
+
if (!/^(\/\w+\/)?\w+$/.test(name)) {
|
|
104971
|
+
return this.unsupported("identifier " + name);
|
|
104972
|
+
}
|
|
104973
|
+
return name;
|
|
104974
|
+
}
|
|
104975
|
+
keyword(node, allowed) {
|
|
104976
|
+
const text = node.concatTokens().toUpperCase();
|
|
104977
|
+
if (!(node instanceof abaplint.Nodes.TokenNode) || !allowed.includes(text)) {
|
|
104978
|
+
return this.unsupported(node.concatTokens());
|
|
104979
|
+
}
|
|
104980
|
+
return text;
|
|
104981
|
+
}
|
|
104982
|
+
quote(name) {
|
|
104983
|
+
return '"' + name.toLowerCase().replace(/"/g, '""') + '"';
|
|
104984
|
+
}
|
|
104985
|
+
unsupported(detail) {
|
|
104986
|
+
throw new Error(`CDS view ${this.viewName}: unsupported database definition: ${detail}`);
|
|
104987
|
+
}
|
|
104988
|
+
}
|
|
104989
|
+
exports.CDSDatabaseView = CDSDatabaseView;
|
|
104990
|
+
//# sourceMappingURL=cds_database_view.js.map
|
|
104991
|
+
|
|
104992
|
+
/***/ },
|
|
104993
|
+
|
|
104504
104994
|
/***/ "./node_modules/@abaplint/transpiler/build/src/db/index.js"
|
|
104505
104995
|
/*!*****************************************************************!*\
|
|
104506
104996
|
!*** ./node_modules/@abaplint/transpiler/build/src/db/index.js ***!
|
|
@@ -104549,6 +105039,7 @@ const sqlite_database_schema_1 = __webpack_require__(/*! ./schema_generation/sql
|
|
|
104549
105039
|
const pg_database_schema_1 = __webpack_require__(/*! ./schema_generation/pg_database_schema */ "./node_modules/@abaplint/transpiler/build/src/db/schema_generation/pg_database_schema.js");
|
|
104550
105040
|
const snowflake_database_schema_1 = __webpack_require__(/*! ./schema_generation/snowflake_database_schema */ "./node_modules/@abaplint/transpiler/build/src/db/schema_generation/snowflake_database_schema.js");
|
|
104551
105041
|
const populate_tables_1 = __webpack_require__(/*! ./populate_tables */ "./node_modules/@abaplint/transpiler/build/src/db/populate_tables.js");
|
|
105042
|
+
const cds_database_view_1 = __webpack_require__(/*! ./cds_database_view */ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js");
|
|
104552
105043
|
/////////////////////////
|
|
104553
105044
|
// NOTES
|
|
104554
105045
|
/////////////////////////
|
|
@@ -104560,9 +105051,11 @@ class DatabaseSetup {
|
|
|
104560
105051
|
this.reg = reg;
|
|
104561
105052
|
}
|
|
104562
105053
|
run(options) {
|
|
105054
|
+
// CDS views are dialect independent SQL, added after the tables and views they select from
|
|
105055
|
+
const cdsViews = this.buildCDSViews();
|
|
104563
105056
|
return {
|
|
104564
105057
|
schemas: {
|
|
104565
|
-
sqlite: this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)),
|
|
105058
|
+
sqlite: [...this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)), ...cdsViews],
|
|
104566
105059
|
// HANA takes the PG schema unchanged -- measured against HANA Express
|
|
104567
105060
|
// on a tree of 77 tables. The one thing it needs is that identifiers
|
|
104568
105061
|
// reach it quoted in UPPER case, and that is not a dialect of DDL: the
|
|
@@ -104571,13 +105064,25 @@ class DatabaseSetup {
|
|
|
104571
105064
|
// here. (Unquoted would nearly work and then meet a column called
|
|
104572
105065
|
// `cross`, which is one of HANA's reserved words.)
|
|
104573
105066
|
hdb: this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)),
|
|
104574
|
-
pg: this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)),
|
|
104575
|
-
snowflake: this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)),
|
|
105067
|
+
pg: [...this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)), ...cdsViews],
|
|
105068
|
+
snowflake: [...this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)), ...cdsViews],
|
|
104576
105069
|
},
|
|
104577
105070
|
insert: this.buildInsert(options),
|
|
104578
105071
|
};
|
|
104579
105072
|
}
|
|
104580
105073
|
////////////////////
|
|
105074
|
+
buildCDSViews() {
|
|
105075
|
+
const views = [];
|
|
105076
|
+
for (const obj of this.reg.getObjects()) {
|
|
105077
|
+
if (obj instanceof abaplint.Objects.DataDefinition) {
|
|
105078
|
+
const view = new cds_database_view_1.CDSDatabaseView(this.reg).build(obj);
|
|
105079
|
+
if (view !== undefined) {
|
|
105080
|
+
views.push(view);
|
|
105081
|
+
}
|
|
105082
|
+
}
|
|
105083
|
+
}
|
|
105084
|
+
return views;
|
|
105085
|
+
}
|
|
104581
105086
|
driver(schemaGenerator) {
|
|
104582
105087
|
const statements = [];
|
|
104583
105088
|
// CREATE TABLEs
|
|
@@ -105728,12 +106233,12 @@ class CompareTranspiler {
|
|
|
105728
106233
|
const field = concat.replace(" IS NOT REQUESTED", "").toLowerCase();
|
|
105729
106234
|
return new chunk_1.Chunk().appendString(pre + "INPUT && INPUT." + field + " === undefined && INPUT.importing?." + field + " === undefined");
|
|
105730
106235
|
}
|
|
105731
|
-
if (concat.includes(" IS INSTANCE OF ")) {
|
|
105732
|
-
const notted = concat.startsWith("NOT ")
|
|
106236
|
+
if (concat.includes(" IS INSTANCE OF ") || concat.includes(" IS NOT INSTANCE OF ")) {
|
|
106237
|
+
const notted = concat.startsWith("NOT ") !== concat.includes(" IS NOT INSTANCE OF ");
|
|
105733
106238
|
const falsed = notted ? " === false" : "";
|
|
105734
106239
|
const expr = node.findDirectExpression(core_1.Expressions.ClassName);
|
|
105735
106240
|
const cname = expr?.concatTokens();
|
|
105736
|
-
const lookup = traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
106241
|
+
const lookup = cname?.toUpperCase() === "OBJECT" ? '"OBJECT"' : traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
105737
106242
|
return new chunk_1.Chunk().appendString("abap.compare.instance_of(").appendChunk(s0).appendString(`, ${lookup})` + falsed);
|
|
105738
106243
|
}
|
|
105739
106244
|
}
|
|
@@ -111383,10 +111888,12 @@ const traversal_1 = __webpack_require__(/*! ../traversal */ "./node_modules/@aba
|
|
|
111383
111888
|
const requires_1 = __webpack_require__(/*! ../requires */ "./node_modules/@abaplint/transpiler/build/src/requires.js");
|
|
111384
111889
|
const rearranger_1 = __webpack_require__(/*! ../rearranger */ "./node_modules/@abaplint/transpiler/build/src/rearranger.js");
|
|
111385
111890
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
111386
|
-
const
|
|
111891
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111387
111892
|
class HandleABAP {
|
|
111893
|
+
layout;
|
|
111388
111894
|
options;
|
|
111389
|
-
constructor(options) {
|
|
111895
|
+
constructor(options, layout = new output_layout_1.OutputLayout()) {
|
|
111896
|
+
this.layout = layout;
|
|
111390
111897
|
this.options = options;
|
|
111391
111898
|
}
|
|
111392
111899
|
runObject(obj, reg) {
|
|
@@ -111487,11 +111994,12 @@ class HandleABAP {
|
|
|
111487
111994
|
if (filename === output.filename) {
|
|
111488
111995
|
continue;
|
|
111489
111996
|
}
|
|
111997
|
+
const specifier = (0, output_layout_1.importPath)(this.layout.file(output.object, output.filename), this.layout.sourceModule(r.filename));
|
|
111490
111998
|
if (name) {
|
|
111491
|
-
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"
|
|
111999
|
+
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"" + specifier + "\");\n");
|
|
111492
112000
|
}
|
|
111493
112001
|
else {
|
|
111494
|
-
contents.appendString("await import(\"
|
|
112002
|
+
contents.appendString("await import(\"" + specifier + "\");\n");
|
|
111495
112003
|
}
|
|
111496
112004
|
}
|
|
111497
112005
|
contents.appendChunk(output.chunk);
|
|
@@ -111819,7 +112327,13 @@ exports.HandleOA2P = HandleOA2P;
|
|
|
111819
112327
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
111820
112328
|
exports.HandleSMIM = void 0;
|
|
111821
112329
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112330
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111822
112331
|
class HandleSMIM {
|
|
112332
|
+
layout;
|
|
112333
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112334
|
+
this.layout = layout;
|
|
112335
|
+
// Asset paths are relative to the output root.
|
|
112336
|
+
}
|
|
111823
112337
|
runObject(obj, _reg) {
|
|
111824
112338
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
111825
112339
|
if (filename === undefined) {
|
|
@@ -111827,9 +112341,10 @@ class HandleSMIM {
|
|
|
111827
112341
|
}
|
|
111828
112342
|
obj.parse();
|
|
111829
112343
|
const dataFile = obj.getDataFile();
|
|
112344
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
111830
112345
|
const chunk = new chunk_1.Chunk().appendString(`abap.SMIM["${obj.getName().toUpperCase()}"] = {
|
|
111831
112346
|
"objectType": "SMIM",
|
|
111832
|
-
"filename": ${JSON.stringify(
|
|
112347
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
111833
112348
|
"url": ${JSON.stringify(obj.getURL())},
|
|
111834
112349
|
"class": ${JSON.stringify(obj.getClass())},
|
|
111835
112350
|
};`);
|
|
@@ -112102,8 +112617,14 @@ exports.HandleView = HandleView;
|
|
|
112102
112617
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112103
112618
|
exports.HandleW3MI = void 0;
|
|
112104
112619
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112620
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112105
112621
|
const w3mi_name_1 = __webpack_require__(/*! ../w3mi_name */ "./node_modules/@abaplint/transpiler/build/src/w3mi_name.js");
|
|
112106
112622
|
class HandleW3MI {
|
|
112623
|
+
layout;
|
|
112624
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112625
|
+
this.layout = layout;
|
|
112626
|
+
// Asset paths are relative to the output root.
|
|
112627
|
+
}
|
|
112107
112628
|
runObject(obj, _reg) {
|
|
112108
112629
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
112109
112630
|
if (filename === undefined) {
|
|
@@ -112111,9 +112632,10 @@ class HandleW3MI {
|
|
|
112111
112632
|
}
|
|
112112
112633
|
obj.parse();
|
|
112113
112634
|
const dataFile = obj.getDataFile();
|
|
112635
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
112114
112636
|
const chunk = new chunk_1.Chunk().appendString(`abap.W3MI["${(0, w3mi_name_1.w3miObjectName)(obj)}"] = {
|
|
112115
112637
|
"objectType": "W3MI",
|
|
112116
|
-
"filename": ${JSON.stringify(
|
|
112638
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
112117
112639
|
};`);
|
|
112118
112640
|
const output = {
|
|
112119
112641
|
object: {
|
|
@@ -112189,7 +112711,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
112189
112711
|
};
|
|
112190
112712
|
})();
|
|
112191
112713
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112192
|
-
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = void 0;
|
|
112714
|
+
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = exports.importPath = exports.OutputLayout = void 0;
|
|
112193
112715
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112194
112716
|
const validation_1 = __webpack_require__(/*! ./validation */ "./node_modules/@abaplint/transpiler/build/src/validation.js");
|
|
112195
112717
|
Object.defineProperty(exports, "config", ({ enumerable: true, get: function () { return validation_1.config; } }));
|
|
@@ -112213,12 +112735,14 @@ const handle_msag_1 = __webpack_require__(/*! ./handlers/handle_msag */ "./node_
|
|
|
112213
112735
|
const handle_oa2p_1 = __webpack_require__(/*! ./handlers/handle_oa2p */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_oa2p.js");
|
|
112214
112736
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112215
112737
|
const initialization_1 = __webpack_require__(/*! ./initialization */ "./node_modules/@abaplint/transpiler/build/src/initialization.js");
|
|
112738
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112739
|
+
var output_layout_2 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112740
|
+
Object.defineProperty(exports, "OutputLayout", ({ enumerable: true, get: function () { return output_layout_2.OutputLayout; } }));
|
|
112741
|
+
Object.defineProperty(exports, "importPath", ({ enumerable: true, get: function () { return output_layout_2.importPath; } }));
|
|
112216
112742
|
class Transpiler {
|
|
112217
112743
|
options;
|
|
112218
|
-
|
|
112219
|
-
constructor(options, plugin) {
|
|
112744
|
+
constructor(options) {
|
|
112220
112745
|
this.options = options;
|
|
112221
|
-
this.plugin = plugin;
|
|
112222
112746
|
if (this.options === undefined) {
|
|
112223
112747
|
this.options = {};
|
|
112224
112748
|
}
|
|
@@ -112232,23 +112756,22 @@ class Transpiler {
|
|
|
112232
112756
|
const reg = new abaplint.Registry().addFiles(memory);
|
|
112233
112757
|
return this.run(reg);
|
|
112234
112758
|
}
|
|
112235
|
-
async run(reg, progress) {
|
|
112759
|
+
async run(reg, progress, folders) {
|
|
112236
112760
|
// Validation installs the transpiler configuration and findIssues() parses
|
|
112237
112761
|
// dirty registries. Parsing before that would be wasted because setConfig()
|
|
112238
112762
|
// marks every registry object dirty again.
|
|
112239
112763
|
this.validate(reg);
|
|
112764
|
+
const layout = new output_layout_1.OutputLayout(reg, folders);
|
|
112240
112765
|
const dbSetup = new db_1.DatabaseSetup(reg).run(this.options);
|
|
112241
|
-
this.plugin?.amendDatabaseSetup?.(dbSetup, reg, this.options || {});
|
|
112242
112766
|
const output = {
|
|
112243
112767
|
objects: [],
|
|
112244
|
-
unitTestScript: new unit_test_1.UnitTest().unitTestScript(reg, this.options?.skip),
|
|
112245
|
-
unitTestScriptOpen: new unit_test_1.UnitTest().unitTestScriptOpen(reg, this.options?.skip),
|
|
112768
|
+
unitTestScript: new unit_test_1.UnitTest(layout).unitTestScript(reg, this.options?.skip),
|
|
112769
|
+
unitTestScriptOpen: new unit_test_1.UnitTest(layout).unitTestScriptOpen(reg, this.options?.skip),
|
|
112246
112770
|
initializationScript: "",
|
|
112247
112771
|
initializationScript2: "",
|
|
112248
112772
|
databaseSetup: dbSetup,
|
|
112249
112773
|
reg: reg,
|
|
112250
112774
|
};
|
|
112251
|
-
const pluginOutputs = [];
|
|
112252
112775
|
progress?.set(reg.getObjectCount().total, "Building");
|
|
112253
112776
|
for (const obj of reg.getObjects()) {
|
|
112254
112777
|
await progress?.tick("Building, " + obj.getName());
|
|
@@ -112265,7 +112788,7 @@ class Transpiler {
|
|
|
112265
112788
|
output.objects.push(...new handle_fugr_1.HandleFUGR(this.options).runObject(obj, reg));
|
|
112266
112789
|
}
|
|
112267
112790
|
else if (obj instanceof abaplint.ABAPObject) {
|
|
112268
|
-
output.objects.push(...new handle_abap_1.HandleABAP(this.options).runObject(obj, reg));
|
|
112791
|
+
output.objects.push(...new handle_abap_1.HandleABAP(this.options, layout).runObject(obj, reg));
|
|
112269
112792
|
}
|
|
112270
112793
|
else if (obj instanceof abaplint.Objects.Oauth2Profile) {
|
|
112271
112794
|
output.objects.push(...new handle_oa2p_1.HandleOA2P().runObject(obj, reg));
|
|
@@ -112286,30 +112809,25 @@ class Transpiler {
|
|
|
112286
112809
|
output.objects.push(...new handle_table_type_1.HandleTableType().runObject(obj, reg));
|
|
112287
112810
|
}
|
|
112288
112811
|
else if (obj instanceof abaplint.Objects.MIMEObject) {
|
|
112289
|
-
output.objects.push(...new handle_smim_1.HandleSMIM().runObject(obj, reg));
|
|
112812
|
+
output.objects.push(...new handle_smim_1.HandleSMIM(layout).runObject(obj, reg));
|
|
112290
112813
|
}
|
|
112291
112814
|
else if (obj instanceof abaplint.Objects.WebMIME) {
|
|
112292
|
-
output.objects.push(...new handle_w3mi_1.HandleW3MI().runObject(obj, reg));
|
|
112815
|
+
output.objects.push(...new handle_w3mi_1.HandleW3MI(layout).runObject(obj, reg));
|
|
112293
112816
|
}
|
|
112294
112817
|
else if (obj instanceof abaplint.Objects.MessageClass) {
|
|
112295
112818
|
output.objects.push(...new handle_msag_1.HandleMSAG().runObject(obj, reg));
|
|
112296
112819
|
}
|
|
112297
|
-
else if (this.plugin !== undefined) {
|
|
112298
|
-
const handled = this.plugin.handleObject(obj, reg, this.options || {});
|
|
112299
|
-
if (handled !== undefined) {
|
|
112300
|
-
output.objects.push(...handled);
|
|
112301
|
-
pluginOutputs.push(...handled);
|
|
112302
|
-
}
|
|
112303
|
-
}
|
|
112304
112820
|
}
|
|
112305
|
-
|
|
112306
|
-
output.
|
|
112307
|
-
|
|
112821
|
+
output.initializationScript = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, false);
|
|
112822
|
+
output.initializationScript2 = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, true);
|
|
112823
|
+
for (const file of output.objects) {
|
|
112824
|
+
file.filename = layout.file(file.object, file.filename);
|
|
112825
|
+
}
|
|
112308
112826
|
return output;
|
|
112309
112827
|
}
|
|
112310
112828
|
// ///////////////////////////////
|
|
112311
112829
|
validate(reg) {
|
|
112312
|
-
const issues = new validation_1.Validation(this.options
|
|
112830
|
+
const issues = new validation_1.Validation(this.options).run(reg);
|
|
112313
112831
|
if (issues.length > 0) {
|
|
112314
112832
|
const messages = issues.map(i => i.getKey() + ", " +
|
|
112315
112833
|
i.getMessage() + ", " +
|
|
@@ -112371,6 +112889,7 @@ exports.escapeNamespaceFilename = escapeNamespaceFilename;
|
|
|
112371
112889
|
exports.escapeFilenameForImport = escapeFilenameForImport;
|
|
112372
112890
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112373
112891
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112892
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112374
112893
|
function escapeNamespaceFilename(filename) {
|
|
112375
112894
|
// ES modules are resolved and cached as URLs. This means that special characters must be
|
|
112376
112895
|
// percent-encoded, such as # with %23 and ? with %3F.
|
|
@@ -112388,7 +112907,12 @@ function escapeFilenameForImport(filename) {
|
|
|
112388
112907
|
return filename.replace(/%/g, "%25").replace(/#/g, "%23");
|
|
112389
112908
|
}
|
|
112390
112909
|
class Initialization {
|
|
112391
|
-
|
|
112910
|
+
layout;
|
|
112911
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112912
|
+
this.layout = layout;
|
|
112913
|
+
// Flat output unless the caller supplies ownership information.
|
|
112914
|
+
}
|
|
112915
|
+
script(reg, dbSetup, options, useImport) {
|
|
112392
112916
|
let ret = "";
|
|
112393
112917
|
if (useImport === true) {
|
|
112394
112918
|
ret = `/* eslint-disable import/newline-after-import */
|
|
@@ -112431,28 +112955,24 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112431
112955
|
}
|
|
112432
112956
|
ret += `}\n\n`;
|
|
112433
112957
|
ret += `await initializeABAP();\n\n`;
|
|
112434
|
-
ret += `${this.buildImports(reg, useImport, options
|
|
112958
|
+
ret += `${this.buildImports(reg, useImport, options)}`;
|
|
112435
112959
|
if (options?.setup?.postFunction !== undefined) {
|
|
112436
112960
|
ret += `\n\nawait setup.${options?.setup?.postFunction}();\n`;
|
|
112437
112961
|
}
|
|
112438
112962
|
return ret;
|
|
112439
112963
|
}
|
|
112440
|
-
buildImports(reg, useImport, options
|
|
112964
|
+
buildImports(reg, useImport, options) {
|
|
112441
112965
|
// note: ES modules are hoised, so use the dynamic import(), due to setting of globalThis.abap
|
|
112442
112966
|
// some sorting required: eg. a class constructor using constant from interface
|
|
112443
112967
|
const list = [];
|
|
112444
112968
|
const late = [];
|
|
112445
112969
|
const imp = (filename) => {
|
|
112446
|
-
|
|
112447
|
-
|
|
112448
|
-
|
|
112449
|
-
|
|
112450
|
-
|
|
112451
|
-
}
|
|
112970
|
+
const specifier = (0, output_layout_1.importPath)("init.mjs", filename);
|
|
112971
|
+
return {
|
|
112972
|
+
filename: specifier.split("/").pop(),
|
|
112973
|
+
code: useImport === true ? `import "${specifier}";` : `await import("${specifier}");`,
|
|
112974
|
+
};
|
|
112452
112975
|
};
|
|
112453
|
-
for (const pluginOutput of pluginOutputs || []) {
|
|
112454
|
-
list.push(imp(pluginOutput.filename.replace(/\.mjs$/i, "")));
|
|
112455
|
-
}
|
|
112456
112976
|
for (const obj of reg.getObjects()) {
|
|
112457
112977
|
if (obj instanceof abaplint.Objects.Table
|
|
112458
112978
|
|| obj instanceof abaplint.Objects.DataElement
|
|
@@ -112464,11 +112984,11 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112464
112984
|
|| obj instanceof abaplint.Objects.TypePool
|
|
112465
112985
|
|| obj instanceof abaplint.Objects.TableType
|
|
112466
112986
|
|| obj instanceof abaplint.Objects.View) {
|
|
112467
|
-
list.push(imp(
|
|
112987
|
+
list.push(imp(this.layout.objectModule(obj)));
|
|
112468
112988
|
}
|
|
112469
112989
|
}
|
|
112470
112990
|
for (const obj of reg.getObjects()) {
|
|
112471
|
-
const name = imp(
|
|
112991
|
+
const name = imp(this.layout.objectModule(obj));
|
|
112472
112992
|
if (obj instanceof abaplint.Objects.Class
|
|
112473
112993
|
&& obj.getName().toUpperCase() !== "CL_ABAP_CHAR_UTILITIES"
|
|
112474
112994
|
&& this.hasClassConstructor(reg, obj)) {
|
|
@@ -112488,7 +113008,9 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112488
113008
|
list.push(name);
|
|
112489
113009
|
}
|
|
112490
113010
|
}
|
|
112491
|
-
|
|
113011
|
+
// Folder names must not change the original module initialization order.
|
|
113012
|
+
list.sort((a, b) => a.filename < b.filename ? -1 : a.filename > b.filename ? 1 : 0);
|
|
113013
|
+
return [...list, ...late].map(entry => entry.code).join("\n");
|
|
112492
113014
|
}
|
|
112493
113015
|
// class constructors might make early use of eg. constants from interfaces
|
|
112494
113016
|
// sub classes will import() super classes and trigger a class constructor of the super
|
|
@@ -112640,6 +113162,89 @@ exports.DEFAULT_KEYWORDS = new Set([
|
|
|
112640
113162
|
|
|
112641
113163
|
/***/ },
|
|
112642
113164
|
|
|
113165
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/output_layout.js"
|
|
113166
|
+
/*!**********************************************************************!*\
|
|
113167
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/output_layout.js ***!
|
|
113168
|
+
\**********************************************************************/
|
|
113169
|
+
(__unused_webpack_module, exports) {
|
|
113170
|
+
|
|
113171
|
+
"use strict";
|
|
113172
|
+
|
|
113173
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
113174
|
+
exports.OutputLayout = void 0;
|
|
113175
|
+
exports.importPath = importPath;
|
|
113176
|
+
/** Browser-safe paths: generated modules use POSIX paths on every platform. */
|
|
113177
|
+
class OutputLayout {
|
|
113178
|
+
grouped;
|
|
113179
|
+
objectFolders = new Map();
|
|
113180
|
+
sourceFolders = new Map();
|
|
113181
|
+
constructor(reg, folders) {
|
|
113182
|
+
this.grouped = folders !== undefined;
|
|
113183
|
+
if (folders === undefined) {
|
|
113184
|
+
return;
|
|
113185
|
+
}
|
|
113186
|
+
for (const [filename, folder] of folders) {
|
|
113187
|
+
this.sourceFolders.set(filename.toLowerCase(), folder);
|
|
113188
|
+
}
|
|
113189
|
+
for (const obj of reg?.getObjects() || []) {
|
|
113190
|
+
const owners = new Set(obj.getFiles().map(f => this.sourceFolders.get(f.getFilename().toLowerCase()))
|
|
113191
|
+
.filter((folder) => folder !== undefined));
|
|
113192
|
+
if (owners.size !== 1) {
|
|
113193
|
+
throw new Error("Ambiguous output ownership for " + obj.getType() + " " + obj.getName());
|
|
113194
|
+
}
|
|
113195
|
+
const folder = [...owners][0];
|
|
113196
|
+
this.objectFolders.set(this.key({ type: obj.getType(), name: obj.getName() }), folder);
|
|
113197
|
+
for (const file of obj.getFiles()) {
|
|
113198
|
+
// Class locals are merged into a single module.
|
|
113199
|
+
this.sourceFolders.set(file.getFilename().toLowerCase().replace(/\.locals_(def|imp)\.abap$/, ".locals.abap"), folder);
|
|
113200
|
+
}
|
|
113201
|
+
}
|
|
113202
|
+
}
|
|
113203
|
+
key(obj) {
|
|
113204
|
+
return obj.type.toUpperCase() + ":" + obj.name.toUpperCase();
|
|
113205
|
+
}
|
|
113206
|
+
file(obj, filename) {
|
|
113207
|
+
const folder = this.objectFolders.get(this.key(obj));
|
|
113208
|
+
if (this.grouped && folder === undefined) {
|
|
113209
|
+
throw new Error("Missing output ownership for " + obj.type + " " + obj.name);
|
|
113210
|
+
}
|
|
113211
|
+
if (folder !== undefined && (filename.startsWith("/") || /[\\:]/.test(filename)
|
|
113212
|
+
|| filename.split("/").some(segment => segment === "" || segment === "." || segment === ".."))) {
|
|
113213
|
+
throw new Error("Invalid output filename: " + filename);
|
|
113214
|
+
}
|
|
113215
|
+
return folder === undefined ? filename : folder + "/" + filename;
|
|
113216
|
+
}
|
|
113217
|
+
sourceModule(filename) {
|
|
113218
|
+
const folder = this.sourceFolders.get(filename.toLowerCase());
|
|
113219
|
+
if (this.grouped && folder === undefined) {
|
|
113220
|
+
throw new Error("Missing output ownership for source " + filename);
|
|
113221
|
+
}
|
|
113222
|
+
const module = filename.replace(/\.abap$/i, ".mjs").toLowerCase();
|
|
113223
|
+
return folder === undefined ? module : folder + "/" + module;
|
|
113224
|
+
}
|
|
113225
|
+
objectModule(obj, suffix = "") {
|
|
113226
|
+
const identifier = { name: obj.getName(), type: obj.getType() };
|
|
113227
|
+
const filename = obj.getName().toLowerCase().replace(/\//g, "#") + "." + obj.getType().toLowerCase() + suffix + ".mjs";
|
|
113228
|
+
return this.file(identifier, filename);
|
|
113229
|
+
}
|
|
113230
|
+
}
|
|
113231
|
+
exports.OutputLayout = OutputLayout;
|
|
113232
|
+
/** Escape each segment without turning directory separators into namespace markers. */
|
|
113233
|
+
function importPath(from, to) {
|
|
113234
|
+
const source = from.split("/").slice(0, -1);
|
|
113235
|
+
const target = to.split("/");
|
|
113236
|
+
while (source.length > 0 && target.length > 0 && source[0] === target[0]) {
|
|
113237
|
+
source.shift();
|
|
113238
|
+
target.shift();
|
|
113239
|
+
}
|
|
113240
|
+
const relative = [...source.map(() => ".."), ...target].join("/");
|
|
113241
|
+
const escaped = relative.split("/").map(segment => encodeURIComponent(segment)).join("/");
|
|
113242
|
+
return escaped.startsWith("../") ? escaped : "./" + escaped;
|
|
113243
|
+
}
|
|
113244
|
+
//# sourceMappingURL=output_layout.js.map
|
|
113245
|
+
|
|
113246
|
+
/***/ },
|
|
113247
|
+
|
|
112643
113248
|
/***/ "./node_modules/@abaplint/transpiler/build/src/rearranger.js"
|
|
112644
113249
|
/*!*******************************************************************!*\
|
|
112645
113250
|
!*** ./node_modules/@abaplint/transpiler/build/src/rearranger.js ***!
|
|
@@ -113502,6 +114107,22 @@ throw error;
|
|
|
113502
114107
|
}
|
|
113503
114108
|
})())`;
|
|
113504
114109
|
}
|
|
114110
|
+
/** ASSIGN of a statically specified data object, e.g. a variable, an attribute or an offset/length,
|
|
114111
|
+
* does not set sy-subrc, a dereference, a table expression or COMPONENT does */
|
|
114112
|
+
isStaticDataObject(node, source) {
|
|
114113
|
+
const concat = node.concatTokens().toUpperCase();
|
|
114114
|
+
if (source === undefined
|
|
114115
|
+
|| concat.startsWith("ASSIGN COMPONENT ")
|
|
114116
|
+
|| concat.includes(" INCREMENT ")
|
|
114117
|
+
|| concat.includes(" ELSE UNASSIGN")
|
|
114118
|
+
|| source.findFirstExpression(abaplint.Expressions.Dereference) !== undefined
|
|
114119
|
+
|| source.findFirstExpression(abaplint.Expressions.TableExpression) !== undefined) {
|
|
114120
|
+
return false;
|
|
114121
|
+
}
|
|
114122
|
+
// field symbols are left as they are, not measured
|
|
114123
|
+
const first = source.findFirstExpression(abaplint.Expressions.FieldChain)?.getFirstChild();
|
|
114124
|
+
return first !== undefined && !(first.get() instanceof abaplint.Expressions.SourceFieldSymbol);
|
|
114125
|
+
}
|
|
113505
114126
|
transpile(node, traversal) {
|
|
113506
114127
|
const assignSource = node.findDirectExpression(abaplint.Expressions.AssignSource);
|
|
113507
114128
|
const sourceExpressions = assignSource?.findDirectExpressionsMulti([abaplint.Expressions.Source, abaplint.Expressions.SimpleSource3]) || [];
|
|
@@ -113541,6 +114162,9 @@ throw error;
|
|
|
113541
114162
|
}
|
|
113542
114163
|
else {
|
|
113543
114164
|
options.push("source: " + sources.pop());
|
|
114165
|
+
if (this.isStaticDataObject(node, sourceExprForCheck)) {
|
|
114166
|
+
options.push("keepSubrc: true");
|
|
114167
|
+
}
|
|
113544
114168
|
}
|
|
113545
114169
|
}
|
|
113546
114170
|
else {
|
|
@@ -114572,7 +115196,7 @@ static INTERNAL_TYPE = 'CLAS';
|
|
|
114572
115196
|
static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';
|
|
114573
115197
|
static IMPLEMENTED_INTERFACES = [${this.findImplementedByClass(traversal, def, scope).map(e => `"` + e.toUpperCase() + `"`).join(",")}];
|
|
114574
115198
|
static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};
|
|
114575
|
-
static METHODS = {${traversal.buildMethods(def).join(",\n")}};`, node, traversal);
|
|
115199
|
+
static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};`, node, traversal);
|
|
114576
115200
|
}
|
|
114577
115201
|
findImplementedInterface(traversal, def, scope) {
|
|
114578
115202
|
if (def === undefined || scope === undefined) {
|
|
@@ -118964,6 +119588,16 @@ class MethodImplementationTranspiler {
|
|
|
118964
119588
|
else {
|
|
118965
119589
|
after += `let ${varPrefixed} = ${unique}?.${varName};\n`;
|
|
118966
119590
|
}
|
|
119591
|
+
if (passByValue === true) {
|
|
119592
|
+
// pass by value: the method works on its own copy, also for a generic type,
|
|
119593
|
+
// which keeps the type of the actual parameter.
|
|
119594
|
+
// A field symbol that is unassigned or assigned with CASTING is passed on as it is
|
|
119595
|
+
after += `if (${varPrefixed} instanceof abap.types.FieldSymbol) {
|
|
119596
|
+
if (${varPrefixed}.getPointer()?.clone !== undefined) { ${varPrefixed} = ${varPrefixed}.getPointer().clone(); }
|
|
119597
|
+
} else if (${unique}?.${varName} !== undefined && ${varPrefixed}?.clone !== undefined) {
|
|
119598
|
+
${varPrefixed} = ${varPrefixed}.clone();
|
|
119599
|
+
}\n`;
|
|
119600
|
+
}
|
|
118967
119601
|
if (type instanceof abaplint.BasicTypes.NumericGenericType) {
|
|
118968
119602
|
after += `if (${varPrefixed}.constructor.name === "Character") {
|
|
118969
119603
|
${varPrefixed} = ${transpile_types_1.TranspileTypes.toType(identifier.getType())};
|
|
@@ -121516,10 +122150,10 @@ abap.builtin.sy.get().dbcnt.set(${target}.getArrayLength());
|
|
|
121516
122150
|
+ ` : (("" + ${code}.get()).trim() === "" ? "" : "${keyword} " + ${code}.get()))`;
|
|
121517
122151
|
}
|
|
121518
122152
|
dynamicHavingClause(code) {
|
|
121519
|
-
return `((value) => {
|
|
121520
|
-
const condition = value instanceof abap.types.Table || value instanceof abap.types.HashedTable
|
|
121521
|
-
? value.array().map(row => row.get()).join(" ") : value.get();
|
|
121522
|
-
return condition.trim() === "" ? "" : "HAVING " + abap.expandDynamic(condition, (name) => {try { return eval(name);} catch {}});
|
|
122153
|
+
return `((value) => {
|
|
122154
|
+
const condition = value instanceof abap.types.Table || value instanceof abap.types.HashedTable
|
|
122155
|
+
? value.array().map(row => row.get()).join(" ") : value.get();
|
|
122156
|
+
return condition.trim() === "" ? "" : "HAVING " + abap.expandDynamic(condition, (name) => {try { return eval(name);} catch {}});
|
|
121523
122157
|
})(${code})`;
|
|
121524
122158
|
}
|
|
121525
122159
|
isWhereExpression(node, expression) {
|
|
@@ -124762,8 +125396,11 @@ class InterfaceTranspiler {
|
|
|
124762
125396
|
ret += `static INTERNAL_TYPE = 'INTF';\n`;
|
|
124763
125397
|
ret += `static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';\n`;
|
|
124764
125398
|
ret += `static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};\n`;
|
|
124765
|
-
ret += `static METHODS = {${traversal.buildMethods(def).join(",\n")}};\n`;
|
|
124766
|
-
|
|
125399
|
+
ret += `static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};\n`;
|
|
125400
|
+
const interfaces = def?.getImplementing().map(i => `"${i.name.toUpperCase()}"`) || [];
|
|
125401
|
+
if (interfaces.length > 0) {
|
|
125402
|
+
ret += `static IMPLEMENTED_INTERFACES = [${interfaces.join(",")}];\n`;
|
|
125403
|
+
}
|
|
124767
125404
|
}
|
|
124768
125405
|
else if (c instanceof abaplint.Nodes.StatementNode && c.get() instanceof abaplint.Statements.EndInterface) {
|
|
124769
125406
|
ret += "}\n";
|
|
@@ -125558,8 +126195,22 @@ class TranspileTypes {
|
|
|
125558
126195
|
if (type instanceof abaplint.BasicTypes.ObjectReferenceType
|
|
125559
126196
|
|| type instanceof abaplint.BasicTypes.GenericObjectReferenceType) {
|
|
125560
126197
|
resolved = "ABAPObject";
|
|
125561
|
-
|
|
125562
|
-
|
|
126198
|
+
const qualifiedName = type.getQualifiedName()
|
|
126199
|
+
?? (type instanceof abaplint.BasicTypes.ObjectReferenceType ? type.getIdentifierName() : undefined);
|
|
126200
|
+
let RTTIName = type.getRTTIName();
|
|
126201
|
+
if (type instanceof abaplint.BasicTypes.ObjectReferenceType && RTTIName === undefined) {
|
|
126202
|
+
const id = type.getIdentifier();
|
|
126203
|
+
// NEW and CAST can omit metadata; recover it from the referenced definition.
|
|
126204
|
+
const [name, kind] = id.getFilename().split("/").pop().replace(/#/g, "/").split(".");
|
|
126205
|
+
const local = (id instanceof abaplint.Types.ClassDefinition || id instanceof abaplint.Types.InterfaceDefinition)
|
|
126206
|
+
&& id.isGlobal() === false;
|
|
126207
|
+
const prefix = local && kind === "prog" ? "\\PROGRAM=" + name
|
|
126208
|
+
: local && kind === "clas" ? "\\CLASS-POOL=" + name : "";
|
|
126209
|
+
const category = id instanceof abaplint.Types.InterfaceDefinition || kind === "intf" ? "INTERFACE" : "CLASS";
|
|
126210
|
+
RTTIName = prefix + "\\" + category + "=" + id.getName();
|
|
126211
|
+
}
|
|
126212
|
+
extra = "{qualifiedName: " + JSON.stringify(qualifiedName?.toUpperCase()) +
|
|
126213
|
+
", RTTIName: " + JSON.stringify(RTTIName?.toUpperCase()) + "}";
|
|
125563
126214
|
}
|
|
125564
126215
|
else if (type instanceof abaplint.BasicTypes.TableType) {
|
|
125565
126216
|
resolved = "Table";
|
|
@@ -125687,6 +126338,11 @@ class TranspileTypes {
|
|
|
125687
126338
|
resolved = "Packed";
|
|
125688
126339
|
extra = "{length: 8, decimals: 2}";
|
|
125689
126340
|
}
|
|
126341
|
+
else if (type instanceof abaplint.BasicTypes.PGenericType) {
|
|
126342
|
+
// if not supplied its a P LENGTH 8 DECIMALS 0
|
|
126343
|
+
resolved = "Packed";
|
|
126344
|
+
extra = "{length: 8, decimals: 0}";
|
|
126345
|
+
}
|
|
125690
126346
|
else if (type instanceof abaplint.BasicTypes.XStringType) {
|
|
125691
126347
|
resolved = "XString";
|
|
125692
126348
|
if (type.getQualifiedName() !== undefined) {
|
|
@@ -126112,7 +126768,7 @@ class Traversal {
|
|
|
126112
126768
|
}
|
|
126113
126769
|
return undefined;
|
|
126114
126770
|
}
|
|
126115
|
-
buildMethods(def) {
|
|
126771
|
+
buildMethods(def, scope) {
|
|
126116
126772
|
const methods = [];
|
|
126117
126773
|
if (def === undefined) {
|
|
126118
126774
|
return methods;
|
|
@@ -126123,29 +126779,57 @@ class Traversal {
|
|
|
126123
126779
|
throw new Error("buildMethods: unexpected undefined, " + def.getName());
|
|
126124
126780
|
}
|
|
126125
126781
|
for (const m of methodDefinitions.getAll()) {
|
|
126126
|
-
|
|
126127
|
-
|
|
126128
|
-
|
|
126129
|
-
|
|
126130
|
-
|
|
126131
|
-
|
|
126132
|
-
|
|
126133
|
-
|
|
126134
|
-
|
|
126135
|
-
|
|
126136
|
-
|
|
126137
|
-
|
|
126138
|
-
pKind = m.getParameters().getExporting().find((t) => { return t.getName() === p.getName(); }) ? "E" : "";
|
|
126139
|
-
}
|
|
126140
|
-
if (pKind === "") {
|
|
126141
|
-
pKind = m.getParameters().getReturning()?.getName() === p.getName() ? "R" : "";
|
|
126142
|
-
}
|
|
126143
|
-
parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}", "parm_kind": "${pKind}", "type_name": "${p.getType().constructor.name}"}`);
|
|
126782
|
+
methods.push(this.buildMethod(m.getName(), m, m.getVisibility()));
|
|
126783
|
+
}
|
|
126784
|
+
// an alias for an interface method is listed under its own name, pointing to the method
|
|
126785
|
+
for (const a of def.getAliases() || []) {
|
|
126786
|
+
const [intfName, methodName] = a.getComponent().split("~");
|
|
126787
|
+
if (methodName === undefined) {
|
|
126788
|
+
continue;
|
|
126789
|
+
}
|
|
126790
|
+
const aliased = this.findInterfaceDefinition(intfName, scope)?.getMethodDefinitions()?.getByName(methodName);
|
|
126791
|
+
if (aliased === undefined) {
|
|
126792
|
+
// not a method, or the interface is unknown
|
|
126793
|
+
continue;
|
|
126144
126794
|
}
|
|
126145
|
-
methods.push(
|
|
126795
|
+
methods.push(this.buildMethod(a.getName(), aliased, a.getVisibility(), a.getComponent()));
|
|
126146
126796
|
}
|
|
126147
126797
|
return methods;
|
|
126148
126798
|
}
|
|
126799
|
+
buildMethod(name, m, visibility, aliasFor) {
|
|
126800
|
+
const optionalNames = m.getParameters().getOptional().map(o => o.toUpperCase());
|
|
126801
|
+
const parameters = [];
|
|
126802
|
+
for (const p of m.getParameters().getAll()) {
|
|
126803
|
+
const type = transpile_types_1.TranspileTypes.toType(p.getType());
|
|
126804
|
+
const optional = optionalNames.includes(p.getName().toUpperCase()) ? "X" : " ";
|
|
126805
|
+
let pKind = "";
|
|
126806
|
+
if (pKind === "") {
|
|
126807
|
+
pKind = m.getParameters().getImporting().find((t) => { return t.getName() === p.getName(); }) ? "I" : "";
|
|
126808
|
+
}
|
|
126809
|
+
if (pKind === "") {
|
|
126810
|
+
pKind = m.getParameters().getChanging().find((t) => { return t.getName() === p.getName(); }) ? "C" : "";
|
|
126811
|
+
}
|
|
126812
|
+
if (pKind === "") {
|
|
126813
|
+
pKind = m.getParameters().getExporting().find((t) => { return t.getName() === p.getName(); }) ? "E" : "";
|
|
126814
|
+
}
|
|
126815
|
+
if (pKind === "") {
|
|
126816
|
+
pKind = m.getParameters().getReturning()?.getName() === p.getName() ? "R" : "";
|
|
126817
|
+
}
|
|
126818
|
+
parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}", "parm_kind": "${pKind}", "type_name": "${p.getType().constructor.name}"}`);
|
|
126819
|
+
}
|
|
126820
|
+
// only written when set, a method without them is described as before
|
|
126821
|
+
let extra = "";
|
|
126822
|
+
if (m.isStatic() === true) {
|
|
126823
|
+
extra += `"is_class": "X", `;
|
|
126824
|
+
}
|
|
126825
|
+
if (m.getRaising().length > 0) {
|
|
126826
|
+
extra += `"exceptions": [${m.getRaising().map(e => `"${e.toUpperCase()}"`).join(", ")}], `;
|
|
126827
|
+
}
|
|
126828
|
+
if (aliasFor !== undefined) {
|
|
126829
|
+
extra += `"alias_for": "${aliasFor.toUpperCase()}", `;
|
|
126830
|
+
}
|
|
126831
|
+
return `"${name.toUpperCase()}": {"visibility": "${this.mapVisibility(visibility)}", ${extra}"parameters": {${parameters.join(", ")}}}`;
|
|
126832
|
+
}
|
|
126149
126833
|
mapVisibility(vis) {
|
|
126150
126834
|
switch (vis) {
|
|
126151
126835
|
case abaplint.Visibility.Private:
|
|
@@ -127039,8 +127723,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
127039
127723
|
exports.UnitTest = void 0;
|
|
127040
127724
|
/* eslint-disable max-len */
|
|
127041
127725
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
127042
|
-
const
|
|
127726
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
127043
127727
|
class UnitTest {
|
|
127728
|
+
layout;
|
|
127729
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
127730
|
+
this.layout = layout;
|
|
127731
|
+
// Test runners live at the output root.
|
|
127732
|
+
}
|
|
127044
127733
|
unitTestScriptOpen(reg, _skip) {
|
|
127045
127734
|
let ret = `/* eslint-disable curly */
|
|
127046
127735
|
import fs from "fs";
|
|
@@ -127061,7 +127750,7 @@ async function run() {
|
|
|
127061
127750
|
}
|
|
127062
127751
|
const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
|
|
127063
127752
|
if (hasTestFile === true) {
|
|
127064
|
-
ret += ` await import("
|
|
127753
|
+
ret += ` await import("${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}");\n`;
|
|
127065
127754
|
}
|
|
127066
127755
|
for (const file of obj.getABAPFiles()) {
|
|
127067
127756
|
for (const def of file.getInfo().listClassDefinitions()) {
|
|
@@ -127123,7 +127812,7 @@ run().then(() => {
|
|
|
127123
127812
|
}
|
|
127124
127813
|
tests.push({
|
|
127125
127814
|
obj,
|
|
127126
|
-
filename:
|
|
127815
|
+
filename: `${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}`,
|
|
127127
127816
|
localClass: def.name.toLowerCase(),
|
|
127128
127817
|
riskLevel: def.riskLevel,
|
|
127129
127818
|
duration: def.duration,
|
|
@@ -127268,8 +127957,12 @@ const core_1 = __webpack_require__(/*! @abaplint/core */ "./node_modules/@abapli
|
|
|
127268
127957
|
const types_1 = __webpack_require__(/*! ./types */ "./node_modules/@abaplint/transpiler/build/src/types.js");
|
|
127269
127958
|
const defaultAllowedObjectTypes = [
|
|
127270
127959
|
"APIS",
|
|
127960
|
+
"APLO",
|
|
127271
127961
|
"AUTH",
|
|
127962
|
+
"BDEF",
|
|
127272
127963
|
"CLAS",
|
|
127964
|
+
"DDLS",
|
|
127965
|
+
"DDLX",
|
|
127273
127966
|
"DEVC",
|
|
127274
127967
|
"DOMA",
|
|
127275
127968
|
"DTEL",
|
|
@@ -127291,13 +127984,19 @@ const defaultAllowedObjectTypes = [
|
|
|
127291
127984
|
"PARA",
|
|
127292
127985
|
"PINF",
|
|
127293
127986
|
"PROG",
|
|
127987
|
+
"SAJC",
|
|
127988
|
+
"SAJT",
|
|
127989
|
+
"SCO2",
|
|
127294
127990
|
"WAPA",
|
|
127295
127991
|
"SHLP",
|
|
127296
127992
|
"SHMA",
|
|
127993
|
+
"SIA6",
|
|
127297
127994
|
"SICF",
|
|
127298
127995
|
"SMIM",
|
|
127299
127996
|
"SPLO",
|
|
127300
127997
|
"SRFC",
|
|
127998
|
+
"SRVB",
|
|
127999
|
+
"SRVD",
|
|
127301
128000
|
"SUSC",
|
|
127302
128001
|
"SUSH",
|
|
127303
128002
|
"SUSO",
|
|
@@ -127373,10 +128072,8 @@ exports.config = {
|
|
|
127373
128072
|
// hmm this ^ is okay? since lines will be prefixed with "abap.builtin"?
|
|
127374
128073
|
class Validation {
|
|
127375
128074
|
options;
|
|
127376
|
-
|
|
127377
|
-
constructor(options, plugin) {
|
|
128075
|
+
constructor(options) {
|
|
127378
128076
|
this.options = options;
|
|
127379
|
-
this.plugin = plugin;
|
|
127380
128077
|
}
|
|
127381
128078
|
run(reg) {
|
|
127382
128079
|
if (this.options?.ignoreSyntaxCheck === true) {
|
|
@@ -127386,13 +128083,6 @@ class Validation {
|
|
|
127386
128083
|
exports.config.rules.check_syntax = true;
|
|
127387
128084
|
}
|
|
127388
128085
|
exports.config.rules.forbidden_identifier.check = ["^unique\\d+$"];
|
|
127389
|
-
const allowed = [...defaultAllowedObjectTypes];
|
|
127390
|
-
for (const type of this.plugin?.objectTypes() || []) {
|
|
127391
|
-
if (allowed.includes(type.toUpperCase()) === false) {
|
|
127392
|
-
allowed.push(type.toUpperCase());
|
|
127393
|
-
}
|
|
127394
|
-
}
|
|
127395
|
-
exports.config.rules.allowed_object_types.allowed = allowed;
|
|
127396
128086
|
if (this.options?.unknownTypes === types_1.UnknownTypesEnum.runtimeError) {
|
|
127397
128087
|
// this is not a constant, just a regex that happens to not match anything
|
|
127398
128088
|
exports.config.syntax.errorNamespace = "VOID_EVERYTHING";
|
|
@@ -130878,17 +131568,6 @@ module.exports = require("fs");
|
|
|
130878
131568
|
|
|
130879
131569
|
/***/ },
|
|
130880
131570
|
|
|
130881
|
-
/***/ "module"
|
|
130882
|
-
/*!*************************!*\
|
|
130883
|
-
!*** external "module" ***!
|
|
130884
|
-
\*************************/
|
|
130885
|
-
(module) {
|
|
130886
|
-
|
|
130887
|
-
"use strict";
|
|
130888
|
-
module.exports = require("module");
|
|
130889
|
-
|
|
130890
|
-
/***/ },
|
|
130891
|
-
|
|
130892
131571
|
/***/ "node:events"
|
|
130893
131572
|
/*!******************************!*\
|
|
130894
131573
|
!*** external "node:events" ***!
|